diff --git a/src/Compilers/CSharp/Portable/CodeGen/CodeGenerator.cs b/src/Compilers/CSharp/Portable/CodeGen/CodeGenerator.cs index f0cb89cac6f72..340ff9f77bf08 100644 --- a/src/Compilers/CSharp/Portable/CodeGen/CodeGenerator.cs +++ b/src/Compilers/CSharp/Portable/CodeGen/CodeGenerator.cs @@ -29,7 +29,7 @@ internal sealed partial class CodeGenerator private readonly BoundStatement _boundBody; private readonly ILBuilder _builder; private readonly PEModuleBuilder _module; - private readonly DiagnosticBag _diagnostics; + private readonly BindingDiagnosticBag _diagnostics; private readonly ILEmitStyle _ilEmitStyle; private readonly bool _emitPdbSequencePoints; @@ -85,7 +85,7 @@ public CodeGenerator( BoundStatement boundBody, ILBuilder builder, PEModuleBuilder moduleBuilder, - DiagnosticBag diagnostics, + BindingDiagnosticBag diagnostics, OptimizationLevel optimizations, bool emittingPdb) { @@ -94,6 +94,7 @@ public CodeGenerator( Debug.Assert(builder != null); Debug.Assert(moduleBuilder != null); Debug.Assert(diagnostics != null); + Debug.Assert(diagnostics.DiagnosticBag != null); _method = method; _boundBody = boundBody; @@ -177,7 +178,7 @@ private LocalDefinition LazyReturnTemp var localSymbol = new SynthesizedLocal(_method, _method.ReturnTypeWithAnnotations, SynthesizedLocalKind.FunctionReturnValue, bodySyntax); result = _builder.LocalSlotManager.DeclareLocal( - type: _module.Translate(localSymbol.Type, bodySyntax, _diagnostics), + type: _module.Translate(localSymbol.Type, bodySyntax, _diagnostics.DiagnosticBag), symbol: localSymbol, name: null, kind: localSymbol.SynthesizedKind, @@ -338,27 +339,27 @@ private void HandleReturn() private void EmitTypeReferenceToken(Cci.ITypeReference symbol, SyntaxNode syntaxNode) { - _builder.EmitToken(symbol, syntaxNode, _diagnostics); + _builder.EmitToken(symbol, syntaxNode, _diagnostics.DiagnosticBag); } private void EmitSymbolToken(TypeSymbol symbol, SyntaxNode syntaxNode) { - EmitTypeReferenceToken(_module.Translate(symbol, syntaxNode, _diagnostics), syntaxNode); + EmitTypeReferenceToken(_module.Translate(symbol, syntaxNode, _diagnostics.DiagnosticBag), syntaxNode); } private void EmitSymbolToken(MethodSymbol method, SyntaxNode syntaxNode, BoundArgListOperator optArgList, bool encodeAsRawDefinitionToken = false) { - _builder.EmitToken(_module.Translate(method, syntaxNode, _diagnostics, optArgList, needDeclaration: encodeAsRawDefinitionToken), syntaxNode, _diagnostics, encodeAsRawDefinitionToken); + _builder.EmitToken(_module.Translate(method, syntaxNode, _diagnostics.DiagnosticBag, optArgList, needDeclaration: encodeAsRawDefinitionToken), syntaxNode, _diagnostics.DiagnosticBag, encodeAsRawDefinitionToken); } private void EmitSymbolToken(FieldSymbol symbol, SyntaxNode syntaxNode) { - _builder.EmitToken(_module.Translate(symbol, syntaxNode, _diagnostics), syntaxNode, _diagnostics); + _builder.EmitToken(_module.Translate(symbol, syntaxNode, _diagnostics.DiagnosticBag), syntaxNode, _diagnostics.DiagnosticBag); } private void EmitSignatureToken(FunctionPointerTypeSymbol symbol, SyntaxNode syntaxNode) { - _builder.EmitToken(_module.Translate(symbol).Signature, syntaxNode, _diagnostics); + _builder.EmitToken(_module.Translate(symbol).Signature, syntaxNode, _diagnostics.DiagnosticBag); } private void EmitSequencePointStatement(BoundSequencePoint node) diff --git a/src/Compilers/CSharp/Portable/CodeGen/EmitAddress.cs b/src/Compilers/CSharp/Portable/CodeGen/EmitAddress.cs index af1b9a8db8a21..12f37a4d90c57 100644 --- a/src/Compilers/CSharp/Portable/CodeGen/EmitAddress.cs +++ b/src/Compilers/CSharp/Portable/CodeGen/EmitAddress.cs @@ -406,7 +406,7 @@ private void EmitArrayElementAddress(BoundArrayAccess arrayAccess, AddressKind a else { _builder.EmitArrayElementAddress(_module.Translate((ArrayTypeSymbol)arrayAccess.Expression.Type), - arrayAccess.Syntax, _diagnostics); + arrayAccess.Syntax, _diagnostics.DiagnosticBag); } } diff --git a/src/Compilers/CSharp/Portable/CodeGen/EmitArrayInitializer.cs b/src/Compilers/CSharp/Portable/CodeGen/EmitArrayInitializer.cs index 3307f76b6597e..3dc85ce6c3474 100644 --- a/src/Compilers/CSharp/Portable/CodeGen/EmitArrayInitializer.cs +++ b/src/Compilers/CSharp/Portable/CodeGen/EmitArrayInitializer.cs @@ -52,7 +52,7 @@ private void EmitArrayInitializers(ArrayTypeSymbol arrayType, BoundArrayInitiali else { ImmutableArray data = this.GetRawData(initExprs); - _builder.EmitArrayBlockInitializer(data, inits.Syntax, _diagnostics); + _builder.EmitArrayBlockInitializer(data, inits.Syntax, _diagnostics.DiagnosticBag); if (initializationStyle == ArrayInitializerStyle.Mixed) { @@ -236,8 +236,7 @@ private bool EnableEnumArrayBlockInitialization { get { - var sustainedLowLatency = _module.Compilation.GetWellKnownTypeMember(WellKnownMember.System_Runtime_GCLatencyMode__SustainedLowLatency); - return sustainedLowLatency != null && sustainedLowLatency.ContainingAssembly == _module.Compilation.Assembly.CorLibrary; + return _module.Compilation.EnableEnumArrayBlockInitialization; } } @@ -384,12 +383,15 @@ private bool TryEmitReadonlySpanAsBlobWrapper(NamedTypeSymbol spanType, BoundExp return false; } - var ctor = ((MethodSymbol?)this._module.Compilation.GetWellKnownTypeMember(WellKnownMember.System_ReadOnlySpan_T__ctor_Pointer)); + var ctor = (MethodSymbol?)Binder.GetWellKnownTypeMember(this._module.Compilation, WellKnownMember.System_ReadOnlySpan_T__ctor_Pointer, _diagnostics, syntax: wrappedExpression.Syntax, isOptional: true); + if (ctor == null) { return false; } + Debug.Assert(!ctor.HasUnsupportedMetadata); + if (wrappedExpression is BoundArrayCreation ac) { var arrayType = (ArrayTypeSymbol)ac.Type; @@ -471,7 +473,7 @@ private bool TryEmitReadonlySpanAsBlobWrapper(NamedTypeSymbol spanType, BoundExp return false; } - _builder.EmitArrayBlockFieldRef(data, wrappedExpression.Syntax, _diagnostics); + _builder.EmitArrayBlockFieldRef(data, wrappedExpression.Syntax, _diagnostics.DiagnosticBag!); _builder.EmitIntConstant(lengthForConstructor); if (inPlace) diff --git a/src/Compilers/CSharp/Portable/CodeGen/EmitExpression.cs b/src/Compilers/CSharp/Portable/CodeGen/EmitExpression.cs index a83e4b624bb2f..5dcaa907bef00 100644 --- a/src/Compilers/CSharp/Portable/CodeGen/EmitExpression.cs +++ b/src/Compilers/CSharp/Portable/CodeGen/EmitExpression.cs @@ -729,7 +729,7 @@ private void EmitThisReferenceExpression(BoundThisReference thisRef) private void EmitPseudoVariableValue(BoundPseudoVariable expression, bool used) { - EmitExpression(expression.EmitExpressions.GetValue(expression, _diagnostics), used); + EmitExpression(expression.EmitExpressions.GetValue(expression, _diagnostics.DiagnosticBag), used); } private void EmitSequencePointExpression(BoundSequencePointExpression node, bool used) @@ -995,7 +995,7 @@ private void EmitArrayElementLoad(BoundArrayAccess arrayAccess, bool used) } else { - _builder.EmitArrayElementLoad(_module.Translate((ArrayTypeSymbol)arrayAccess.Expression.Type), arrayAccess.Expression.Syntax, _diagnostics); + _builder.EmitArrayElementLoad(_module.Translate((ArrayTypeSymbol)arrayAccess.Expression.Type), arrayAccess.Expression.Syntax, _diagnostics.DiagnosticBag); } EmitPopIfUnused(used); @@ -1934,7 +1934,7 @@ private void EmitArrayCreationExpression(BoundArrayCreation expression, bool use } else { - _builder.EmitArrayCreation(_module.Translate(arrayType), expression.Syntax, _diagnostics); + _builder.EmitArrayCreation(_module.Translate(arrayType), expression.Syntax, _diagnostics.DiagnosticBag); } if (expression.InitializerOpt != null) @@ -2752,7 +2752,7 @@ private void EmitArrayElementStore(ArrayTypeSymbol arrayType, SyntaxNode syntaxN } else { - _builder.EmitArrayElementStore(_module.Translate(arrayType), syntaxNode, _diagnostics); + _builder.EmitArrayElementStore(_module.Translate(arrayType), syntaxNode, _diagnostics.DiagnosticBag); } } @@ -3111,7 +3111,7 @@ private void EmitModuleVersionIdStore(BoundModuleVersionId node) private void EmitModuleVersionIdToken(BoundModuleVersionId node) { - _builder.EmitToken(_module.GetModuleVersionId(_module.Translate(node.Type, node.Syntax, _diagnostics), node.Syntax, _diagnostics), node.Syntax, _diagnostics); + _builder.EmitToken(_module.GetModuleVersionId(_module.Translate(node.Type, node.Syntax, _diagnostics.DiagnosticBag), node.Syntax, _diagnostics.DiagnosticBag), node.Syntax, _diagnostics.DiagnosticBag); } private void EmitModuleVersionIdStringLoad(BoundModuleVersionIdString node) @@ -3134,7 +3134,7 @@ private void EmitInstrumentationPayloadRootStore(BoundInstrumentationPayloadRoot private void EmitInstrumentationPayloadRootToken(BoundInstrumentationPayloadRoot node) { - _builder.EmitToken(_module.GetInstrumentationPayloadRoot(node.AnalysisKind, _module.Translate(node.Type, node.Syntax, _diagnostics), node.Syntax, _diagnostics), node.Syntax, _diagnostics); + _builder.EmitToken(_module.GetInstrumentationPayloadRoot(node.AnalysisKind, _module.Translate(node.Type, node.Syntax, _diagnostics.DiagnosticBag), node.Syntax, _diagnostics.DiagnosticBag), node.Syntax, _diagnostics.DiagnosticBag); } private void EmitSourceDocumentIndex(BoundSourceDocumentIndex node) diff --git a/src/Compilers/CSharp/Portable/CodeGen/EmitStackAllocInitializer.cs b/src/Compilers/CSharp/Portable/CodeGen/EmitStackAllocInitializer.cs index 41cb5fe785d5b..74ac0d74260be 100644 --- a/src/Compilers/CSharp/Portable/CodeGen/EmitStackAllocInitializer.cs +++ b/src/Compilers/CSharp/Portable/CodeGen/EmitStackAllocInitializer.cs @@ -36,7 +36,7 @@ private void EmitStackAllocInitializers(TypeSymbol type, BoundArrayInitializatio ImmutableArray data = this.GetRawData(initExprs); if (data.All(datum => datum == data[0])) { - _builder.EmitStackAllocBlockInitializer(data, inits.Syntax, emitInitBlock: true, _diagnostics); + _builder.EmitStackAllocBlockInitializer(data, inits.Syntax, emitInitBlock: true, _diagnostics.DiagnosticBag); if (initializationStyle == ArrayInitializerStyle.Mixed) { @@ -45,7 +45,7 @@ private void EmitStackAllocInitializers(TypeSymbol type, BoundArrayInitializatio } else if (elementType.SpecialType.SizeInBytes() == 1) { - _builder.EmitStackAllocBlockInitializer(data, inits.Syntax, emitInitBlock: false, _diagnostics); + _builder.EmitStackAllocBlockInitializer(data, inits.Syntax, emitInitBlock: false, _diagnostics.DiagnosticBag); if (initializationStyle == ArrayInitializerStyle.Mixed) { diff --git a/src/Compilers/CSharp/Portable/CodeGen/EmitStatement.cs b/src/Compilers/CSharp/Portable/CodeGen/EmitStatement.cs index 3e045b6ee2739..9bd07bebd1ad9 100644 --- a/src/Compilers/CSharp/Portable/CodeGen/EmitStatement.cs +++ b/src/Compilers/CSharp/Portable/CodeGen/EmitStatement.cs @@ -789,7 +789,7 @@ private void EmitReturnStatement(BoundReturnStatement boundReturnStatement) { // Ensure the return type has been translated. (Necessary // for cases of untranslated anonymous types.) - _module.Translate(expressionOpt.Type, boundReturnStatement.Syntax, _diagnostics); + _module.Translate(expressionOpt.Type, boundReturnStatement.Syntax, _diagnostics.DiagnosticBag); } _builder.EmitRet(expressionOpt == null); } @@ -924,8 +924,8 @@ private void EmitCatchBlock(BoundCatchBlock catchBlock) if (catchBlock.ExceptionFilterOpt == null) { var exceptionType = ((object)catchBlock.ExceptionTypeOpt != null) ? - _module.Translate(catchBlock.ExceptionTypeOpt, catchBlock.Syntax, _diagnostics) : - _module.GetSpecialType(SpecialType.System_Object, catchBlock.Syntax, _diagnostics); + _module.Translate(catchBlock.ExceptionTypeOpt, catchBlock.Syntax, _diagnostics.DiagnosticBag) : + _module.GetSpecialType(SpecialType.System_Object, catchBlock.Syntax, _diagnostics.DiagnosticBag); _builder.OpenLocalScope(ScopeType.Catch, exceptionType); @@ -971,10 +971,10 @@ private void EmitCatchBlock(BoundCatchBlock catchBlock) if ((object)catchBlock.ExceptionTypeOpt != null) { - var exceptionType = _module.Translate(catchBlock.ExceptionTypeOpt, catchBlock.Syntax, _diagnostics); + var exceptionType = _module.Translate(catchBlock.ExceptionTypeOpt, catchBlock.Syntax, _diagnostics.DiagnosticBag); _builder.EmitOpCode(ILOpCode.Isinst); - _builder.EmitToken(exceptionType, catchBlock.Syntax, _diagnostics); + _builder.EmitToken(exceptionType, catchBlock.Syntax, _diagnostics.DiagnosticBag); _builder.EmitOpCode(ILOpCode.Dup); _builder.EmitBranch(ILOpCode.Brtrue, typeCheckPassedLabel); _builder.EmitOpCode(ILOpCode.Pop); @@ -1221,7 +1221,7 @@ private void EmitStringSwitchJumpTable( { Debug.Assert(_module.SupportsPrivateImplClass); - var privateImplClass = _module.GetPrivateImplClass(syntaxNode, _diagnostics); + var privateImplClass = _module.GetPrivateImplClass(syntaxNode, _diagnostics.DiagnosticBag); Cci.IReference stringHashMethodRef = privateImplClass.GetMethod( isSpanOrReadOnlySpan ? isReadOnlySpan @@ -1242,9 +1242,9 @@ private void EmitStringSwitchJumpTable( _builder.EmitLoad(key); _builder.EmitOpCode(ILOpCode.Call, stackAdjustment: 0); - _builder.EmitToken(stringHashMethodRef, syntaxNode, _diagnostics); + _builder.EmitToken(stringHashMethodRef, syntaxNode, _diagnostics.DiagnosticBag); - var UInt32Type = _module.Compilation.GetSpecialType(SpecialType.System_UInt32); + var UInt32Type = Binder.GetSpecialType(_module.Compilation, SpecialType.System_UInt32, syntaxNode, _diagnostics); keyHash = AllocateTemp(UInt32Type, syntaxNode); _builder.EmitLocalStore(keyHash); @@ -1260,34 +1260,38 @@ private void EmitStringSwitchJumpTable( if (isSpanOrReadOnlySpan) { // Binder.ConvertPatternExpression() has checked for these well-known members. - var sequenceEqualsTMethod = (MethodSymbol)_module.Compilation.GetWellKnownTypeMember(isReadOnlySpan + var sequenceEqualsTMethod = (MethodSymbol)Binder.GetWellKnownTypeMember(_module.Compilation, + (isReadOnlySpan ? WellKnownMember.System_MemoryExtensions__SequenceEqual_ReadOnlySpan_T - : WellKnownMember.System_MemoryExtensions__SequenceEqual_Span_T); + : WellKnownMember.System_MemoryExtensions__SequenceEqual_Span_T), + _diagnostics, syntax: syntaxNode); Debug.Assert(sequenceEqualsTMethod != null && !sequenceEqualsTMethod.HasUseSiteError); - var sequenceEqualsCharMethod = sequenceEqualsTMethod.Construct(_module.Compilation.GetSpecialType(SpecialType.System_Char)); - sequenceEqualsMethodRef = _module.Translate(sequenceEqualsCharMethod, null, _diagnostics); + var sequenceEqualsCharMethod = sequenceEqualsTMethod.Construct(Binder.GetSpecialType(_module.Compilation, SpecialType.System_Char, syntaxNode, _diagnostics)); + sequenceEqualsMethodRef = _module.Translate(sequenceEqualsCharMethod, null, _diagnostics.DiagnosticBag); - var asSpanMethod = (MethodSymbol)_module.Compilation.GetWellKnownTypeMember(WellKnownMember.System_MemoryExtensions__AsSpan_String); + var asSpanMethod = (MethodSymbol)Binder.GetWellKnownTypeMember(_module.Compilation, WellKnownMember.System_MemoryExtensions__AsSpan_String, _diagnostics, syntax: syntaxNode); Debug.Assert(asSpanMethod != null && !asSpanMethod.HasUseSiteError); - asSpanMethodRef = _module.Translate(asSpanMethod, null, _diagnostics); + asSpanMethodRef = _module.Translate(asSpanMethod, null, _diagnostics.DiagnosticBag); - var spanTLengthMethod = (MethodSymbol)_module.Compilation.GetWellKnownTypeMember(isReadOnlySpan + var spanTLengthMethod = (MethodSymbol)Binder.GetWellKnownTypeMember(_module.Compilation, + (isReadOnlySpan ? WellKnownMember.System_ReadOnlySpan_T__get_Length - : WellKnownMember.System_Span_T__get_Length); + : WellKnownMember.System_Span_T__get_Length), + _diagnostics, syntax: syntaxNode); Debug.Assert(spanTLengthMethod != null && !spanTLengthMethod.HasUseSiteError); var spanCharLengthMethod = spanTLengthMethod.AsMember((NamedTypeSymbol)keyType); - lengthMethodRef = _module.Translate(spanCharLengthMethod, null, _diagnostics); + lengthMethodRef = _module.Translate(spanCharLengthMethod, null, _diagnostics.DiagnosticBag); } else { var stringEqualityMethod = _module.Compilation.GetSpecialTypeMember(SpecialMember.System_String__op_Equality) as MethodSymbol; Debug.Assert(stringEqualityMethod != null && !stringEqualityMethod.HasUseSiteError); - stringEqualityMethodRef = _module.Translate(stringEqualityMethod, syntaxNode, _diagnostics); + stringEqualityMethodRef = _module.Translate(stringEqualityMethod, syntaxNode, _diagnostics.DiagnosticBag); var stringLengthMethod = _module.Compilation.GetSpecialTypeMember(SpecialMember.System_String__Length) as MethodSymbol; if (stringLengthMethod != null && !stringLengthMethod.HasUseSiteError) { - lengthMethodRef = _module.Translate(stringLengthMethod, syntaxNode, _diagnostics); + lengthMethodRef = _module.Translate(stringLengthMethod, syntaxNode, _diagnostics.DiagnosticBag); } } @@ -1398,7 +1402,7 @@ private void EmitStringCompareAndBranch(LocalOrParameter key, SyntaxNode syntaxN _builder.EmitLoad(key); _builder.EmitConstantValue(stringConstant); _builder.EmitOpCode(ILOpCode.Call, stackAdjustment: -1); - _builder.EmitToken(stringEqualityMethodRef, syntaxNode, _diagnostics); + _builder.EmitToken(stringEqualityMethodRef, syntaxNode, _diagnostics.DiagnosticBag); // Branch to targetLabel if String.Equals returned true. _builder.EmitBranch(ILOpCode.Brtrue, targetLabel, ILOpCode.Brfalse); @@ -1425,9 +1429,9 @@ private void EmitCharCompareAndBranch(LocalOrParameter key, SyntaxNode syntaxNod _builder.EmitLoad(key); _builder.EmitConstantValue(stringConstant); _builder.EmitOpCode(ILOpCode.Call, stackAdjustment: 0); - _builder.EmitToken(asSpanRef, syntaxNode, _diagnostics); + _builder.EmitToken(asSpanRef, syntaxNode, _diagnostics.DiagnosticBag); _builder.EmitOpCode(ILOpCode.Call, stackAdjustment: -1); - _builder.EmitToken(sequenceEqualsRef, syntaxNode, _diagnostics); + _builder.EmitToken(sequenceEqualsRef, syntaxNode, _diagnostics.DiagnosticBag); // Branch to targetLabel if SequenceEquals returned true. _builder.EmitBranch(ILOpCode.Brtrue, targetLabel, ILOpCode.Brfalse); @@ -1459,7 +1463,7 @@ private LocalDefinition DefineLocal(LocalSymbol local, SyntaxNode syntaxNode) if (local.IsConst) { Debug.Assert(local.HasConstantValue); - MetadataConstant compileTimeValue = _module.CreateConstant(local.Type, local.ConstantValue, syntaxNode, _diagnostics); + MetadataConstant compileTimeValue = _module.CreateConstant(local.Type, local.ConstantValue, syntaxNode, _diagnostics.DiagnosticBag); LocalConstantDefinition localConstantDef = new LocalConstantDefinition( local.Name, local.Locations.FirstOrDefault() ?? Location.None, @@ -1490,19 +1494,19 @@ private LocalDefinition DefineLocal(LocalSymbol local, SyntaxNode syntaxNode) // We can't declare a reference to void, so if the pointed-at type is void, use native int // (represented here by IntPtr) instead. translatedType = pointedAtType.IsVoidType() - ? _module.GetSpecialType(SpecialType.System_IntPtr, syntaxNode, _diagnostics) - : _module.Translate(pointedAtType, syntaxNode, _diagnostics); + ? _module.GetSpecialType(SpecialType.System_IntPtr, syntaxNode, _diagnostics.DiagnosticBag) + : _module.Translate(pointedAtType, syntaxNode, _diagnostics.DiagnosticBag); } else { constraints = (local.IsPinned ? LocalSlotConstraints.Pinned : LocalSlotConstraints.None) | (local.RefKind != RefKind.None ? LocalSlotConstraints.ByRef : LocalSlotConstraints.None); - translatedType = _module.Translate(local.Type, syntaxNode, _diagnostics); + translatedType = _module.Translate(local.Type, syntaxNode, _diagnostics.DiagnosticBag); } // Even though we don't need the token immediately, we will need it later when signature for the local is emitted. // Also, requesting the token has side-effect of registering types used, which is critical for embedded types (NoPia, VBCore, etc). - _module.GetFakeSymbolTokenForIL(translatedType, syntaxNode, _diagnostics); + _module.GetFakeSymbolTokenForIL(translatedType, syntaxNode, _diagnostics.DiagnosticBag); LocalDebugId localId; var name = GetLocalDebugName(local, out localId); @@ -1594,7 +1598,7 @@ private void FreeLocal(LocalSymbol local) private LocalDefinition AllocateTemp(TypeSymbol type, SyntaxNode syntaxNode, LocalSlotConstraints slotConstraints = LocalSlotConstraints.None) { return _builder.LocalSlotManager.AllocateSlot( - _module.Translate(type, syntaxNode, _diagnostics), + _module.Translate(type, syntaxNode, _diagnostics.DiagnosticBag), slotConstraints); } diff --git a/src/Compilers/CSharp/Portable/Compiler/MethodCompiler.cs b/src/Compilers/CSharp/Portable/Compiler/MethodCompiler.cs index 4d132290c1759..b486b10c297e6 100644 --- a/src/Compilers/CSharp/Portable/Compiler/MethodCompiler.cs +++ b/src/Compilers/CSharp/Portable/Compiler/MethodCompiler.cs @@ -1508,7 +1508,7 @@ private static MethodBody GenerateMethodBody( { StateMachineMoveNextBodyDebugInfo moveNextBodyDebugInfoOpt = null; - var codeGen = new CodeGen.CodeGenerator(method, block, builder, moduleBuilder, diagnosticsForThisMethod.DiagnosticBag, optimizations, emittingPdb); + var codeGen = new CodeGen.CodeGenerator(method, block, builder, moduleBuilder, diagnosticsForThisMethod, optimizations, emittingPdb); if (diagnosticsForThisMethod.HasAnyErrors()) { diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenReadOnlySpanConstructionTest.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenReadOnlySpanConstructionTest.cs index ccdcc9622d335..2a2cdcdf4afee 100644 --- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenReadOnlySpanConstructionTest.cs +++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenReadOnlySpanConstructionTest.cs @@ -691,7 +691,7 @@ .maxstack 4 [Fact] [WorkItem(24621, "https://github.com/dotnet/roslyn/issues/24621")] - public void StaticFieldIsUsedForSpanCreatedFromArrayWithInitializer() + public void StaticFieldIsUsedForSpanCreatedFromArrayWithInitializer_01() { var csharp = @" using System; @@ -719,5 +719,194 @@ .maxstack 2 IL_000b: ret }"); } + + [Fact] + public void StaticFieldIsUsedForSpanCreatedFromArrayWithInitializer_02() + { + // This IL applies CompilerFeatureRequiredAttribute to WellKnownMember.System_ReadOnlySpan_T__ctor_Pointer. + // That should prevent its usage during code gen, as if the member doesn't exist. + var ilSource = @" +.class public sequential ansi sealed beforefieldinit System.ReadOnlySpan`1 + extends [mscorlib]System.ValueType +{ + .custom instance void [mscorlib]System.Runtime.CompilerServices.IsByRefLikeAttribute::.ctor() = ( + 01 00 00 00 + ) + .custom instance void [mscorlib]System.ObsoleteAttribute::.ctor(string, bool) = ( + 01 00 52 54 79 70 65 73 20 77 69 74 68 20 65 6d + 62 65 64 64 65 64 20 72 65 66 65 72 65 6e 63 65 + 73 20 61 72 65 20 6e 6f 74 20 73 75 70 70 6f 72 + 74 65 64 20 69 6e 20 74 68 69 73 20 76 65 72 73 + 69 6f 6e 20 6f 66 20 79 6f 75 72 20 63 6f 6d 70 + 69 6c 65 72 2e 01 00 00 + ) + .custom instance void [mscorlib]System.Runtime.CompilerServices.IsReadOnlyAttribute::.ctor() = ( + 01 00 00 00 + ) + .pack 0 + .size 1 + + .method public hidebysig specialname rtspecialname + instance void .ctor ( + void* pointer, + int32 length + ) cil managed + { + .custom instance void System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute::.ctor(string) = ( + 01 00 04 54 65 73 74 00 00 + ) + + .maxstack 8 + + IL_0000: ldnull + IL_0001: throw + } + + .method public hidebysig specialname rtspecialname + instance void .ctor ( + !T[] arr + ) cil managed + { + .maxstack 8 + + IL_0000: ldnull + IL_0001: throw + } + + .method public hidebysig specialname static + valuetype System.ReadOnlySpan`1 op_Implicit ( + !T[] 'array' + ) cil managed + { + .maxstack 1 + .locals init ( + [0] valuetype System.ReadOnlySpan`1 + ) + + IL_0000: ldnull + IL_0001: throw + } +} + +.class public auto ansi sealed beforefieldinit System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute + extends [mscorlib]System.Attribute + { + .custom instance void [mscorlib]System.AttributeUsageAttribute::.ctor(valuetype [mscorlib]System.AttributeTargets) = ( + 01 00 ff 7f 00 00 02 00 54 02 0d 41 6c 6c 6f 77 + 4d 75 6c 74 69 70 6c 65 01 54 02 09 49 6e 68 65 + 72 69 74 65 64 00 + ) + // Fields + .field private initonly string 'k__BackingField' + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( + 01 00 00 00 + ) + .field private initonly bool 'k__BackingField' + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( + 01 00 00 00 + ) + + .field public static literal string RefStructs = ""RefStructs"" + .field public static literal string RequiredMembers = ""RequiredMembers"" + + // Methods + .method public hidebysig specialname rtspecialname + instance void .ctor ( + string featureName + ) cil managed + { + ldarg.0 + call instance void [mscorlib]System.Attribute::.ctor() + ldarg.0 + ldarg.1 + stfld string System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute::'k__BackingField' + ret + } // end of method CompilerFeatureRequiredAttribute::.ctor + + .method public hidebysig specialname + instance string get_FeatureName () cil managed + { + ldarg.0 + ldfld string System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute::'k__BackingField' + ret + } // end of method CompilerFeatureRequiredAttribute::get_FeatureName + + .method public hidebysig specialname + instance bool get_IsOptional () cil managed + { + ldarg.0 + ldfld bool System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute::'k__BackingField' + ret + } // end of method CompilerFeatureRequiredAttribute::get_IsOptional + + .method public hidebysig specialname + instance void modreq([mscorlib]System.Runtime.CompilerServices.IsExternalInit) set_IsOptional ( + bool 'value' + ) cil managed + { + ldarg.0 + ldarg.1 + stfld bool System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute::'k__BackingField' + ret + } // end of method CompilerFeatureRequiredAttribute::set_IsOptional + + // Properties + .property instance string FeatureName() + { + .get instance string System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute::get_FeatureName() + } + .property instance bool IsOptional() + { + .get instance bool System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute::get_IsOptional() + .set instance void modreq([mscorlib]System.Runtime.CompilerServices.IsExternalInit) System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute::set_IsOptional(bool) + } + + } // end of class System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute +"; + + var csharp = @" +using System; + +public class Test +{ + public static ReadOnlySpan StaticData => new byte[] { 10, 20 }; + + public static void Main() + { + } +}"; + + var compilation = CreateCompilationWithIL(csharp, ilSource); + var verifier = CompileAndVerify(compilation, verify: Verification.Skipped); + + var expected = +@" +{ + // Code size 22 (0x16) + .maxstack 4 + IL_0000: ldc.i4.2 + IL_0001: newarr ""byte"" + IL_0006: dup + IL_0007: ldc.i4.0 + IL_0008: ldc.i4.s 10 + IL_000a: stelem.i1 + IL_000b: dup + IL_000c: ldc.i4.1 + IL_000d: ldc.i4.s 20 + IL_000f: stelem.i1 + IL_0010: call ""System.ReadOnlySpan System.ReadOnlySpan.op_Implicit(byte[])"" + IL_0015: ret +} +"; + // Verify emitted IL with "bad" WellKnownMember.System_ReadOnlySpan_T__ctor_Pointer + verifier.VerifyIL("Test.StaticData.get", expected); + + // We should get the same IL with regular ReadOnlySpan implementation, + // but with WellKnownMember.System_ReadOnlySpan_T__ctor_Pointer missing + compilation = CreateCompilationWithMscorlibAndSpan(csharp); + compilation.MakeMemberMissing(WellKnownMember.System_ReadOnlySpan_T__ctor_Pointer); + verifier = CompileAndVerify(compilation, verify: Verification.Skipped); + verifier.VerifyIL("Test.StaticData.get", expected); + } } }