From d63f038476c93c21c9f169ddbf79dedd9c7aab2a Mon Sep 17 00:00:00 2001 From: Omar Tawfik Date: Thu, 18 May 2017 11:56:16 -0700 Subject: [PATCH] Generate readonlyattribute if it does not exist (#18715) * Call this.DeclaringCompilation.EnsureReadOnlyAttributeExists() when needed * Promote EmbeddedAttribute to be used by both compilers * Generate Embedded attributes on PE Module Builder * Thread PEModuleBuilder through Symbol.AddSynthesizedAttributes() * Fix failing tests * Base case passing * Refactor ReadOnlyAttribute to IsReadOnlyAttribute * Fix build break * More Tests * Clean up * PR Comments #1 PR Comments #3 PR Comments #4 PR Comments #5 PR Comments #6 PR Comments # 7 * Handle NoPIA Added more tests * Lambdas and Local functions no longer generate attributes in symbols Added tests for constructors and operators Signal need for synthesized attributes in local rewriter for lambdas an local functions Clean up * Clean up * More PR Feedback * Adding more tests * More PR Comments * More tests for explicit interface implementations * Latest PR Comments * Moved EnsureIsReadOnlyAttributeExists to AfterAddingTypeMembersChecks * Fix failing tests --- .../CSharp/Portable/Binder/Binder_Lookup.cs | 7 +- .../CSharp/Portable/Binder/LookupResult.cs | 5 + .../Portable/BoundTree/UnboundLambda.cs | 21 +- .../CSharp/Portable/CSharpCodeAnalysis.csproj | 1 + .../Portable/CSharpResources.Designer.cs | 11 +- .../CSharp/Portable/CSharpResources.resx | 5 +- .../Portable/Compilation/CSharpCompilation.cs | 4 + .../AnonymousTypeMethodBodySynthesizer.cs | 3 +- .../Portable/Compiler/MethodCompiler.cs | 37 +- .../Emitter/Model/MethodSymbolAdapter.cs | 12 +- .../Emitter/Model/PEAssemblyBuilder.cs | 82 +- .../Portable/Emitter/Model/PEModuleBuilder.cs | 65 +- .../Model/SourceAssemblySymbolAdapter.cs | 5 +- .../Portable/Emitter/Model/SymbolAdapter.cs | 10 +- .../Portable/Emitter/NoPia/EmbeddedEvent.cs | 4 +- .../Portable/Emitter/NoPia/EmbeddedField.cs | 4 +- .../Portable/Emitter/NoPia/EmbeddedMethod.cs | 4 +- .../Emitter/NoPia/EmbeddedParameter.cs | 4 +- .../Emitter/NoPia/EmbeddedProperty.cs | 4 +- .../Portable/Emitter/NoPia/EmbeddedType.cs | 4 +- .../CSharp/Portable/Errors/ErrorCode.cs | 1 + .../IteratorRewriter/IteratorConstructor.cs | 4 +- .../Lowering/LocalRewriter/LocalRewriter.cs | 30 + .../Lowering/MethodToClassRewriter.cs | 5 +- .../StateMachineTypeSymbol.cs | 2 + .../SynthesizedStateMachineMethod.cs | 5 +- .../Lowering/SynthesizedMethodBaseSymbol.cs | 4 +- .../AnonymousType.TypePublicSymbol.cs | 2 + .../AnonymousType.FieldSymbol.cs | 4 +- .../AnonymousType.PropertyAccessorSymbol.cs | 2 +- .../AnonymousType.SynthesizedMethodBase.cs | 5 +- .../AnonymousType.TemplateSymbol.cs | 7 +- .../CSharp/Portable/Symbols/AssemblySymbol.cs | 5 + .../Symbols/Compilation_WellKnownMembers.cs | 58 +- .../Portable/Symbols/ErrorTypeSymbol.cs | 2 + .../Symbols/Metadata/PE/PEEventSymbol.cs | 3 +- .../Symbols/Metadata/PE/PEFieldSymbol.cs | 2 +- .../Symbols/Metadata/PE/PEMethodSymbol.cs | 3 +- .../Symbols/Metadata/PE/PENamedTypeSymbol.cs | 26 +- .../Symbols/Metadata/PE/PEParameterSymbol.cs | 4 +- .../Symbols/Metadata/PE/PEPropertySymbol.cs | 4 +- .../CSharp/Portable/Symbols/MethodSymbol.cs | 5 +- .../Portable/Symbols/NamedTypeSymbol.cs | 5 + .../Retargeting/RetargetingEventSymbol.cs | 4 +- .../Retargeting/RetargetingFieldSymbol.cs | 4 +- .../Retargeting/RetargetingMethodSymbol.cs | 4 +- .../Retargeting/RetargetingNamedTypeSymbol.cs | 4 +- .../Retargeting/RetargetingParameterSymbol.cs | 4 +- .../Retargeting/RetargetingPropertySymbol.cs | 4 +- .../Symbols/Source/ImplicitNamedTypeSymbol.cs | 2 + .../Portable/Symbols/Source/LambdaSymbol.cs | 10 +- .../Symbols/Source/LocalFunctionSymbol.cs | 41 +- .../Symbols/Source/ParameterHelpers.cs | 39 +- .../Symbols/Source/SourceAssemblySymbol.cs | 5 +- .../Source/SourceClonedParameterSymbol.cs | 7 +- .../Source/SourceComplexParameterSymbol.cs | 4 +- .../Symbols/Source/SourceConstructorSymbol.cs | 7 + .../Source/SourceDelegateMethodSymbol.cs | 13 + .../Symbols/Source/SourceEventFieldSymbol.cs | 4 +- .../Symbols/Source/SourceEventSymbol.cs | 5 +- .../Symbols/Source/SourceFieldSymbol.cs | 8 +- .../Symbols/Source/SourceFixedFieldSymbol.cs | 8 +- .../Symbols/Source/SourceMemberFieldSymbol.cs | 4 +- .../Source/SourceMemberMethodSymbol.cs | 12 +- .../Symbols/Source/SourceMethodSymbol.cs | 19 +- .../Symbols/Source/SourceModuleSymbol.cs | 5 +- .../Symbols/Source/SourceNamedTypeSymbol.cs | 33 +- .../Symbols/Source/SourceParameterSymbol.cs | 8 +- .../Source/SourceParameterSymbolBase.cs | 4 +- .../Source/SourcePropertyAccessorSymbol.cs | 4 +- .../Symbols/Source/SourcePropertySymbol.cs | 18 +- .../SourceUserDefinedOperatorSymbolBase.cs | 2 + .../Symbols/SubstitutedNamedTypeSymbol.cs | 3 +- .../CSharp/Portable/Symbols/Symbol.cs | 3 +- .../Portable/Symbols/SymbolExtensions.cs | 20 + .../SynthesizedBackingFieldSymbol.cs | 5 +- .../Synthesized/SynthesizedContainer.cs | 7 +- .../SynthesizedEmbeddedAttributeSymbol.cs | 194 ++ .../SynthesizedEnumValueFieldSymbol.cs | 3 +- ...SynthesizedFieldLikeEventAccessorSymbol.cs | 4 +- .../Synthesized/SynthesizedFieldSymbolBase.cs | 5 +- .../SynthesizedImplementationMethod.cs | 5 +- .../SynthesizedInstanceConstructor.cs | 4 + .../Synthesized/SynthesizedParameterSymbol.cs | 5 +- .../Symbols/Tuples/TupleTypeSymbol.cs | 3 +- .../Symbols/Wrapped/WrappedNamedTypeSymbol.cs | 2 + .../Symbols/Wrapped/WrappedParameterSymbol.cs | 5 +- .../Portable/Syntax/SyntaxNodeExtensions.cs | 10 + .../Test/Emit/Attributes/AttributeTests.cs | 2 - .../Attributes/AttributeTests_Assembly.cs | 4 +- .../Attributes/AttributeTests_Embedded.cs | 435 ++++ .../Attributes/AttributeTests_RefReadOnly.cs | 2000 ++++++++++++++++- .../Test/Emit/CSharpCompilerEmitTest.csproj | 1 + .../Emit/CodeGen/CodeGenAsyncMainTests.cs | 1 + .../Test/Emit/Emit/OptionalArgumentsTests.cs | 4 +- .../Symbol/Symbols/CorLibrary/CorTypes.cs | 4 + .../Symbol/Symbols/GenericConstraintTests.cs | 10 +- .../Test/Symbol/Symbols/IndexerTests.cs | 2 +- .../Symbols/Metadata/PE/LoadingAttributes.cs | 22 +- .../Symbol/Symbols/MissingSpecialMember.cs | 4 +- .../Symbol/Symbols/MockNamedTypeSymbol.cs | 2 + .../Emit/NoPia/CommonEmbeddedMember.cs | 8 +- .../Emit/NoPia/CommonEmbeddedMethod.cs | 9 +- .../Emit/NoPia/CommonEmbeddedParameter.cs | 8 +- .../Portable/Emit/NoPia/CommonEmbeddedType.cs | 8 +- .../Core/Portable/Emit/NoPia/VtblGap.cs | 4 +- .../Core/Portable/MetadataReader/PEModule.cs | 9 +- .../Core/Portable/PEWriter/Members.cs | 2 +- .../Core/Portable/PEWriter/MetadataVisitor.cs | 2 +- .../Core/Portable/PEWriter/MetadataWriter.cs | 4 +- .../Portable/PEWriter/ReturnValueParameter.cs | 2 +- .../Attributes/AttributeDescription.cs | 7 +- .../CommonTypeEarlyWellKnownAttributeData.cs | 18 + .../Core/Portable/WellKnownMember.cs | 2 +- .../Core/Portable/WellKnownMembers.cs | 6 +- src/Compilers/Core/Portable/WellKnownTypes.cs | 4 +- .../Test/Utilities/CSharp/CSharpTestBase.cs | 12 + .../Utilities/CSharp/CompilationTestUtils.cs | 23 +- .../Test/Utilities/VisualBasic/MockSymbols.vb | 8 +- .../Portable/Binding/Binder_Lookup.vb | 10 +- .../Portable/Emit/MethodSymbolAdapter.vb | 8 +- .../Portable/Emit/NoPia/EmbeddedEvent.vb | 4 +- .../Portable/Emit/NoPia/EmbeddedField.vb | 4 +- .../Portable/Emit/NoPia/EmbeddedMethod.vb | 4 +- .../Portable/Emit/NoPia/EmbeddedParameter.vb | 4 +- .../Portable/Emit/NoPia/EmbeddedProperty.vb | 4 +- .../Portable/Emit/NoPia/EmbeddedType.vb | 4 +- .../SynthesizedContainer.vb | 8 +- .../AnonymousTypeOrDelegatePublicSymbol.vb | 8 +- .../AnonymousTypeOrDelegateTemplateSymbol.vb | 8 +- .../Portable/Symbols/AssemblySymbol.vb | 5 +- .../TypeEarlyWellKnownAttributeData.vb | 8 +- .../Portable/Symbols/ErrorTypeSymbol.vb | 8 +- .../Symbols/Metadata/PE/PENamedTypeSymbol.vb | 30 +- .../Portable/Symbols/NamedTypeSymbol.vb | 7 +- .../Retargeting/RetargetingNamedTypeSymbol.vb | 10 +- .../Symbols/Source/ImplicitNamedTypeSymbol.vb | 8 +- .../Symbols/Source/SourceNamedTypeSymbol.vb | 23 +- .../Source/SourceNamedTypeSymbol_ComClass.vb | 8 +- .../Portable/Symbols/SubstitutedNamedType.vb | 10 +- .../Portable/Symbols/SymbolExtensions.vb | 25 +- .../SynthesizedEventDelegateSymbol.vb | 8 +- .../Portable/Symbols/UnboundGenericType.vb | 10 +- .../Symbols/Wrapped/WrappedNamedTypeSymbol.vb | 10 +- .../Test/Emit/Attributes/AttributeTests.vb | 232 ++ .../VisualBasic/Test/Emit/ErrorHandling.vb | 84 + .../WellKnownTypeValidationTests.vb | 14 +- .../Symbols/EEMethodSymbol.cs | 5 +- .../Symbols/EENamedTypeSymbol.cs | 2 + .../ExpressionCompilerTestBase.cs | 2 +- .../Symbols/EENamedTypeSymbol.vb | 8 +- .../ExpressionCompilerTestBase.vb | 2 +- 152 files changed, 3809 insertions(+), 447 deletions(-) create mode 100644 src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEmbeddedAttributeSymbol.cs create mode 100644 src/Compilers/CSharp/Test/Emit/Attributes/AttributeTests_Embedded.cs diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Lookup.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Lookup.cs index b08ba29634ab8..4c7f4a040e75e 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Lookup.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Lookup.cs @@ -1116,7 +1116,12 @@ internal SingleLookupResult CheckViability(Symbol symbol, int arity, LookupOptio ? ((AliasSymbol)symbol).GetAliasTarget(basesBeingResolved) : symbol; - if (WrongArity(symbol, arity, diagnose, options, out diagInfo)) + // Check for symbols marked with 'Microsoft.CodeAnalysis.Embedded' attribute + if (!this.Compilation.SourceModule.Equals(unwrappedSymbol.ContainingModule) && unwrappedSymbol.IsHiddenByCodeAnalysisEmbeddedAttribute()) + { + return LookupResult.Empty(); + } + else if (WrongArity(symbol, arity, diagnose, options, out diagInfo)) { return LookupResult.WrongArity(symbol, diagInfo); } diff --git a/src/Compilers/CSharp/Portable/Binder/LookupResult.cs b/src/Compilers/CSharp/Portable/Binder/LookupResult.cs index e75cafe0c2e14..1c53142a85a78 100644 --- a/src/Compilers/CSharp/Portable/Binder/LookupResult.cs +++ b/src/Compilers/CSharp/Portable/Binder/LookupResult.cs @@ -157,6 +157,11 @@ internal static SingleLookupResult WrongArity(Symbol symbol, DiagnosticInfo erro return new SingleLookupResult(LookupResultKind.WrongArity, symbol, error); } + internal static SingleLookupResult Empty() + { + return new SingleLookupResult(LookupResultKind.Empty, null, null); + } + internal static SingleLookupResult NotReferencable(Symbol symbol, DiagnosticInfo error) { return new SingleLookupResult(LookupResultKind.NotReferencable, symbol, error); diff --git a/src/Compilers/CSharp/Portable/BoundTree/UnboundLambda.cs b/src/Compilers/CSharp/Portable/BoundTree/UnboundLambda.cs index 7c5884ae49d3f..6c1c77673ecab 100644 --- a/src/Compilers/CSharp/Portable/BoundTree/UnboundLambda.cs +++ b/src/Compilers/CSharp/Portable/BoundTree/UnboundLambda.cs @@ -450,8 +450,17 @@ private BoundLambda ReallyBind(NamedTypeSymbol delegateType) cacheKey.ParameterTypes, cacheKey.ParameterRefKinds, refKind, - returnType); + returnType, + diagnostics); lambdaBodyBinder = new ExecutableCodeBinder(_unboundLambda.Syntax, lambdaSymbol, ParameterBinder(lambdaSymbol, binder)); + + if (lambdaSymbol.RefKind == CodeAnalysis.RefKind.RefReadOnly) + { + binder.Compilation.EnsureIsReadOnlyAttributeExists(diagnostics, lambdaSymbol.DiagnosticLocation, modifyCompilationForRefReadOnly: false); + } + + ParameterHelpers.EnsureIsReadOnlyAttributeExists(lambdaSymbol.Parameters, diagnostics, modifyCompilationForRefReadOnly: false); + block = BindLambdaBody(lambdaSymbol, lambdaBodyBinder, diagnostics); ((ExecutableCodeBinder)lambdaBodyBinder).ValidateIteratorMethods(diagnostics); @@ -525,7 +534,15 @@ private void ValidateUnsafeParameters(DiagnosticBag diagnostics, ImmutableArray< private BoundLambda ReallyInferReturnType(NamedTypeSymbol delegateType, ImmutableArray parameterTypes, ImmutableArray parameterRefKinds) { var diagnostics = DiagnosticBag.GetInstance(); - var lambdaSymbol = new LambdaSymbol(binder.Compilation, binder.ContainingMemberOrLambda, _unboundLambda, parameterTypes, parameterRefKinds, refKind: Microsoft.CodeAnalysis.RefKind.None, returnType: null); + var lambdaSymbol = new LambdaSymbol( + binder.Compilation, + binder.ContainingMemberOrLambda, + _unboundLambda, + parameterTypes, + parameterRefKinds, + refKind: CodeAnalysis.RefKind.None, + returnType: null, + diagnostics: diagnostics); Binder lambdaBodyBinder = new ExecutableCodeBinder(_unboundLambda.Syntax, lambdaSymbol, ParameterBinder(lambdaSymbol, binder)); var block = BindLambdaBody(lambdaSymbol, lambdaBodyBinder, diagnostics); diff --git a/src/Compilers/CSharp/Portable/CSharpCodeAnalysis.csproj b/src/Compilers/CSharp/Portable/CSharpCodeAnalysis.csproj index ecb9453ec414f..9aa65c8a48600 100644 --- a/src/Compilers/CSharp/Portable/CSharpCodeAnalysis.csproj +++ b/src/Compilers/CSharp/Portable/CSharpCodeAnalysis.csproj @@ -512,6 +512,7 @@ + diff --git a/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs b/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs index 66827478e7789..c92b4718da3ae 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs +++ b/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs @@ -4112,7 +4112,7 @@ internal static string ERR_ExplicitPropertyMissingAccessor { } /// - /// Looks up a localized string similar to Do not use 'System.Runtime.CompilerServices.ReadOnlyAttribute'. This is reserved for compiler usage.. + /// Looks up a localized string similar to Do not use 'System.Runtime.CompilerServices.IsReadOnlyAttribute'. This is reserved for compiler usage.. /// internal static string ERR_ExplicitReadOnlyAttr { get { @@ -9261,6 +9261,15 @@ internal static string ERR_TypeParamMustBeIdentifier { } } + /// + /// Looks up a localized string similar to The type name '{0}' is reserved to be used by the compiler.. + /// + internal static string ERR_TypeReserved { + get { + return ResourceManager.GetString("ERR_TypeReserved", resourceCulture); + } + } + /// /// Looks up a localized string similar to Cannot convert null to type parameter '{0}' because it could be a non-nullable value type. Consider using 'default({0})' instead.. /// diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index 197305d1bbe50..6064faf0c4b42 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.resx +++ b/src/Compilers/CSharp/Portable/CSharpResources.resx @@ -5115,6 +5115,9 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ An expression of type '{0}' cannot be handled by a pattern of type '{1}' in C# {2}. Please use language version {3} or greater. - Do not use 'System.Runtime.CompilerServices.ReadOnlyAttribute'. This is reserved for compiler usage. + Do not use 'System.Runtime.CompilerServices.IsReadOnlyAttribute'. This is reserved for compiler usage. + + + The type name '{0}' is reserved to be used by the compiler. diff --git a/src/Compilers/CSharp/Portable/Compilation/CSharpCompilation.cs b/src/Compilers/CSharp/Portable/Compilation/CSharpCompilation.cs index fb78b5a1e184c..3d69d2331b4b7 100644 --- a/src/Compilers/CSharp/Portable/Compilation/CSharpCompilation.cs +++ b/src/Compilers/CSharp/Portable/Compilation/CSharpCompilation.cs @@ -1988,6 +1988,10 @@ internal DiagnosticBag DeclarationDiagnostics private IEnumerable FreezeDeclarationDiagnostics() { _declarationDiagnosticsFrozen = true; + + // Also freeze that flag, as symbols bound after getting the declaration diagnostics shouldn't need to modify it + _needsGeneratedIsReadOnlyAttribute_IsFrozen = true; + var result = _lazyDeclarationDiagnostics?.AsEnumerable() ?? Enumerable.Empty(); return result; } diff --git a/src/Compilers/CSharp/Portable/Compiler/AnonymousTypeMethodBodySynthesizer.cs b/src/Compilers/CSharp/Portable/Compiler/AnonymousTypeMethodBodySynthesizer.cs index b3f3b9dd7ad36..dc20ab9e26a9b 100644 --- a/src/Compilers/CSharp/Portable/Compiler/AnonymousTypeMethodBodySynthesizer.cs +++ b/src/Compilers/CSharp/Portable/Compiler/AnonymousTypeMethodBodySynthesizer.cs @@ -29,7 +29,8 @@ internal override void GenerateMethodBody(TypeCompilationState compilationState, int statementIndex = 0; // explicit base constructor call - BoundExpression call = MethodCompiler.GenerateObjectConstructorInitializer(this, diagnostics); + Debug.Assert(ContainingType.BaseTypeNoUseSiteDiagnostics.SpecialType == SpecialType.System_Object); + BoundExpression call = MethodCompiler.GenerateBaseParameterlessConstructorInitializer(this, diagnostics); if (call == null) { // This may happen if Object..ctor is not found or is unaccessible diff --git a/src/Compilers/CSharp/Portable/Compiler/MethodCompiler.cs b/src/Compilers/CSharp/Portable/Compiler/MethodCompiler.cs index 5fe5afe4942d1..1b8fd11ead40e 100644 --- a/src/Compilers/CSharp/Portable/Compiler/MethodCompiler.cs +++ b/src/Compilers/CSharp/Portable/Compiler/MethodCompiler.cs @@ -145,7 +145,7 @@ public static void CompileMethodBodies( // compile additional and anonymous types if any if (moduleBeingBuiltOpt != null) { - var additionalTypes = moduleBeingBuiltOpt.GetAdditionalTopLevelTypes(); + var additionalTypes = moduleBeingBuiltOpt.GetAdditionalTopLevelTypes(diagnostics); if (!additionalTypes.IsEmpty) { methodCompiler.CompileSynthesizedMethods(additionalTypes, diagnostics); @@ -1715,7 +1715,7 @@ internal static BoundExpression BindConstructorInitializer( { if (baseType.SpecialType == SpecialType.System_Object) { - return GenerateObjectConstructorInitializer(constructor, diagnostics); + return GenerateBaseParameterlessConstructorInitializer(constructor, diagnostics); } else if (baseType.IsErrorType() || baseType.IsStatic) { @@ -1816,42 +1816,47 @@ private static SyntaxToken GetImplicitConstructorBodyToken(CSharpSyntaxNode cont } } - internal static BoundCall GenerateObjectConstructorInitializer(MethodSymbol constructor, DiagnosticBag diagnostics) + internal static BoundCall GenerateBaseParameterlessConstructorInitializer(MethodSymbol constructor, DiagnosticBag diagnostics) { - NamedTypeSymbol objectType = constructor.ContainingType.BaseTypeNoUseSiteDiagnostics; - Debug.Assert(objectType.SpecialType == SpecialType.System_Object); - MethodSymbol objectConstructor = null; + NamedTypeSymbol baseType = constructor.ContainingType.BaseTypeNoUseSiteDiagnostics; + MethodSymbol baseConstructor = null; LookupResultKind resultKind = LookupResultKind.Viable; + Location diagnosticsLocation = constructor.Locations.IsEmpty ? NoLocation.Singleton : constructor.Locations[0]; - foreach (MethodSymbol objectCtor in objectType.InstanceConstructors) + foreach (MethodSymbol ctor in baseType.InstanceConstructors) { - if (objectCtor.ParameterCount == 0) + if (ctor.ParameterCount == 0) { - objectConstructor = objectCtor; + baseConstructor = ctor; break; } } // UNDONE: If this happens then something is deeply wrong. Should we give a better error? - if ((object)objectConstructor == null) + if ((object)baseConstructor == null) + { + diagnostics.Add(ErrorCode.ERR_BadCtorArgCount, diagnosticsLocation, baseType, /*desired param count*/ 0); + return null; + } + + if (Binder.ReportUseSiteDiagnostics(baseConstructor, diagnostics, diagnosticsLocation)) { - diagnostics.Add(ErrorCode.ERR_BadCtorArgCount, constructor.Locations[0], objectType, /*desired param count*/ 0); return null; } // UNDONE: If this happens then something is deeply wrong. Should we give a better error? bool hasErrors = false; HashSet useSiteDiagnostics = null; - if (!AccessCheck.IsSymbolAccessible(objectConstructor, constructor.ContainingType, ref useSiteDiagnostics)) + if (!AccessCheck.IsSymbolAccessible(baseConstructor, constructor.ContainingType, ref useSiteDiagnostics)) { - diagnostics.Add(ErrorCode.ERR_BadAccess, constructor.Locations[0], objectConstructor); + diagnostics.Add(ErrorCode.ERR_BadAccess, diagnosticsLocation, baseConstructor); resultKind = LookupResultKind.Inaccessible; hasErrors = true; } if (!useSiteDiagnostics.IsNullOrEmpty()) { - diagnostics.Add(constructor.Locations.IsEmpty ? NoLocation.Singleton : constructor.Locations[0], useSiteDiagnostics); + diagnostics.Add(diagnosticsLocation, useSiteDiagnostics); } CSharpSyntaxNode syntax = constructor.GetNonNullSyntaxNode(); @@ -1860,7 +1865,7 @@ internal static BoundCall GenerateObjectConstructorInitializer(MethodSymbol cons return new BoundCall( syntax: syntax, receiverOpt: receiver, - method: objectConstructor, + method: baseConstructor, arguments: ImmutableArray.Empty, argumentNamesOpt: ImmutableArray.Empty, argumentRefKindsOpt: ImmutableArray.Empty, @@ -1869,7 +1874,7 @@ internal static BoundCall GenerateObjectConstructorInitializer(MethodSymbol cons invokedAsExtensionMethod: false, argsToParamsOpt: ImmutableArray.Empty, resultKind: resultKind, - type: objectType, + type: baseType, hasErrors: hasErrors) { WasCompilerGenerated = true }; } diff --git a/src/Compilers/CSharp/Portable/Emitter/Model/MethodSymbolAdapter.cs b/src/Compilers/CSharp/Portable/Emitter/Model/MethodSymbolAdapter.cs index 14ac29de0067e..d04241504ea9f 100644 --- a/src/Compilers/CSharp/Portable/Emitter/Model/MethodSymbolAdapter.cs +++ b/src/Compilers/CSharp/Portable/Emitter/Model/MethodSymbolAdapter.cs @@ -570,21 +570,13 @@ bool Cci.IMethodDefinition.RequiresSecurityObject } } - IEnumerable Cci.IMethodDefinition.ReturnValueAttributes - { - get - { - return GetReturnValueCustomAttributesToEmit(); - } - } - - private IEnumerable GetReturnValueCustomAttributesToEmit() + IEnumerable Cci.IMethodDefinition.GetReturnValueAttributes(EmitContext context) { CheckDefinitionInvariant(); ImmutableArray userDefined = this.GetReturnTypeAttributes(); ArrayBuilder synthesized = null; - this.AddSynthesizedReturnTypeAttributes(ref synthesized); + this.AddSynthesizedReturnTypeAttributes((PEModuleBuilder)context.Module, ref synthesized); // Note that callers of this method (CCI and ReflectionEmitter) have to enumerate // all items of the returned iterator, otherwise the synthesized ArrayBuilder may leak. diff --git a/src/Compilers/CSharp/Portable/Emitter/Model/PEAssemblyBuilder.cs b/src/Compilers/CSharp/Portable/Emitter/Model/PEAssemblyBuilder.cs index bf13d195f60c4..6a5905f3f5800 100644 --- a/src/Compilers/CSharp/Portable/Emitter/Model/PEAssemblyBuilder.cs +++ b/src/Compilers/CSharp/Portable/Emitter/Model/PEAssemblyBuilder.cs @@ -1,10 +1,13 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; using System.Reflection; +using System.Threading; +using Microsoft.Cci; using Microsoft.CodeAnalysis.CSharp.Symbols; using Microsoft.CodeAnalysis.Emit; using Roslyn.Utilities; @@ -17,6 +20,9 @@ internal abstract class PEAssemblyBuilderBase : PEModuleBuilder, Cci.IAssemblyRe private readonly ImmutableArray _additionalTypes; private ImmutableArray _lazyFiles; + private SynthesizedEmbeddedAttributeSymbol _lazyEmbeddedAttribute; + private SynthesizedEmbeddedAttributeSymbol _lazyIsReadOnlyAttribute; + /// /// The behavior of the C# command-line compiler is as follows: /// 1) If the /out switch is specified, then the explicit assembly name is used. @@ -56,9 +62,22 @@ public PEAssemblyBuilderBase( public override ISourceAssemblySymbolInternal SourceAssemblyOpt => _sourceAssembly; - internal override ImmutableArray GetAdditionalTopLevelTypes() + internal override ImmutableArray GetAdditionalTopLevelTypes(DiagnosticBag diagnostics) { - return _additionalTypes; + var builder = ArrayBuilder.GetInstance(); + builder.AddRange(_additionalTypes); + + CreateEmbeddedAttributesIfNeeded(diagnostics); + if ((object)_lazyEmbeddedAttribute != null) + { + builder.Add(_lazyEmbeddedAttribute); + } + if ((object)_lazyIsReadOnlyAttribute != null) + { + builder.Add(_lazyIsReadOnlyAttribute); + } + + return builder.ToImmutableAndFree(); } public sealed override IEnumerable GetFiles(EmitContext context) @@ -131,6 +150,65 @@ protected override void AddEmbeddedResourcesFromAddedModules(ArrayBuilder _metadataName; public AssemblyIdentity Identity => _sourceAssembly.Identity; public Version AssemblyVersionPattern => _sourceAssembly.AssemblyVersionPattern; + + internal override SynthesizedAttributeData SynthesizeEmbeddedAttribute() + { + if ((object)_lazyEmbeddedAttribute != null) + { + return new SynthesizedAttributeData( + _lazyEmbeddedAttribute.Constructor, + ImmutableArray.Empty, + ImmutableArray>.Empty); + } + + return base.SynthesizeEmbeddedAttribute(); + } + + protected override SynthesizedAttributeData TrySynthesizeIsReadOnlyAttribute() + { + if ((object)_lazyIsReadOnlyAttribute != null) + { + return new SynthesizedAttributeData( + _lazyIsReadOnlyAttribute.Constructor, + ImmutableArray.Empty, + ImmutableArray>.Empty); + } + + return base.TrySynthesizeIsReadOnlyAttribute(); + } + + private void CreateEmbeddedAttributesIfNeeded(DiagnosticBag diagnostics) + { + if (this.NeedsGeneratedIsReadOnlyAttribute) + { + CreateEmbeddedAttributeIfNeeded( + ref _lazyEmbeddedAttribute, + diagnostics, + AttributeDescription.CodeAnalysisEmbeddedAttribute); + + CreateEmbeddedAttributeIfNeeded( + ref _lazyIsReadOnlyAttribute, + diagnostics, + AttributeDescription.IsReadOnlyAttribute); + } + } + + private void CreateEmbeddedAttributeIfNeeded(ref SynthesizedEmbeddedAttributeSymbol symbol, DiagnosticBag diagnostics, AttributeDescription description) + { + if ((object)symbol == null) + { + var attributeMetadataName = MetadataTypeName.FromFullName(description.FullName); + var userDefinedAttribute = _sourceAssembly.SourceModule.LookupTopLevelMetadataType(ref attributeMetadataName); + Debug.Assert((object)userDefinedAttribute.ContainingModule == _sourceAssembly.SourceModule); + + if (!(userDefinedAttribute is MissingMetadataTypeSymbol)) + { + diagnostics.Add(ErrorCode.ERR_TypeReserved, userDefinedAttribute.Locations[0], description.FullName); + } + + symbol = new SynthesizedEmbeddedAttributeSymbol(description, _sourceAssembly.DeclaringCompilation, diagnostics); + } + } } internal sealed class PEAssemblyBuilder : PEAssemblyBuilderBase diff --git a/src/Compilers/CSharp/Portable/Emitter/Model/PEModuleBuilder.cs b/src/Compilers/CSharp/Portable/Emitter/Model/PEModuleBuilder.cs index 1f6765b2b9526..ae073a78cc312 100644 --- a/src/Compilers/CSharp/Portable/Emitter/Model/PEModuleBuilder.cs +++ b/src/Compilers/CSharp/Portable/Emitter/Model/PEModuleBuilder.cs @@ -40,6 +40,23 @@ public override NoPia.EmbeddedTypesManager EmbeddedTypesManagerOpt /// private Dictionary _fixedImplementationTypes; + private bool _needsGeneratedIsReadOnlyAttribute_IsFrozen; + private bool _needsGeneratedIsReadOnlyAttribute_Value; + + /// + /// Returns a value indicating whether this builder has a symbol that needs IsReadOnlyAttribute to be generated during emit phase. + /// The value is set during lowering the symbols that need that attribute, and is frozen on first trial to get it. + /// Freezing is needed to make sure that nothing tries to modify the value after the value is read. + /// + internal bool NeedsGeneratedIsReadOnlyAttribute + { + get + { + _needsGeneratedIsReadOnlyAttribute_IsFrozen = true; + return Compilation.NeedsGeneratedIsReadOnlyAttribute || _needsGeneratedIsReadOnlyAttribute_Value; + } + } + internal PEModuleBuilder( SourceModuleSymbol sourceModule, EmitOptions emitOptions, @@ -86,7 +103,7 @@ internal sealed override Cci.ICustomAttribute SynthesizeAttribute(WellKnownMembe public sealed override IEnumerable GetSourceAssemblyAttributes(bool isRefAssembly) { return SourceModule.ContainingSourceAssembly - .GetCustomAttributesToEmit(this.CompilationState, isRefAssembly, emittingAssemblyAttributesInNetModule: OutputKind.IsNetModule()); + .GetCustomAttributesToEmit(this, isRefAssembly, emittingAssemblyAttributesInNetModule: OutputKind.IsNetModule()); } public sealed override IEnumerable GetSourceAssemblySecurityAttributes() @@ -96,7 +113,7 @@ internal sealed override Cci.ICustomAttribute SynthesizeAttribute(WellKnownMembe public sealed override IEnumerable GetSourceModuleAttributes() { - return SourceModule.GetCustomAttributesToEmit(this.CompilationState); + return SourceModule.GetCustomAttributesToEmit(this); } internal sealed override AssemblySymbol CorLibrary @@ -377,9 +394,9 @@ internal virtual bool IsEncDelta get { return false; } } - internal override IEnumerable GetTopLevelTypesCore(CodeAnalysis.Emit.EmitContext context) + internal override IEnumerable GetTopLevelTypesCore(EmitContext context) { - foreach (var type in GetAdditionalTopLevelTypes()) + foreach (var type in GetAdditionalTopLevelTypes(context.Diagnostics)) { yield return type; } @@ -406,7 +423,7 @@ internal virtual bool IsEncDelta } } - internal virtual ImmutableArray GetAdditionalTopLevelTypes() + internal virtual ImmutableArray GetAdditionalTopLevelTypes(DiagnosticBag diagnostics) { return ImmutableArray.Empty; } @@ -1386,5 +1403,43 @@ protected override Cci.IMethodDefinition CreatePrivateImplementationDetailsStati { return new SynthesizedPrivateImplementationDetailsStaticConstructor(SourceModule, details, GetUntranslatedSpecialType(SpecialType.System_Void, syntaxOpt, diagnostics)); } + + internal virtual SynthesizedAttributeData SynthesizeEmbeddedAttribute() + { + // Embedded attributes should never be synthesized in modules. + throw ExceptionUtilities.Unreachable; + } + + internal SynthesizedAttributeData SynthesizeIsReadOnlyAttribute(Symbol symbol) + { + if ((object)Compilation.SourceModule != symbol.ContainingModule) + { + // For symbols that are not defined in the same compilation (like NoPia), don't synthesize this attribute. + return null; + } + + return TrySynthesizeIsReadOnlyAttribute(); + } + + protected virtual SynthesizedAttributeData TrySynthesizeIsReadOnlyAttribute() + { + // For modules, this attribute should be present. Only assemblies generate and embed this type. + return Compilation.TrySynthesizeAttribute(WellKnownMember.System_Runtime_CompilerServices_IsReadOnlyAttribute__ctor); + } + + internal void EnsureIsReadOnlyAttributeExists() + { + if (_needsGeneratedIsReadOnlyAttribute_Value || Compilation.NeedsGeneratedIsReadOnlyAttribute) + { + return; + } + + // Don't report any errors. They should be reported during binding. + if (Compilation.CheckIfIsReadOnlyAttributeShouldBeEmbedded(diagnosticsOpt: null, locationOpt: null)) + { + Debug.Assert(!_needsGeneratedIsReadOnlyAttribute_IsFrozen); + _needsGeneratedIsReadOnlyAttribute_Value = true; + } + } } } diff --git a/src/Compilers/CSharp/Portable/Emitter/Model/SourceAssemblySymbolAdapter.cs b/src/Compilers/CSharp/Portable/Emitter/Model/SourceAssemblySymbolAdapter.cs index e93fc7cdcc63f..a60d598898661 100644 --- a/src/Compilers/CSharp/Portable/Emitter/Model/SourceAssemblySymbolAdapter.cs +++ b/src/Compilers/CSharp/Portable/Emitter/Model/SourceAssemblySymbolAdapter.cs @@ -2,18 +2,19 @@ using System.Collections.Generic; using System.Collections.Immutable; +using Microsoft.CodeAnalysis.CSharp.Emit; namespace Microsoft.CodeAnalysis.CSharp.Symbols { internal partial class SourceAssemblySymbol { - internal IEnumerable GetCustomAttributesToEmit(ModuleCompilationState compilationState, bool emittingRefAssembly, bool emittingAssemblyAttributesInNetModule) + internal IEnumerable GetCustomAttributesToEmit(PEModuleBuilder moduleBuilder, bool emittingRefAssembly, bool emittingAssemblyAttributesInNetModule) { CheckDefinitionInvariant(); ImmutableArray userDefined = this.GetAttributes(); ArrayBuilder synthesized = null; - this.AddSynthesizedAttributes(compilationState, ref synthesized); + this.AddSynthesizedAttributes(moduleBuilder, ref synthesized); if (emittingRefAssembly && !HasReferenceAssemblyAttribute) { diff --git a/src/Compilers/CSharp/Portable/Emitter/Model/SymbolAdapter.cs b/src/Compilers/CSharp/Portable/Emitter/Model/SymbolAdapter.cs index 1395f36244021..966134ebea971 100644 --- a/src/Compilers/CSharp/Portable/Emitter/Model/SymbolAdapter.cs +++ b/src/Compilers/CSharp/Portable/Emitter/Model/SymbolAdapter.cs @@ -52,18 +52,18 @@ internal bool IsDefinitionOrDistinct() IEnumerable Cci.IReference.GetAttributes(EmitContext context) { - return GetCustomAttributesToEmit(((PEModuleBuilder)context.Module).CompilationState); + return GetCustomAttributesToEmit((PEModuleBuilder)context.Module); } - internal virtual IEnumerable GetCustomAttributesToEmit(ModuleCompilationState compilationState) + internal virtual IEnumerable GetCustomAttributesToEmit(PEModuleBuilder moduleBuilder) { CheckDefinitionInvariant(); Debug.Assert(this.Kind != SymbolKind.Assembly); - return GetCustomAttributesToEmit(compilationState, emittingAssemblyAttributesInNetModule: false); + return GetCustomAttributesToEmit(moduleBuilder, emittingAssemblyAttributesInNetModule: false); } - internal IEnumerable GetCustomAttributesToEmit(ModuleCompilationState compilationState, bool emittingAssemblyAttributesInNetModule) + internal IEnumerable GetCustomAttributesToEmit(PEModuleBuilder moduleBuilder, bool emittingAssemblyAttributesInNetModule) { CheckDefinitionInvariant(); Debug.Assert(this.Kind != SymbolKind.Assembly); @@ -71,7 +71,7 @@ internal IEnumerable GetCustomAttributesToEmit(ModuleCompil ImmutableArray userDefined; ArrayBuilder synthesized = null; userDefined = this.GetAttributes(); - this.AddSynthesizedAttributes(compilationState, ref synthesized); + this.AddSynthesizedAttributes(moduleBuilder, ref synthesized); // Note that callers of this method (CCI and ReflectionEmitter) have to enumerate // all items of the returned iterator, otherwise the synthesized ArrayBuilder may leak. diff --git a/src/Compilers/CSharp/Portable/Emitter/NoPia/EmbeddedEvent.cs b/src/Compilers/CSharp/Portable/Emitter/NoPia/EmbeddedEvent.cs index fa8bf34b3bcbd..742d21ba7c1b3 100644 --- a/src/Compilers/CSharp/Portable/Emitter/NoPia/EmbeddedEvent.cs +++ b/src/Compilers/CSharp/Portable/Emitter/NoPia/EmbeddedEvent.cs @@ -12,9 +12,9 @@ public EmbeddedEvent(EventSymbol underlyingEvent, EmbeddedMethod adder, Embedded { } - protected override IEnumerable GetCustomAttributesToEmit(ModuleCompilationState compilationState) + protected override IEnumerable GetCustomAttributesToEmit(PEModuleBuilder moduleBuilder) { - return UnderlyingEvent.GetCustomAttributesToEmit(compilationState); + return UnderlyingEvent.GetCustomAttributesToEmit(moduleBuilder); } protected override bool IsRuntimeSpecial diff --git a/src/Compilers/CSharp/Portable/Emitter/NoPia/EmbeddedField.cs b/src/Compilers/CSharp/Portable/Emitter/NoPia/EmbeddedField.cs index 96d1a65f56902..b160a4c5e801c 100644 --- a/src/Compilers/CSharp/Portable/Emitter/NoPia/EmbeddedField.cs +++ b/src/Compilers/CSharp/Portable/Emitter/NoPia/EmbeddedField.cs @@ -23,9 +23,9 @@ internal override EmbeddedTypesManager TypeManager } } - protected override IEnumerable GetCustomAttributesToEmit(ModuleCompilationState compilationState) + protected override IEnumerable GetCustomAttributesToEmit(PEModuleBuilder moduleBuilder) { - return UnderlyingField.GetCustomAttributesToEmit(compilationState); + return UnderlyingField.GetCustomAttributesToEmit(moduleBuilder); } protected override MetadataConstant GetCompileTimeValue(EmitContext context) diff --git a/src/Compilers/CSharp/Portable/Emitter/NoPia/EmbeddedMethod.cs b/src/Compilers/CSharp/Portable/Emitter/NoPia/EmbeddedMethod.cs index ffb916b85552d..8c6306fd32956 100644 --- a/src/Compilers/CSharp/Portable/Emitter/NoPia/EmbeddedMethod.cs +++ b/src/Compilers/CSharp/Portable/Emitter/NoPia/EmbeddedMethod.cs @@ -24,9 +24,9 @@ internal override EmbeddedTypesManager TypeManager } } - protected override IEnumerable GetCustomAttributesToEmit(ModuleCompilationState compilationState) + protected override IEnumerable GetCustomAttributesToEmit(PEModuleBuilder moduleBuilder) { - return UnderlyingMethod.GetCustomAttributesToEmit(compilationState); + return UnderlyingMethod.GetCustomAttributesToEmit(moduleBuilder); } protected override ImmutableArray GetParameters() diff --git a/src/Compilers/CSharp/Portable/Emitter/NoPia/EmbeddedParameter.cs b/src/Compilers/CSharp/Portable/Emitter/NoPia/EmbeddedParameter.cs index ad4be13a44b4a..64ab165c7f27d 100644 --- a/src/Compilers/CSharp/Portable/Emitter/NoPia/EmbeddedParameter.cs +++ b/src/Compilers/CSharp/Portable/Emitter/NoPia/EmbeddedParameter.cs @@ -27,9 +27,9 @@ protected override bool HasDefaultValue } } - protected override IEnumerable GetCustomAttributesToEmit(ModuleCompilationState compilationState) + protected override IEnumerable GetCustomAttributesToEmit(PEModuleBuilder moduleBuilder) { - return UnderlyingParameter.GetCustomAttributesToEmit(compilationState); + return UnderlyingParameter.GetCustomAttributesToEmit(moduleBuilder); } protected override MetadataConstant GetDefaultValue(EmitContext context) diff --git a/src/Compilers/CSharp/Portable/Emitter/NoPia/EmbeddedProperty.cs b/src/Compilers/CSharp/Portable/Emitter/NoPia/EmbeddedProperty.cs index 1edef3c683931..cf822da4a37a9 100644 --- a/src/Compilers/CSharp/Portable/Emitter/NoPia/EmbeddedProperty.cs +++ b/src/Compilers/CSharp/Portable/Emitter/NoPia/EmbeddedProperty.cs @@ -14,9 +14,9 @@ public EmbeddedProperty(PropertySymbol underlyingProperty, EmbeddedMethod getter { } - protected override IEnumerable GetCustomAttributesToEmit(ModuleCompilationState compilationState) + protected override IEnumerable GetCustomAttributesToEmit(PEModuleBuilder moduleBuilder) { - return UnderlyingProperty.GetCustomAttributesToEmit(compilationState); + return UnderlyingProperty.GetCustomAttributesToEmit(moduleBuilder); } protected override ImmutableArray GetParameters() diff --git a/src/Compilers/CSharp/Portable/Emitter/NoPia/EmbeddedType.cs b/src/Compilers/CSharp/Portable/Emitter/NoPia/EmbeddedType.cs index d9e3414a0dfc2..c0273835f3228 100644 --- a/src/Compilers/CSharp/Portable/Emitter/NoPia/EmbeddedType.cs +++ b/src/Compilers/CSharp/Portable/Emitter/NoPia/EmbeddedType.cs @@ -201,9 +201,9 @@ protected override System.Runtime.InteropServices.CharSet StringFormat } } - protected override IEnumerable GetCustomAttributesToEmit(ModuleCompilationState compilationState) + protected override IEnumerable GetCustomAttributesToEmit(PEModuleBuilder moduleBuilder) { - return UnderlyingNamedType.GetCustomAttributesToEmit(compilationState); + return UnderlyingNamedType.GetCustomAttributesToEmit(moduleBuilder); } protected override CSharpAttributeData CreateTypeIdentifierAttribute(bool hasGuid, SyntaxNode syntaxNodeOpt, DiagnosticBag diagnostics) diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs index 6b6fa05d70e12..cee7288cb3f52 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs @@ -1503,5 +1503,6 @@ internal enum ErrorCode ERR_RefReturnReadonlyNotField = 8410, ERR_RefReturnReadonlyNotField2 = 8411, ERR_ExplicitReadOnlyAttr = 8412, + ERR_TypeReserved = 8413, } } diff --git a/src/Compilers/CSharp/Portable/Lowering/IteratorRewriter/IteratorConstructor.cs b/src/Compilers/CSharp/Portable/Lowering/IteratorRewriter/IteratorConstructor.cs index 257039682364c..4c218f8fbc512 100644 --- a/src/Compilers/CSharp/Portable/Lowering/IteratorRewriter/IteratorConstructor.cs +++ b/src/Compilers/CSharp/Portable/Lowering/IteratorRewriter/IteratorConstructor.cs @@ -22,9 +22,9 @@ internal IteratorConstructor(IteratorStateMachine container) SynthesizedParameterSymbol.Create(this, intType, 0, RefKind.None, GeneratedNames.MakeStateMachineStateFieldName())); } - internal override void AddSynthesizedAttributes(ModuleCompilationState compilationState, ref ArrayBuilder attributes) + internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, ref ArrayBuilder attributes) { - base.AddSynthesizedAttributes(compilationState, ref attributes); + base.AddSynthesizedAttributes(moduleBuilder, ref attributes); var compilation = this.DeclaringCompilation; AddSynthesizedAttribute(ref attributes, compilation.TrySynthesizeAttribute(WellKnownMember.System_Diagnostics_DebuggerHiddenAttribute__ctor)); diff --git a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter.cs b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter.cs index 3ef735c25087b..ef68dc0e4246c 100644 --- a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter.cs +++ b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter.cs @@ -189,6 +189,8 @@ private BoundExpression VisitExpressionImpl(BoundExpression node) public override BoundNode VisitLambda(BoundLambda node) { _sawLambdas = true; + CheckRefReadOnlySymbols(node.Symbol); + var oldContainingSymbol = _factory.CurrentMethod; try { @@ -204,6 +206,8 @@ public override BoundNode VisitLambda(BoundLambda node) public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatement node) { _sawLocalFunctions = true; + CheckRefReadOnlySymbols(node.Symbol); + var oldContainingSymbol = _factory.CurrentMethod; try { @@ -555,5 +559,31 @@ internal static bool WouldBeAssignableIfUsedAsMethodReceiver(BoundExpression rec return false; } + + private void CheckRefReadOnlySymbols(MethodSymbol symbol) + { + var foundRefReadOnly = false; + + if (symbol.ReturnsByRefReadonly) + { + foundRefReadOnly = true; + } + else + { + foreach (var parameter in symbol.Parameters) + { + if (parameter.RefKind == RefKind.RefReadOnly) + { + foundRefReadOnly = true; + break; + } + } + } + + if (foundRefReadOnly) + { + _factory.CompilationState.ModuleBuilderOpt?.EnsureIsReadOnlyAttributeExists(); + } + } } } diff --git a/src/Compilers/CSharp/Portable/Lowering/MethodToClassRewriter.cs b/src/Compilers/CSharp/Portable/Lowering/MethodToClassRewriter.cs index 4b8e2d4becf59..3938c58fcf093 100644 --- a/src/Compilers/CSharp/Portable/Lowering/MethodToClassRewriter.cs +++ b/src/Compilers/CSharp/Portable/Lowering/MethodToClassRewriter.cs @@ -4,6 +4,7 @@ using System.Collections.Immutable; using System.Diagnostics; using Microsoft.CodeAnalysis.CodeGen; +using Microsoft.CodeAnalysis.CSharp.Emit; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.CSharp.Symbols @@ -670,9 +671,9 @@ internal BaseMethodWrapperSymbol(NamedTypeSymbol containingType, MethodSymbol me AssignTypeMapAndTypeParameters(typeMap, typeParameters); } - internal override void AddSynthesizedAttributes(ModuleCompilationState compilationState, ref ArrayBuilder attributes) + internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, ref ArrayBuilder attributes) { - base.AddSynthesizedAttributes(compilationState, ref attributes); + base.AddSynthesizedAttributes(moduleBuilder, ref attributes); AddSynthesizedAttribute(ref attributes, this.DeclaringCompilation.TrySynthesizeAttribute(WellKnownMember.System_Diagnostics_DebuggerHiddenAttribute__ctor)); } diff --git a/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/StateMachineTypeSymbol.cs b/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/StateMachineTypeSymbol.cs index 77828b1f270b5..340460ae1900e 100644 --- a/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/StateMachineTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/StateMachineTypeSymbol.cs @@ -91,5 +91,7 @@ public sealed override ImmutableArray GetAttributes() return _attributes; } + + internal override bool HasCodeAnalysisEmbeddedAttribute => false; } } diff --git a/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/SynthesizedStateMachineMethod.cs b/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/SynthesizedStateMachineMethod.cs index b90d6af8f4ada..3f23b36bf93e9 100644 --- a/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/SynthesizedStateMachineMethod.cs +++ b/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/SynthesizedStateMachineMethod.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Immutable; using System.Diagnostics; +using Microsoft.CodeAnalysis.CSharp.Emit; using Microsoft.CodeAnalysis.CSharp.Symbols; namespace Microsoft.CodeAnalysis.CSharp @@ -111,12 +112,12 @@ public SynthesizedStateMachineDebuggerHiddenMethod( { } - internal sealed override void AddSynthesizedAttributes(ModuleCompilationState compilationState, ref ArrayBuilder attributes) + internal sealed override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, ref ArrayBuilder attributes) { var compilation = this.DeclaringCompilation; AddSynthesizedAttribute(ref attributes, compilation.TrySynthesizeAttribute(WellKnownMember.System_Diagnostics_DebuggerHiddenAttribute__ctor)); - base.AddSynthesizedAttributes(compilationState, ref attributes); + base.AddSynthesizedAttributes(moduleBuilder, ref attributes); } } } diff --git a/src/Compilers/CSharp/Portable/Lowering/SynthesizedMethodBaseSymbol.cs b/src/Compilers/CSharp/Portable/Lowering/SynthesizedMethodBaseSymbol.cs index 24f3d108d9b69..c8ab9900c0778 100644 --- a/src/Compilers/CSharp/Portable/Lowering/SynthesizedMethodBaseSymbol.cs +++ b/src/Compilers/CSharp/Portable/Lowering/SynthesizedMethodBaseSymbol.cs @@ -58,9 +58,9 @@ protected override void MethodChecks(DiagnosticBag diagnostics) // TODO: move more functionality into here, making these symbols more lazy } - internal override void AddSynthesizedAttributes(ModuleCompilationState compilationState, ref ArrayBuilder attributes) + internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, ref ArrayBuilder attributes) { - base.AddSynthesizedAttributes(compilationState, ref attributes); + base.AddSynthesizedAttributes(moduleBuilder, ref attributes); // do not generate attributes for members of compiler-generated types: if (ContainingType.IsImplicitlyDeclared) diff --git a/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/PublicSymbols/AnonymousType.TypePublicSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/PublicSymbols/AnonymousType.TypePublicSymbol.cs index fb885a1d184ab..3f5fb694111f5 100644 --- a/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/PublicSymbols/AnonymousType.TypePublicSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/PublicSymbols/AnonymousType.TypePublicSymbol.cs @@ -111,6 +111,8 @@ internal override bool HasTypeArgumentsCustomModifiers } } + internal override bool HasCodeAnalysisEmbeddedAttribute => false; + public override ImmutableArray GetTypeArgumentCustomModifiers(int ordinal) { return GetEmptyTypeArgumentCustomModifiers(ordinal); diff --git a/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/SynthesizedSymbols/AnonymousType.FieldSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/SynthesizedSymbols/AnonymousType.FieldSymbol.cs index c5efc835f1557..044afb48741b2 100644 --- a/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/SynthesizedSymbols/AnonymousType.FieldSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/SynthesizedSymbols/AnonymousType.FieldSymbol.cs @@ -136,9 +136,9 @@ public override bool IsImplicitlyDeclared get { return true; } } - internal override void AddSynthesizedAttributes(ModuleCompilationState compilationState, ref ArrayBuilder attributes) + internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, ref ArrayBuilder attributes) { - base.AddSynthesizedAttributes(compilationState, ref attributes); + base.AddSynthesizedAttributes(moduleBuilder, ref attributes); AnonymousTypeManager manager = ((AnonymousTypeTemplateSymbol)this.ContainingSymbol).Manager; diff --git a/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/SynthesizedSymbols/AnonymousType.PropertyAccessorSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/SynthesizedSymbols/AnonymousType.PropertyAccessorSymbol.cs index a3336e7f3fa7a..2c4b7b92348fa 100644 --- a/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/SynthesizedSymbols/AnonymousType.PropertyAccessorSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/SynthesizedSymbols/AnonymousType.PropertyAccessorSymbol.cs @@ -78,7 +78,7 @@ internal override bool IsMetadataFinal } } - internal override void AddSynthesizedAttributes(ModuleCompilationState compilationState, ref ArrayBuilder attributes) + internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, ref ArrayBuilder attributes) { // Do not call base.AddSynthesizedAttributes. // Dev11 does not emit DebuggerHiddenAttribute in property accessors diff --git a/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/SynthesizedSymbols/AnonymousType.SynthesizedMethodBase.cs b/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/SynthesizedSymbols/AnonymousType.SynthesizedMethodBase.cs index 944cfd2928b54..6b2a6047b1e9d 100644 --- a/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/SynthesizedSymbols/AnonymousType.SynthesizedMethodBase.cs +++ b/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/SynthesizedSymbols/AnonymousType.SynthesizedMethodBase.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Collections.Immutable; +using Microsoft.CodeAnalysis.CSharp.Emit; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.CSharp.Symbols @@ -155,9 +156,9 @@ internal sealed override bool IsMetadataNewSlot(bool ignoreInterfaceImplementati return false; } - internal override void AddSynthesizedAttributes(ModuleCompilationState compilationState, ref ArrayBuilder attributes) + internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, ref ArrayBuilder attributes) { - base.AddSynthesizedAttributes(compilationState, ref attributes); + base.AddSynthesizedAttributes(moduleBuilder, ref attributes); AddSynthesizedAttribute(ref attributes, Manager.Compilation.TrySynthesizeAttribute( WellKnownMember.System_Diagnostics_DebuggerHiddenAttribute__ctor)); diff --git a/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/SynthesizedSymbols/AnonymousType.TemplateSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/SynthesizedSymbols/AnonymousType.TemplateSymbol.cs index 1b91c53ab583c..b72a7bd60316d 100644 --- a/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/SynthesizedSymbols/AnonymousType.TemplateSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/SynthesizedSymbols/AnonymousType.TemplateSymbol.cs @@ -7,6 +7,7 @@ using System.Runtime.InteropServices; using System.Threading; using Microsoft.CodeAnalysis.Collections; +using Microsoft.CodeAnalysis.CSharp.Emit; using Microsoft.CodeAnalysis.Emit; using Roslyn.Utilities; @@ -212,6 +213,8 @@ internal override IEnumerable GetFieldsToEmit() } } + internal override bool HasCodeAnalysisEmbeddedAttribute => false; + internal override ImmutableArray TypeArgumentsNoUseSiteDiagnostics { get { return StaticCast.From(this.TypeParameters); } @@ -440,9 +443,9 @@ internal override AttributeUsageInfo GetAttributeUsageInfo() return AttributeUsageInfo.Null; } - internal override void AddSynthesizedAttributes(ModuleCompilationState compilationState, ref ArrayBuilder attributes) + internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, ref ArrayBuilder attributes) { - base.AddSynthesizedAttributes(compilationState, ref attributes); + base.AddSynthesizedAttributes(moduleBuilder, ref attributes); AddSynthesizedAttribute(ref attributes, Manager.Compilation.TrySynthesizeAttribute( WellKnownMember.System_Runtime_CompilerServices_CompilerGeneratedAttribute__ctor)); diff --git a/src/Compilers/CSharp/Portable/Symbols/AssemblySymbol.cs b/src/Compilers/CSharp/Portable/Symbols/AssemblySymbol.cs index bb52a85859669..a2b387eccd207 100644 --- a/src/Compilers/CSharp/Portable/Symbols/AssemblySymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/AssemblySymbol.cs @@ -777,6 +777,11 @@ internal NamedTypeSymbol GetTopLevelTypeByMetadataName( continue; } + if (candidate.IsHiddenByCodeAnalysisEmbeddedAttribute()) + { + continue; + } + Debug.Assert(candidate != result); if ((object)result != null) diff --git a/src/Compilers/CSharp/Portable/Symbols/Compilation_WellKnownMembers.cs b/src/Compilers/CSharp/Portable/Symbols/Compilation_WellKnownMembers.cs index 2a46f6edf97e2..838e9f04d8c68 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Compilation_WellKnownMembers.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Compilation_WellKnownMembers.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; +using System.Linq; using System.Threading; using Microsoft.CodeAnalysis.CSharp.Symbols; using Microsoft.CodeAnalysis.RuntimeMembers; @@ -30,6 +31,23 @@ public partial class CSharpCompilation /// private Symbol[] _lazyWellKnownTypeMembers; + private bool _needsGeneratedIsReadOnlyAttribute_IsFrozen; + private bool _needsGeneratedIsReadOnlyAttribute_Value; + + /// + /// Returns a value indicating whether this compilation has a member that needs IsReadOnlyAttribute to be generated during emit phase. + /// The value is set during binding the symbols that need that attribute, and is frozen on first trial to get it. + /// Freezing is needed to make sure that nothing tries to modify the value after the value is read. + /// + internal bool NeedsGeneratedIsReadOnlyAttribute + { + get + { + _needsGeneratedIsReadOnlyAttribute_IsFrozen = true; + return _needsGeneratedIsReadOnlyAttribute_Value; + } + } + /// /// Lookup member declaration in well known type used by this Compilation. /// @@ -415,10 +433,44 @@ internal SynthesizedAttributeData SynthesizeDebuggerStepThroughAttribute() return TrySynthesizeAttribute(WellKnownMember.System_Diagnostics_DebuggerStepThroughAttribute__ctor); } - internal SynthesizedAttributeData SynthesizeReadOnlyAttribute() + internal void EnsureIsReadOnlyAttributeExists(DiagnosticBag diagnostics, Location location, bool modifyCompilationForRefReadOnly) + { + Debug.Assert(!modifyCompilationForRefReadOnly || !_needsGeneratedIsReadOnlyAttribute_IsFrozen); + + var isNeeded = CheckIfIsReadOnlyAttributeShouldBeEmbedded(diagnostics, location); + + if (isNeeded && modifyCompilationForRefReadOnly) + { + _needsGeneratedIsReadOnlyAttribute_Value = true; + } + } + + internal bool CheckIfIsReadOnlyAttributeShouldBeEmbedded(DiagnosticBag diagnosticsOpt, Location locationOpt) { - // PROTOTYPE(readonlyRefs) it is optional now as it will be generated in the next PR - return TrySynthesizeAttribute(WellKnownMember.System_Runtime_CompilerServices_ReadOnlyAttribute__ctor, isOptionalUse: true); + var userDefinedAttribute = GetWellKnownType(WellKnownType.System_Runtime_CompilerServices_IsReadOnlyAttribute); + + if (userDefinedAttribute is MissingMetadataTypeSymbol) + { + if (Options.OutputKind == OutputKind.NetModule) + { + if (diagnosticsOpt != null) + { + var errorReported = Binder.ReportUseSiteDiagnostics(userDefinedAttribute, diagnosticsOpt, locationOpt); + Debug.Assert(errorReported); + } + } + else + { + return true; + } + } + else if (diagnosticsOpt != null) + { + // This should produce diagnostics if the member is missing or bad + Binder.GetWellKnownTypeMember(this, WellKnownMember.System_Runtime_CompilerServices_IsReadOnlyAttribute__ctor, diagnosticsOpt, locationOpt); + } + + return false; } internal SynthesizedAttributeData SynthesizeDebuggableAttribute() diff --git a/src/Compilers/CSharp/Portable/Symbols/ErrorTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/ErrorTypeSymbol.cs index b32b91d07d295..d7451235dd9ff 100644 --- a/src/Compilers/CSharp/Portable/Symbols/ErrorTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/ErrorTypeSymbol.cs @@ -421,6 +421,8 @@ internal override NamedTypeSymbol BaseTypeNoUseSiteDiagnostics get { return null; } } + internal override bool HasCodeAnalysisEmbeddedAttribute => false; + internal override ImmutableArray InterfacesNoUseSiteDiagnostics(ConsList basesBeingResolved) { return ImmutableArray.Empty; diff --git a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEEventSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEEventSymbol.cs index a9c717e311184..accb82034df90 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEEventSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEEventSymbol.cs @@ -10,6 +10,7 @@ using System.Reflection; using System.Reflection.Metadata; using System.Threading; +using Microsoft.CodeAnalysis.CSharp.Emit; namespace Microsoft.CodeAnalysis.CSharp.Symbols.Metadata.PE { @@ -349,7 +350,7 @@ public override ImmutableArray GetAttributes() return _lazyCustomAttributes; } - internal override IEnumerable GetCustomAttributesToEmit(ModuleCompilationState compilationState) + internal override IEnumerable GetCustomAttributesToEmit(PEModuleBuilder moduleBuilder) { return GetAttributes(); } diff --git a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEFieldSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEFieldSymbol.cs index 627410417a718..9cf412f5e762a 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEFieldSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEFieldSymbol.cs @@ -467,7 +467,7 @@ private bool FilterOutDecimalConstantAttribute() value.Discriminator == ConstantValueTypeDiscriminator.Decimal; } - internal override IEnumerable GetCustomAttributesToEmit(ModuleCompilationState compilationState) + internal override IEnumerable GetCustomAttributesToEmit(PEModuleBuilder moduleBuilder) { foreach (CSharpAttributeData attribute in GetAttributes()) { diff --git a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEMethodSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEMethodSymbol.cs index 356fd02ba3470..5866a4e4b7354 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEMethodSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEMethodSymbol.cs @@ -10,6 +10,7 @@ using System.Reflection.Metadata; using Microsoft.CodeAnalysis.CSharp.DocumentationComments; using Roslyn.Utilities; +using Microsoft.CodeAnalysis.CSharp.Emit; namespace Microsoft.CodeAnalysis.CSharp.Symbols.Metadata.PE { @@ -754,7 +755,7 @@ public override ImmutableArray GetAttributes() } } - internal override IEnumerable GetCustomAttributesToEmit(ModuleCompilationState compilationState) => GetAttributes(); + internal override IEnumerable GetCustomAttributesToEmit(PEModuleBuilder moduleBuilder) => GetAttributes(); public override ImmutableArray GetReturnTypeAttributes() => Signature.ReturnParam.GetAttributes(); diff --git a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PENamedTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PENamedTypeSymbol.cs index 4f54577dcae94..58e2341c21f8e 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PENamedTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PENamedTypeSymbol.cs @@ -132,6 +132,7 @@ private class UncommonProperties internal ThreeState lazyIsByRefLike; internal string lazyDefaultMemberName; internal NamedTypeSymbol lazyComImportCoClassType = ErrorTypeSymbol.UnknownResultType; + internal ThreeState lazyHasEmbeddedAttribute = ThreeState.Unknown; internal bool IsDefaultValue() { @@ -143,7 +144,8 @@ internal bool IsDefaultValue() lazyAttributeUsageInfo.IsNull && !lazyContainsExtensionMethods.HasValue() && lazyDefaultMemberName == null && - (object)lazyComImportCoClassType == (object)ErrorTypeSymbol.UnknownResultType; + (object)lazyComImportCoClassType == (object)ErrorTypeSymbol.UnknownResultType && + !lazyHasEmbeddedAttribute.HasValue(); } } @@ -372,6 +374,26 @@ internal TypeDefinitionHandle Handle } } + + internal override bool HasCodeAnalysisEmbeddedAttribute + { + get + { + var uncommon = GetUncommonProperties(); + if (uncommon == s_noUncommonProperties) + { + return false; + } + + if (!uncommon.lazyHasEmbeddedAttribute.HasValue()) + { + uncommon.lazyHasEmbeddedAttribute = ContainingPEModule.Module.HasCodeAnalysisEmbeddedAttribute(_handle).ToThreeState(); + } + + return uncommon.lazyHasEmbeddedAttribute.Value(); + } + } + internal override NamedTypeSymbol BaseTypeNoUseSiteDiagnostics { get @@ -592,7 +614,7 @@ public override ImmutableArray GetAttributes() return uncommon.lazyCustomAttributes; } - internal override IEnumerable GetCustomAttributesToEmit(ModuleCompilationState compilationState) + internal override IEnumerable GetCustomAttributesToEmit(PEModuleBuilder moduleBuilder) { return GetAttributes(); } diff --git a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEParameterSymbol.cs index 43a307c1e4a71..991494b170d00 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEParameterSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEParameterSymbol.cs @@ -223,7 +223,7 @@ private PEParameterSymbol( { refKind = RefKind.Out; } - else if (moduleSymbol.Module.HasReadOnlyAttribute(handle)) + else if (moduleSymbol.Module.HasIsReadOnlyAttribute(handle)) { refKind = RefKind.RefReadOnly; } @@ -790,7 +790,7 @@ public override ImmutableArray GetAttributes() return _lazyCustomAttributes; } - internal override IEnumerable GetCustomAttributesToEmit(ModuleCompilationState compilationState) + internal override IEnumerable GetCustomAttributesToEmit(PEModuleBuilder moduleBuilder) { foreach (CSharpAttributeData attribute in GetAttributes()) { diff --git a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEPropertySymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEPropertySymbol.cs index e322e8343ac9b..ba556a6248b15 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEPropertySymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEPropertySymbol.cs @@ -142,7 +142,7 @@ private PEPropertySymbol( if (returnInfo.IsByRef) { - if (moduleSymbol.Module.HasReadOnlyAttribute(handle)) + if (moduleSymbol.Module.HasIsReadOnlyAttribute(handle)) { _refKind = RefKind.RefReadOnly; } @@ -535,7 +535,7 @@ public override ImmutableArray GetAttributes() return _lazyCustomAttributes; } - internal override IEnumerable GetCustomAttributesToEmit(ModuleCompilationState compilationState) + internal override IEnumerable GetCustomAttributesToEmit(PEModuleBuilder moduleBuilder) { return GetAttributes(); } diff --git a/src/Compilers/CSharp/Portable/Symbols/MethodSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/MethodSymbol.cs index 3c5380646f2fc..42ec11b842863 100644 --- a/src/Compilers/CSharp/Portable/Symbols/MethodSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/MethodSymbol.cs @@ -5,6 +5,7 @@ using System.Collections.Immutable; using System.Diagnostics; using System.Linq; +using Microsoft.CodeAnalysis.CSharp.Emit; using Microsoft.CodeAnalysis.CSharp.Symbols; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Symbols; @@ -1151,11 +1152,11 @@ ImmutableArray IMethodSymbol.GetReturnTypeAttributes() /// /// Build and add synthesized return type attributes for this method symbol. /// - internal virtual void AddSynthesizedReturnTypeAttributes(ref ArrayBuilder attributes) + internal virtual void AddSynthesizedReturnTypeAttributes(PEModuleBuilder moduleBuilder, ref ArrayBuilder attributes) { if (this.ReturnsByRefReadonly) { - AddSynthesizedAttribute(ref attributes, this.DeclaringCompilation.SynthesizeReadOnlyAttribute()); + AddSynthesizedAttribute(ref attributes, moduleBuilder.SynthesizeIsReadOnlyAttribute(this)); } } diff --git a/src/Compilers/CSharp/Portable/Symbols/NamedTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/NamedTypeSymbol.cs index 7768308cbeee0..618a0539b1d6a 100644 --- a/src/Compilers/CSharp/Portable/Symbols/NamedTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/NamedTypeSymbol.cs @@ -824,6 +824,11 @@ internal NamedTypeSymbol GetUnboundGenericTypeOrSelf() return this.ConstructUnboundGenericType(); } + /// + /// Gets a value indicating whether this type has an EmbeddedAttribute or not. + /// + internal abstract bool HasCodeAnalysisEmbeddedAttribute { get; } + internal static readonly Func TypeSymbolIsNullFunction = type => (object)type.Type == null; internal static readonly Func TypeSymbolIsErrorType = type => (object)type.Type != null && type.Type.IsErrorType(); diff --git a/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingEventSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingEventSymbol.cs index 7c79157899cd7..30fdeb4d8efe2 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingEventSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingEventSymbol.cs @@ -155,9 +155,9 @@ public override ImmutableArray GetAttributes() return _underlyingEvent.GetAttributes(); } - internal override IEnumerable GetCustomAttributesToEmit(ModuleCompilationState compilationState) + internal override IEnumerable GetCustomAttributesToEmit(PEModuleBuilder moduleBuilder) { - return this.RetargetingTranslator.RetargetAttributes(_underlyingEvent.GetCustomAttributesToEmit(compilationState)); + return this.RetargetingTranslator.RetargetAttributes(_underlyingEvent.GetCustomAttributesToEmit(moduleBuilder)); } internal override bool MustCallMethodsDirectly diff --git a/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingFieldSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingFieldSymbol.cs index e426982e2a829..2ff1a642c5f00 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingFieldSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingFieldSymbol.cs @@ -86,9 +86,9 @@ public override ImmutableArray GetAttributes() return this.RetargetingTranslator.GetRetargetedAttributes(_underlyingField.GetAttributes(), ref _lazyCustomAttributes); } - internal override IEnumerable GetCustomAttributesToEmit(ModuleCompilationState compilationState) + internal override IEnumerable GetCustomAttributesToEmit(PEModuleBuilder moduleBuilder) { - return this.RetargetingTranslator.RetargetAttributes(_underlyingField.GetCustomAttributesToEmit(compilationState)); + return this.RetargetingTranslator.RetargetAttributes(_underlyingField.GetCustomAttributesToEmit(moduleBuilder)); } public override AssemblySymbol ContainingAssembly diff --git a/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingMethodSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingMethodSymbol.cs index 499a042f02c13..e23456d298c9a 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingMethodSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingMethodSymbol.cs @@ -234,9 +234,9 @@ public override ImmutableArray GetAttributes() return this.RetargetingTranslator.GetRetargetedAttributes(_underlyingMethod.GetAttributes(), ref _lazyCustomAttributes); } - internal override IEnumerable GetCustomAttributesToEmit(ModuleCompilationState compilationState) + internal override IEnumerable GetCustomAttributesToEmit(PEModuleBuilder moduleBuilder) { - return this.RetargetingTranslator.RetargetAttributes(_underlyingMethod.GetCustomAttributesToEmit(compilationState)); + return this.RetargetingTranslator.RetargetAttributes(_underlyingMethod.GetCustomAttributesToEmit(moduleBuilder)); } // Get return type attributes diff --git a/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingNamedTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingNamedTypeSymbol.cs index 72de6f2f9090f..9aa4bdd294d96 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingNamedTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingNamedTypeSymbol.cs @@ -238,9 +238,9 @@ public override ImmutableArray GetAttributes() return this.RetargetingTranslator.GetRetargetedAttributes(_underlyingType.GetAttributes(), ref _lazyCustomAttributes); } - internal override IEnumerable GetCustomAttributesToEmit(ModuleCompilationState compilationState) + internal override IEnumerable GetCustomAttributesToEmit(PEModuleBuilder moduleBuilder) { - return this.RetargetingTranslator.RetargetAttributes(_underlyingType.GetCustomAttributesToEmit(compilationState)); + return this.RetargetingTranslator.RetargetAttributes(_underlyingType.GetCustomAttributesToEmit(moduleBuilder)); } public override AssemblySymbol ContainingAssembly diff --git a/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingParameterSymbol.cs index 8fb803ee25d98..bbbf882cecf1c 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingParameterSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingParameterSymbol.cs @@ -82,9 +82,9 @@ public sealed override ImmutableArray GetAttributes() return this.RetargetingModule.RetargetingTranslator.GetRetargetedAttributes(_underlyingParameter.GetAttributes(), ref _lazyCustomAttributes); } - internal sealed override IEnumerable GetCustomAttributesToEmit(ModuleCompilationState compilationState) + internal sealed override IEnumerable GetCustomAttributesToEmit(PEModuleBuilder moduleBuilder) { - return this.RetargetingModule.RetargetingTranslator.RetargetAttributes(_underlyingParameter.GetCustomAttributesToEmit(compilationState)); + return this.RetargetingModule.RetargetingTranslator.RetargetAttributes(_underlyingParameter.GetCustomAttributesToEmit(moduleBuilder)); } public sealed override AssemblySymbol ContainingAssembly diff --git a/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingPropertySymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingPropertySymbol.cs index b5b1fe48c6523..7b0c1c00ffbd3 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingPropertySymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingPropertySymbol.cs @@ -232,9 +232,9 @@ public override ImmutableArray GetAttributes() return this.RetargetingTranslator.GetRetargetedAttributes(_underlyingProperty.GetAttributes(), ref _lazyCustomAttributes); } - internal override IEnumerable GetCustomAttributesToEmit(ModuleCompilationState compilationState) + internal override IEnumerable GetCustomAttributesToEmit(PEModuleBuilder moduleBuilder) { - return this.RetargetingTranslator.RetargetAttributes(_underlyingProperty.GetCustomAttributesToEmit(compilationState)); + return this.RetargetingTranslator.RetargetAttributes(_underlyingProperty.GetCustomAttributesToEmit(moduleBuilder)); } internal override bool MustCallMethodsDirectly diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/ImplicitNamedTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/ImplicitNamedTypeSymbol.cs index a35bbde08e26a..a476b9cd3892e 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/ImplicitNamedTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/ImplicitNamedTypeSymbol.cs @@ -178,5 +178,7 @@ internal override ObsoleteAttributeData ObsoleteAttributeData { get { return null; } } + + internal override bool HasCodeAnalysisEmbeddedAttribute => false; } } diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/LambdaSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/LambdaSymbol.cs index de5c02890f8a8..f2bd493d231e1 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/LambdaSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/LambdaSymbol.cs @@ -31,7 +31,8 @@ public LambdaSymbol( ImmutableArray parameterTypes, ImmutableArray parameterRefKinds, RefKind refKind, - TypeSymbol returnType) + TypeSymbol returnType, + DiagnosticBag diagnostics) { _containingSymbol = containingSymbol; _messageID = unboundLambda.Data.MessageID; @@ -41,7 +42,7 @@ public LambdaSymbol( _isSynthesized = unboundLambda.WasCompilerGenerated; _isAsync = unboundLambda.IsAsync; // No point in making this lazy. We are always going to need these soon after creation of the symbol. - _parameters = MakeParameters(compilation, unboundLambda, parameterTypes, parameterRefKinds); + _parameters = MakeParameters(compilation, unboundLambda, parameterTypes, parameterRefKinds, diagnostics); } public LambdaSymbol( @@ -313,7 +314,8 @@ private ImmutableArray MakeParameters( CSharpCompilation compilation, UnboundLambda unboundLambda, ImmutableArray parameterTypes, - ImmutableArray parameterRefKinds) + ImmutableArray parameterRefKinds, + DiagnosticBag diagnostics) { Debug.Assert(parameterTypes.Length == parameterRefKinds.Length); @@ -359,7 +361,7 @@ private ImmutableArray MakeParameters( type = new ExtendedErrorTypeSymbol(compilation, name: string.Empty, arity: 0, errorInfo: null); refKind = RefKind.None; } - + var name = unboundLambda.ParameterName(p); var location = unboundLambda.ParameterLocation(p); var locations = ImmutableArray.Create(location); diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/LocalFunctionSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/LocalFunctionSymbol.cs index 2c579a5218f73..31afa048b4866 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/LocalFunctionSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/LocalFunctionSymbol.cs @@ -19,12 +19,12 @@ internal sealed class LocalFunctionSymbol : MethodSymbol private readonly Symbol _containingSymbol; private readonly DeclarationModifiers _declarationModifiers; private readonly ImmutableArray _typeParameters; + private readonly RefKind _refKind; private ImmutableArray _lazyParameters; private bool _lazyIsVarArg; private ImmutableArray _lazyTypeParameterConstraints; private TypeSymbol _lazyReturnType; - private RefKind _lazyRefKind; private TypeSymbol _iteratorElementType; // Lock for initializing lazy fields and registering their diagnostics @@ -72,6 +72,23 @@ public LocalFunctionSymbol( ReportAttributesDisallowed(param.AttributeLists, _declarationDiagnostics); } + if (syntax.ReturnType.Kind() == SyntaxKind.RefType) + { + var returnType = (RefTypeSyntax)syntax.ReturnType; + if (returnType.ReadOnlyKeyword.Kind() == SyntaxKind.ReadOnlyKeyword) + { + _refKind = RefKind.RefReadOnly; + } + else + { + _refKind = RefKind.Ref; + } + } + else + { + _refKind = RefKind.None; + } + _binder = binder; } @@ -145,6 +162,8 @@ private void ComputeParameters() allowThis: true, diagnostics: diagnostics); + ParameterHelpers.EnsureIsReadOnlyAttributeExists(parameters, diagnostics, modifyCompilationForRefReadOnly: false); + var isVararg = arglistToken.Kind() == SyntaxKind.ArgListKeyword; if (isVararg) { @@ -179,15 +198,8 @@ public override TypeSymbol ReturnType } } - internal override RefKind RefKind - { - get - { - ComputeReturnType(); - return _lazyRefKind; - } - } - + internal override RefKind RefKind => _refKind; + internal void ComputeReturnType() { if (_lazyReturnType != null) @@ -196,7 +208,7 @@ internal void ComputeReturnType() } var diagnostics = DiagnosticBag.GetInstance(); - TypeSyntax returnTypeSyntax = _syntax.ReturnType.SkipRef(out _lazyRefKind); + TypeSyntax returnTypeSyntax = _syntax.ReturnType.SkipRef(); TypeSymbol returnType = _binder.BindType(returnTypeSyntax, diagnostics); if (IsAsync && returnType.SpecialType != SpecialType.System_Void && @@ -207,7 +219,12 @@ internal void ComputeReturnType() diagnostics.Add(ErrorCode.ERR_BadAsyncReturn, this.Locations[0]); } - Debug.Assert(_lazyRefKind == RefKind.None + if (_refKind == RefKind.RefReadOnly) + { + DeclaringCompilation.EnsureIsReadOnlyAttributeExists(diagnostics, _syntax.ReturnType.Location, modifyCompilationForRefReadOnly: false); + } + + Debug.Assert(_refKind == RefKind.None || returnType.SpecialType != SpecialType.System_Void || returnTypeSyntax.HasErrors); diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/ParameterHelpers.cs b/src/Compilers/CSharp/Portable/Symbols/Source/ParameterHelpers.cs index a34e157070e0a..c140961151ccd 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/ParameterHelpers.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/ParameterHelpers.cs @@ -43,8 +43,7 @@ public static ImmutableArray MakeParameters( CheckParameterModifiers(parameterSyntax, diagnostics); - var refKind = GetModifiers(parameterSyntax.Modifiers, out SyntaxToken refOrOutKeyword, out SyntaxToken paramsKeyword, out SyntaxToken thisKeyword); - + var refKind = GetModifiers(parameterSyntax.Modifiers, out SyntaxToken refnessKeyword, out SyntaxToken paramsKeyword, out SyntaxToken thisKeyword); if (thisKeyword.Kind() != SyntaxKind.None && !allowThis) { diagnostics.Add(ErrorCode.ERR_ThisInBadContext, thisKeyword.GetLocation()); @@ -56,7 +55,7 @@ public static ImmutableArray MakeParameters( // The native compiler produces "Expected type" here, in the parser. Roslyn produces // the somewhat more informative "arglist not valid" error. if (paramsKeyword.Kind() != SyntaxKind.None - || refOrOutKeyword.Kind() != SyntaxKind.None + || refnessKeyword.Kind() != SyntaxKind.None || thisKeyword.Kind() != SyntaxKind.None) { // CS1669: __arglist is not valid in this context @@ -75,10 +74,10 @@ public static ImmutableArray MakeParameters( if (!allowRefOrOut && (refKind == RefKind.Ref || refKind == RefKind.Out)) { - Debug.Assert(refOrOutKeyword.Kind() != SyntaxKind.None); + Debug.Assert(refnessKeyword.Kind() != SyntaxKind.None); // error CS0631: ref and out are not valid in this context - diagnostics.Add(ErrorCode.ERR_IllegalRefParam, refOrOutKeyword.GetLocation()); + diagnostics.Add(ErrorCode.ERR_IllegalRefParam, refnessKeyword.GetLocation()); } var parameter = SourceParameterSymbol.Create( @@ -119,6 +118,17 @@ public static ImmutableArray MakeParameters( return parameters; } + internal static void EnsureIsReadOnlyAttributeExists(ImmutableArray parameters, DiagnosticBag diagnostics, bool modifyCompilationForRefReadOnly) + { + foreach (var parameter in parameters) + { + if (parameter.RefKind == RefKind.RefReadOnly) + { + parameter.DeclaringCompilation.EnsureIsReadOnlyAttributeExists(diagnostics, parameter.GetNonNullSyntaxNode().Location, modifyCompilationForRefReadOnly); + } + } + } + private static void CheckParameterModifiers( ParameterSyntax parameter, DiagnosticBag diagnostics) { @@ -387,10 +397,7 @@ internal static bool ReportDefaultParameterErrors( Conversion conversion = binder.Conversions.ClassifyImplicitConversionFromExpression(defaultExpression, parameterType, ref useSiteDiagnostics); diagnostics.Add(defaultExpression.Syntax, useSiteDiagnostics); - SyntaxToken argPassingKeyword; - SyntaxToken paramsKeyword; - SyntaxToken thisKeyword; - var refKind = GetModifiers(parameterSyntax.Modifiers, out argPassingKeyword, out paramsKeyword, out thisKeyword); + var refKind = GetModifiers(parameterSyntax.Modifiers, out SyntaxToken refnessKeyword, out SyntaxToken paramsKeyword, out SyntaxToken thisKeyword); // CONSIDER: We are inconsistent here regarding where the error is reported; is it // CONSIDER: reported on the parameter name, or on the value of the initializer? @@ -399,7 +406,7 @@ internal static bool ReportDefaultParameterErrors( if (refKind == RefKind.Ref || refKind == RefKind.Out) { // error CS1741: A ref or out parameter cannot have a default value - diagnostics.Add(ErrorCode.ERR_RefOutDefaultValue, argPassingKeyword.GetLocation()); + diagnostics.Add(ErrorCode.ERR_RefOutDefaultValue, refnessKeyword.GetLocation()); hasErrors = true; } else if (paramsKeyword.Kind() == SyntaxKind.ParamsKeyword) @@ -546,11 +553,11 @@ internal static MethodSymbol FindContainingGenericMethod(Symbol symbol) return null; } - private static RefKind GetModifiers(SyntaxTokenList modifiers, out SyntaxToken refOrOutKeyword, out SyntaxToken paramsKeyword, out SyntaxToken thisKeyword) + private static RefKind GetModifiers(SyntaxTokenList modifiers, out SyntaxToken refnessKeyword, out SyntaxToken paramsKeyword, out SyntaxToken thisKeyword) { var refKind = RefKind.None; - refOrOutKeyword = default(SyntaxToken); + refnessKeyword = default(SyntaxToken); paramsKeyword = default(SyntaxToken); thisKeyword = default(SyntaxToken); @@ -559,30 +566,30 @@ private static RefKind GetModifiers(SyntaxTokenList modifiers, out SyntaxToken r switch (modifier.Kind()) { case SyntaxKind.OutKeyword: - refOrOutKeyword = modifier; if (refKind == RefKind.None) { + refnessKeyword = modifier; refKind = RefKind.Out; } break; case SyntaxKind.RefKeyword: - refOrOutKeyword = modifier; if (refKind == RefKind.None) { + refnessKeyword = modifier; refKind = RefKind.Ref; } break; case SyntaxKind.InKeyword: if (refKind == RefKind.None) { + refnessKeyword = modifier; refKind = RefKind.RefReadOnly; } break; case SyntaxKind.ReadOnlyKeyword: if (refKind == RefKind.Ref) { - // this is not a ref or out - refOrOutKeyword = default(SyntaxToken); + refnessKeyword = modifier; refKind = RefKind.RefReadOnly; } break; diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceAssemblySymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceAssemblySymbol.cs index 48f86ecbd1c2e..6c7c6872d3e3f 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceAssemblySymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceAssemblySymbol.cs @@ -8,6 +8,7 @@ using System.Linq; using System.Reflection; using System.Threading; +using Microsoft.CodeAnalysis.CSharp.Emit; using Microsoft.CodeAnalysis.CSharp.Symbols; using Microsoft.CodeAnalysis.CSharp.Symbols.Metadata.PE; using Microsoft.CodeAnalysis.CSharp.Syntax; @@ -1704,9 +1705,9 @@ private bool HasReferenceAssemblyAttribute } } - internal override void AddSynthesizedAttributes(ModuleCompilationState compilationState, ref ArrayBuilder attributes) + internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, ref ArrayBuilder attributes) { - base.AddSynthesizedAttributes(compilationState, ref attributes); + base.AddSynthesizedAttributes(moduleBuilder, ref attributes); CSharpCompilationOptions options = _compilation.Options; bool isBuildingNetModule = options.OutputKind.IsNetModule(); diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceClonedParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceClonedParameterSymbol.cs index 114dda44b5977..77cd7f7da47bf 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceClonedParameterSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceClonedParameterSymbol.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Immutable; using System.Diagnostics; +using Microsoft.CodeAnalysis.CSharp.Emit; namespace Microsoft.CodeAnalysis.CSharp.Symbols { @@ -156,13 +157,13 @@ internal override bool IsCallerMemberName get { return _originalParam.IsCallerMemberName; } } - internal override void AddSynthesizedAttributes(ModuleCompilationState compilationState, ref ArrayBuilder attributes) + internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, ref ArrayBuilder attributes) { - base.AddSynthesizedAttributes(compilationState, ref attributes); + base.AddSynthesizedAttributes(moduleBuilder, ref attributes); if (this.RefKind == RefKind.RefReadOnly) { - AddSynthesizedAttribute(ref attributes, this.DeclaringCompilation.SynthesizeReadOnlyAttribute()); + AddSynthesizedAttribute(ref attributes, moduleBuilder.SynthesizeIsReadOnlyAttribute(this)); } } diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceComplexParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceComplexParameterSymbol.cs index 146ed8382a211..8623632e231f9 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceComplexParameterSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceComplexParameterSymbol.cs @@ -558,9 +558,9 @@ internal override void DecodeWellKnownAttribute(ref DecodeWellKnownAttributeArgu // DynamicAttribute should not be set explicitly. arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitDynamicAttr, arguments.AttributeSyntaxOpt.Location); } - else if (attribute.IsTargetAttribute(this, AttributeDescription.ReadOnlyAttribute)) + else if (attribute.IsTargetAttribute(this, AttributeDescription.IsReadOnlyAttribute)) { - // ReadOnlyAttribute should not be set explicitly. + // IsReadOnlyAttribute should not be set explicitly. arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitReadOnlyAttr, arguments.AttributeSyntaxOpt.Location); } else if (attribute.IsTargetAttribute(this, AttributeDescription.TupleElementNamesAttribute)) diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceConstructorSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceConstructorSymbol.cs index 05d81bed261da..a44a27c0756a9 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceConstructorSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceConstructorSymbol.cs @@ -102,6 +102,13 @@ protected override void MethodChecks(DiagnosticBag diagnostics) } } + internal override void AfterAddingTypeMembersChecks(ConversionsBase conversions, DiagnosticBag diagnostics) + { + base.AfterAddingTypeMembersChecks(conversions, diagnostics); + + ParameterHelpers.EnsureIsReadOnlyAttributeExists(Parameters, diagnostics, modifyCompilationForRefReadOnly: true); + } + internal ConstructorDeclarationSyntax GetSyntax() { Debug.Assert(syntaxReferenceOpt != null); diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceDelegateMethodSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceDelegateMethodSymbol.cs index 5a2e92e7576b0..16c0251451a93 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceDelegateMethodSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceDelegateMethodSymbol.cs @@ -282,6 +282,19 @@ internal override LexicalSortKey GetLexicalSortKey() // so we will keep them the same. return new LexicalSortKey(this.syntaxReferenceOpt.GetLocation(), this.DeclaringCompilation); } + + internal override void AfterAddingTypeMembersChecks(ConversionsBase conversions, DiagnosticBag diagnostics) + { + base.AfterAddingTypeMembersChecks(conversions, diagnostics); + + if (refKind == RefKind.RefReadOnly) + { + var syntax = (DelegateDeclarationSyntax)SyntaxRef.GetSyntax(); + DeclaringCompilation.EnsureIsReadOnlyAttributeExists(diagnostics, syntax.ReturnType.GetLocation(), modifyCompilationForRefReadOnly: true); + } + + ParameterHelpers.EnsureIsReadOnlyAttributeExists(Parameters, diagnostics, modifyCompilationForRefReadOnly: true); + } } private sealed class BeginInvokeMethod : SourceDelegateMethodSymbol diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceEventFieldSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceEventFieldSymbol.cs index 7e22fcc56c537..19931f7ecfe43 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceEventFieldSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceEventFieldSymbol.cs @@ -47,9 +47,9 @@ public override Symbol AssociatedSymbol } } - internal override void AddSynthesizedAttributes(ModuleCompilationState compilationState, ref ArrayBuilder attributes) + internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, ref ArrayBuilder attributes) { - base.AddSynthesizedAttributes(compilationState, ref attributes); + base.AddSynthesizedAttributes(moduleBuilder, ref attributes); var compilation = this.DeclaringCompilation; AddSynthesizedAttribute(ref attributes, compilation.TrySynthesizeAttribute(WellKnownMember.System_Runtime_CompilerServices_CompilerGeneratedAttribute__ctor)); diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceEventSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceEventSymbol.cs index 69121106ec6d0..484ab1625819a 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceEventSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceEventSymbol.cs @@ -10,6 +10,7 @@ using Roslyn.Utilities; using System.Collections.Generic; using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.CSharp.Emit; namespace Microsoft.CodeAnalysis.CSharp.Symbols { @@ -295,9 +296,9 @@ internal sealed override void DecodeWellKnownAttribute(ref DecodeWellKnownAttrib } } - internal override void AddSynthesizedAttributes(ModuleCompilationState compilationState, ref ArrayBuilder attributes) + internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, ref ArrayBuilder attributes) { - base.AddSynthesizedAttributes(compilationState, ref attributes); + base.AddSynthesizedAttributes(moduleBuilder, ref attributes); if (this.Type.ContainsDynamic()) { diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceFieldSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceFieldSymbol.cs index 300886ade5b49..7bf919c2ae6b5 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceFieldSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceFieldSymbol.cs @@ -354,9 +354,9 @@ internal sealed override void DecodeWellKnownAttribute(ref DecodeWellKnownAttrib // DynamicAttribute should not be set explicitly. arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitDynamicAttr, arguments.AttributeSyntaxOpt.Location); } - else if (attribute.IsTargetAttribute(this, AttributeDescription.ReadOnlyAttribute)) + else if (attribute.IsTargetAttribute(this, AttributeDescription.IsReadOnlyAttribute)) { - // ReadOnlyAttribute should not be set explicitly. + // IsReadOnlyAttribute should not be set explicitly. arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitReadOnlyAttr, arguments.AttributeSyntaxOpt.Location); } else if (attribute.IsTargetAttribute(this, AttributeDescription.DateTimeConstantAttribute)) @@ -460,9 +460,9 @@ internal override void PostDecodeWellKnownAttributes(ImmutableArray attributes) + internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, ref ArrayBuilder attributes) { - base.AddSynthesizedAttributes(compilationState, ref attributes); + base.AddSynthesizedAttributes(moduleBuilder, ref attributes); if (this.Type.ContainsDynamic()) { diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceFixedFieldSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceFixedFieldSymbol.cs index 074baa373f362..be83577665d8a 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceFixedFieldSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceFixedFieldSymbol.cs @@ -32,9 +32,9 @@ internal SourceFixedFieldSymbol( Debug.Assert(this.IsFixed); } - internal override void AddSynthesizedAttributes(ModuleCompilationState compilationState, ref ArrayBuilder attributes) + internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, ref ArrayBuilder attributes) { - base.AddSynthesizedAttributes(compilationState, ref attributes); + base.AddSynthesizedAttributes(moduleBuilder, ref attributes); var compilation = this.DeclaringCompilation; var systemType = compilation.GetWellKnownType(WellKnownType.System_Type); @@ -198,9 +198,9 @@ internal override FieldSymbol FixedElementField get { return _internalField; } } - internal override void AddSynthesizedAttributes(ModuleCompilationState compilationState, ref ArrayBuilder attributes) + internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, ref ArrayBuilder attributes) { - base.AddSynthesizedAttributes(compilationState, ref attributes); + base.AddSynthesizedAttributes(moduleBuilder, ref attributes); var compilation = ContainingSymbol.DeclaringCompilation; AddSynthesizedAttribute(ref attributes, compilation.TrySynthesizeAttribute(WellKnownMember.System_Runtime_CompilerServices_UnsafeValueTypeAttribute__ctor)); } diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberFieldSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberFieldSymbol.cs index 6afa99959965c..dd7b1819346d5 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberFieldSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberFieldSymbol.cs @@ -87,9 +87,9 @@ protected void TypeChecks(TypeSymbol type, DiagnosticBag diagnostics) public abstract bool HasInitializer { get; } - internal override void AddSynthesizedAttributes(ModuleCompilationState compilationState, ref ArrayBuilder attributes) + internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, ref ArrayBuilder attributes) { - base.AddSynthesizedAttributes(compilationState, ref attributes); + base.AddSynthesizedAttributes(moduleBuilder, ref attributes); var compilation = this.DeclaringCompilation; var value = this.GetConstantValue(ConstantFieldsInProgress.Empty, earlyDecodingWellKnownAttributes: false); diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberMethodSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberMethodSymbol.cs index 9fab9ad81371e..0f5c164e87ccd 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberMethodSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberMethodSymbol.cs @@ -5,6 +5,7 @@ using System.Globalization; using System.Linq; using System.Threading; +using Microsoft.CodeAnalysis.CSharp.Emit; using Microsoft.CodeAnalysis.CSharp.Symbols; using Microsoft.CodeAnalysis.CSharp.Syntax; using Roslyn.Utilities; @@ -979,9 +980,9 @@ private void CheckModifiers(Location location, DiagnosticBag diagnostics) } } - internal override void AddSynthesizedAttributes(ModuleCompilationState compilationState, ref ArrayBuilder attributes) + internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, ref ArrayBuilder attributes) { - base.AddSynthesizedAttributes(compilationState, ref attributes); + base.AddSynthesizedAttributes(moduleBuilder, ref attributes); if (this.IsExtensionMethod) { @@ -1030,6 +1031,13 @@ internal override void AfterAddingTypeMembersChecks(ConversionsBase conversions, { PartialMethodChecks(this, implementingPart, diagnostics); } + + if (_refKind == RefKind.RefReadOnly) + { + this.DeclaringCompilation.EnsureIsReadOnlyAttributeExists(diagnostics, GetSyntax().ReturnType.Location, modifyCompilationForRefReadOnly: true); + } + + ParameterHelpers.EnsureIsReadOnlyAttributeExists(Parameters, diagnostics, modifyCompilationForRefReadOnly: true); } /// diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMethodSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMethodSymbol.cs index 49e3ed3b4ac9b..44eea538beb6c 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMethodSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMethodSymbol.cs @@ -10,6 +10,7 @@ using System.Linq; using System.Runtime.InteropServices; using System.Threading; +using Microsoft.CodeAnalysis.CSharp.Emit; namespace Microsoft.CodeAnalysis.CSharp.Symbols { @@ -962,9 +963,9 @@ public sealed override ImmutableArray GetReturnTypeAttribut return this.GetReturnTypeAttributesBag().Attributes; } - internal override void AddSynthesizedReturnTypeAttributes(ref ArrayBuilder attributes) + internal override void AddSynthesizedReturnTypeAttributes(PEModuleBuilder moduleBuilder, ref ArrayBuilder attributes) { - base.AddSynthesizedReturnTypeAttributes(ref attributes); + base.AddSynthesizedReturnTypeAttributes(moduleBuilder, ref attributes); if (this.ReturnType.ContainsDynamic()) { @@ -1120,9 +1121,9 @@ private void DecodeWellKnownAttributeAppliedToMethod(ref DecodeWellKnownAttribut else if (VerifyObsoleteAttributeAppliedToMethod(ref arguments, AttributeDescription.DeprecatedAttribute)) { } - else if (attribute.IsTargetAttribute(this, AttributeDescription.ReadOnlyAttribute)) + else if (attribute.IsTargetAttribute(this, AttributeDescription.IsReadOnlyAttribute)) { - // ReadOnlyAttribute should not be set explicitly. + // IsReadOnlyAttribute should not be set explicitly. arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitReadOnlyAttr, arguments.AttributeSyntaxOpt.Location); } else if (attribute.IsTargetAttribute(this, AttributeDescription.CaseSensitiveExtensionAttribute)) @@ -1245,9 +1246,9 @@ private void DecodeWellKnownAttributeAppliedToReturnValue(ref DecodeWellKnownAtt // DynamicAttribute should not be set explicitly. arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitDynamicAttr, arguments.AttributeSyntaxOpt.Location); } - else if (attribute.IsTargetAttribute(this, AttributeDescription.ReadOnlyAttribute)) + else if (attribute.IsTargetAttribute(this, AttributeDescription.IsReadOnlyAttribute)) { - // ReadOnlyAttribute should not be set explicitly. + // IsReadOnlyAttribute should not be set explicitly. arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitReadOnlyAttr, arguments.AttributeSyntaxOpt.Location); } else if (attribute.IsTargetAttribute(this, AttributeDescription.TupleElementNamesAttribute)) @@ -1531,9 +1532,9 @@ internal override System.Reflection.MethodImplAttributes ImplementationAttribute #endregion - internal override void AddSynthesizedAttributes(ModuleCompilationState compilationState, ref ArrayBuilder attributes) + internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, ref ArrayBuilder attributes) { - base.AddSynthesizedAttributes(compilationState, ref attributes); + base.AddSynthesizedAttributes(moduleBuilder, ref attributes); if (this.IsAsync || this.IsIterator) { @@ -1543,7 +1544,7 @@ internal override void AddSynthesizedAttributes(ModuleCompilationState compilati // only emitting metadata the method body will not have been rewritten, and the async state machine // type will not have been created. In this case, omit the attribute. NamedTypeSymbol stateMachineType; - if (compilationState.TryGetStateMachineType(this, out stateMachineType)) + if (moduleBuilder.CompilationState.TryGetStateMachineType(this, out stateMachineType)) { WellKnownMember ctor = this.IsAsync ? WellKnownMember.System_Runtime_CompilerServices_AsyncStateMachineAttribute__ctor : diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceModuleSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceModuleSymbol.cs index 38d5776fe7a9c..68ebb2f3e3513 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceModuleSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceModuleSymbol.cs @@ -7,6 +7,7 @@ using System.Reflection.PortableExecutable; using System.Runtime.InteropServices; using System.Threading; +using Microsoft.CodeAnalysis.CSharp.Emit; using Microsoft.CodeAnalysis.CSharp.Syntax; using Roslyn.Utilities; @@ -508,9 +509,9 @@ internal override void DecodeWellKnownAttribute(ref DecodeWellKnownAttributeArgu } } - internal override void AddSynthesizedAttributes(ModuleCompilationState compilationState, ref ArrayBuilder attributes) + internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, ref ArrayBuilder attributes) { - base.AddSynthesizedAttributes(compilationState, ref attributes); + base.AddSynthesizedAttributes(moduleBuilder, ref attributes); var compilation = _assemblySymbol.DeclaringCompilation; if (compilation.Options.AllowUnsafe) diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamedTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamedTypeSymbol.cs index 37fb1637b9142..5a952c7e248fd 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamedTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamedTypeSymbol.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Runtime.InteropServices; using System.Threading; +using Microsoft.CodeAnalysis.CSharp.Emit; using Microsoft.CodeAnalysis.CSharp.Symbols; using Microsoft.CodeAnalysis.CSharp.Syntax; using Roslyn.Utilities; @@ -540,6 +541,21 @@ internal override CSharpAttributeData EarlyDecodeWellKnownAttribute(ref EarlyDec return null; } + if (CSharpAttributeData.IsTargetEarlyAttribute(arguments.AttributeType, arguments.AttributeSyntax, AttributeDescription.CodeAnalysisEmbeddedAttribute)) + { + boundAttribute = arguments.Binder.GetAttribute(arguments.AttributeSyntax, arguments.AttributeType, out hasAnyDiagnostics); + if (!boundAttribute.HasErrors) + { + arguments.GetOrCreateData().HasCodeAnalysisEmbeddedAttribute = true; + if (!hasAnyDiagnostics) + { + return boundAttribute; + } + } + + return null; + } + if (CSharpAttributeData.IsTargetEarlyAttribute(arguments.AttributeType, arguments.AttributeSyntax, AttributeDescription.ConditionalAttribute)) { boundAttribute = arguments.Binder.GetAttribute(arguments.AttributeSyntax, arguments.AttributeType, out hasAnyDiagnostics); @@ -710,9 +726,9 @@ internal sealed override void DecodeWellKnownAttribute(ref DecodeWellKnownAttrib // DynamicAttribute should not be set explicitly. arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitDynamicAttr, arguments.AttributeSyntaxOpt.Location); } - else if (attribute.IsTargetAttribute(this, AttributeDescription.ReadOnlyAttribute)) + else if (attribute.IsTargetAttribute(this, AttributeDescription.IsReadOnlyAttribute)) { - // ReadOnlyAttribute should not be set explicitly. + // IsReadOnlyAttribute should not be set explicitly. arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitReadOnlyAttr, arguments.AttributeSyntaxOpt.Location); } else if (attribute.IsTargetAttribute(this, AttributeDescription.TupleElementNamesAttribute)) @@ -864,6 +880,15 @@ internal override bool HasSpecialName } } + internal override bool HasCodeAnalysisEmbeddedAttribute + { + get + { + var data = GetEarlyDecodedWellKnownAttributeData(); + return data != null && data.HasCodeAnalysisEmbeddedAttribute; + } + } + internal sealed override bool ShouldAddWinRTMembers { get { return false; } @@ -1084,9 +1109,9 @@ internal override void PostDecodeWellKnownAttributes(ImmutableArray - internal override void AddSynthesizedAttributes(ModuleCompilationState compilationState, ref ArrayBuilder attributes) + internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, ref ArrayBuilder attributes) { - base.AddSynthesizedAttributes(compilationState, ref attributes); + base.AddSynthesizedAttributes(moduleBuilder, ref attributes); CSharpCompilation compilation = this.DeclaringCompilation; diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceParameterSymbol.cs index 5fe09af7f7210..912d6edb3406d 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceParameterSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceParameterSymbol.cs @@ -3,7 +3,9 @@ using System.Collections.Immutable; using System.Diagnostics; using System.Threading; +using Microsoft.CodeAnalysis.CSharp.Emit; using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Emit; namespace Microsoft.CodeAnalysis.CSharp.Symbols { @@ -230,13 +232,13 @@ public override bool IsImplicitlyDeclared } } - internal override void AddSynthesizedAttributes(ModuleCompilationState compilationState, ref ArrayBuilder attributes) + internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, ref ArrayBuilder attributes) { - base.AddSynthesizedAttributes(compilationState, ref attributes); + base.AddSynthesizedAttributes(moduleBuilder, ref attributes); if (this.RefKind == RefKind.RefReadOnly) { - AddSynthesizedAttribute(ref attributes, this.DeclaringCompilation.SynthesizeReadOnlyAttribute()); + AddSynthesizedAttribute(ref attributes, moduleBuilder.SynthesizeIsReadOnlyAttribute(this)); } } } diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceParameterSymbolBase.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceParameterSymbolBase.cs index 7fc2518218bb9..1730954107cc2 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceParameterSymbolBase.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceParameterSymbolBase.cs @@ -57,9 +57,9 @@ public sealed override AssemblySymbol ContainingAssembly internal abstract ConstantValue DefaultValueFromAttributes { get; } - internal override void AddSynthesizedAttributes(ModuleCompilationState compilationState, ref ArrayBuilder attributes) + internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, ref ArrayBuilder attributes) { - base.AddSynthesizedAttributes(compilationState, ref attributes); + base.AddSynthesizedAttributes(moduleBuilder, ref attributes); var compilation = this.DeclaringCompilation; diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertyAccessorSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertyAccessorSymbol.cs index b8a68d850934e..f92cb59280be3 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertyAccessorSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertyAccessorSymbol.cs @@ -558,9 +558,9 @@ private ImmutableArray ComputeParameters(DiagnosticBag diagnost return parameters.ToImmutableAndFree(); } - internal override void AddSynthesizedAttributes(ModuleCompilationState compilationState, ref ArrayBuilder attributes) + internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, ref ArrayBuilder attributes) { - base.AddSynthesizedAttributes(compilationState, ref attributes); + base.AddSynthesizedAttributes(moduleBuilder, ref attributes); if (_isAutoPropertyAccessor) { diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbol.cs index 508bb9c4acfe0..b10dd68c9108b 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbol.cs @@ -8,6 +8,7 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Threading; +using Microsoft.CodeAnalysis.CSharp.Emit; using Microsoft.CodeAnalysis.CSharp.Syntax; using Roslyn.Utilities; @@ -703,6 +704,13 @@ internal override void AfterAddingTypeMembersChecks(ConversionsBase conversions, Debug.Assert(explicitInterfaceSpecifier != null); _explicitInterfaceType.CheckAllConstraints(conversions, new SourceLocation(explicitInterfaceSpecifier.Name), diagnostics); } + + if (_refKind == RefKind.RefReadOnly) + { + DeclaringCompilation.EnsureIsReadOnlyAttributeExists(diagnostics, CSharpSyntaxNode.Type.Location, modifyCompilationForRefReadOnly: true); + } + + ParameterHelpers.EnsureIsReadOnlyAttributeExists(Parameters, diagnostics, modifyCompilationForRefReadOnly: true); } private void CheckAccessibility(Location location, DiagnosticBag diagnostics) @@ -1079,9 +1087,9 @@ internal PropertyEarlyWellKnownAttributeData GetEarlyDecodedWellKnownAttributeDa return (PropertyEarlyWellKnownAttributeData)attributesBag.EarlyDecodedWellKnownAttributeData; } - internal override void AddSynthesizedAttributes(ModuleCompilationState compilationState, ref ArrayBuilder attributes) + internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, ref ArrayBuilder attributes) { - base.AddSynthesizedAttributes(compilationState, ref attributes); + base.AddSynthesizedAttributes(moduleBuilder, ref attributes); if (Type.ContainsDynamic()) { @@ -1097,7 +1105,7 @@ internal override void AddSynthesizedAttributes(ModuleCompilationState compilati if (this.ReturnsByRefReadonly) { - AddSynthesizedAttribute(ref attributes, this.DeclaringCompilation.SynthesizeReadOnlyAttribute()); + AddSynthesizedAttribute(ref attributes, moduleBuilder.SynthesizeIsReadOnlyAttribute(this)); } } @@ -1202,9 +1210,9 @@ internal override void DecodeWellKnownAttribute(ref DecodeWellKnownAttributeArgu // DynamicAttribute should not be set explicitly. arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitDynamicAttr, arguments.AttributeSyntaxOpt.Location); } - else if (attribute.IsTargetAttribute(this, AttributeDescription.ReadOnlyAttribute)) + else if (attribute.IsTargetAttribute(this, AttributeDescription.IsReadOnlyAttribute)) { - // ReadOnlyAttribute should not be set explicitly. + // IsReadOnlyAttribute should not be set explicitly. arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitReadOnlyAttr, arguments.AttributeSyntaxOpt.Location); } else if (attribute.IsTargetAttribute(this, AttributeDescription.TupleElementNamesAttribute)) diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceUserDefinedOperatorSymbolBase.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceUserDefinedOperatorSymbolBase.cs index ffb05eba3d606..013e2a16666f4 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceUserDefinedOperatorSymbolBase.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceUserDefinedOperatorSymbolBase.cs @@ -649,6 +649,8 @@ internal sealed override void AfterAddingTypeMembersChecks(ConversionsBase conve { parameter.Type.CheckAllConstraints(conversions, parameter.Locations[0], diagnostics); } + + ParameterHelpers.EnsureIsReadOnlyAttributeExists(Parameters, diagnostics, modifyCompilationForRefReadOnly: true); } } } diff --git a/src/Compilers/CSharp/Portable/Symbols/SubstitutedNamedTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/SubstitutedNamedTypeSymbol.cs index 8a3948e033d49..399a62b7881ba 100644 --- a/src/Compilers/CSharp/Portable/Symbols/SubstitutedNamedTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/SubstitutedNamedTypeSymbol.cs @@ -8,6 +8,7 @@ using System.Linq; using System.Runtime.InteropServices; using System.Threading; +using Microsoft.CodeAnalysis.CSharp.Emit; using Microsoft.CodeAnalysis.CSharp.Symbols; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; @@ -359,7 +360,7 @@ internal override IEnumerable GetPropertiesToEmit() throw ExceptionUtilities.Unreachable; } - internal override IEnumerable GetCustomAttributesToEmit(ModuleCompilationState compilationState) + internal override IEnumerable GetCustomAttributesToEmit(PEModuleBuilder moduleBuilder) { throw ExceptionUtilities.Unreachable; } diff --git a/src/Compilers/CSharp/Portable/Symbols/Symbol.cs b/src/Compilers/CSharp/Portable/Symbols/Symbol.cs index b2e483c95a7ad..519bf9710a49a 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Symbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Symbol.cs @@ -9,6 +9,7 @@ using System.Text; using System.Threading; using Microsoft.CodeAnalysis.Collections; +using Microsoft.CodeAnalysis.CSharp.Emit; using Microsoft.CodeAnalysis.CSharp.Symbols; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; @@ -619,7 +620,7 @@ internal Symbol() /// /// Build and add synthesized attributes for this symbol. /// - internal virtual void AddSynthesizedAttributes(ModuleCompilationState compilationState, ref ArrayBuilder attributes) + internal virtual void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, ref ArrayBuilder attributes) { } diff --git a/src/Compilers/CSharp/Portable/Symbols/SymbolExtensions.cs b/src/Compilers/CSharp/Portable/Symbols/SymbolExtensions.cs index 0aa00b3512d75..6cb616eaa19a4 100644 --- a/src/Compilers/CSharp/Portable/Symbols/SymbolExtensions.cs +++ b/src/Compilers/CSharp/Portable/Symbols/SymbolExtensions.cs @@ -259,6 +259,26 @@ internal static void CheckUnsafeModifier(this Symbol symbol, DeclarationModifier } } + /// + /// Does the top level type containing this symbol have 'Microsoft.CodeAnalysis.Embedded' attribute? + /// + public static bool IsHiddenByCodeAnalysisEmbeddedAttribute(this Symbol symbol) + { + // Only upper-level types should be checked + var upperLevelType = symbol.Kind == SymbolKind.NamedType ? (NamedTypeSymbol)symbol : symbol.ContainingType; + if ((object)upperLevelType == null) + { + return false; + } + + while ((object)upperLevelType.ContainingType != null) + { + upperLevelType = upperLevelType.ContainingType; + } + + return upperLevelType.HasCodeAnalysisEmbeddedAttribute; + } + public static bool MustCallMethodsDirectly(this Symbol symbol) { switch (symbol.Kind) diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedBackingFieldSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedBackingFieldSymbol.cs index 10ce338ecdb26..fa7cc05470ed1 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedBackingFieldSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedBackingFieldSymbol.cs @@ -2,6 +2,7 @@ using System.Collections.Immutable; using System.Diagnostics; +using Microsoft.CodeAnalysis.CSharp.Emit; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.CSharp.Symbols @@ -70,9 +71,9 @@ internal override bool HasPointerType } } - internal override void AddSynthesizedAttributes(ModuleCompilationState compilationState, ref ArrayBuilder attributes) + internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, ref ArrayBuilder attributes) { - base.AddSynthesizedAttributes(compilationState, ref attributes); + base.AddSynthesizedAttributes(moduleBuilder, ref attributes); var compilation = this.DeclaringCompilation; diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedContainer.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedContainer.cs index c173b67ecc474..485f1278545fa 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedContainer.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedContainer.cs @@ -5,6 +5,7 @@ using System.Collections.Immutable; using System.Diagnostics; using System.Runtime.InteropServices; +using Microsoft.CodeAnalysis.CSharp.Emit; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.CSharp.Symbols @@ -74,9 +75,9 @@ private ImmutableArray CreateTypeParameters(int parameterCo internal sealed override bool IsInterface => this.TypeKind == TypeKind.Interface; - internal override void AddSynthesizedAttributes(ModuleCompilationState compilationState, ref ArrayBuilder attributes) + internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, ref ArrayBuilder attributes) { - base.AddSynthesizedAttributes(compilationState, ref attributes); + base.AddSynthesizedAttributes(moduleBuilder, ref attributes); if (ContainingSymbol.Kind == SymbolKind.NamedType && ContainingSymbol.IsImplicitlyDeclared) { @@ -118,6 +119,8 @@ internal override void AddSynthesizedAttributes(ModuleCompilationState compilati internal override bool HasTypeArgumentsCustomModifiers => false; + internal override bool HasCodeAnalysisEmbeddedAttribute => false; + public override ImmutableArray GetTypeArgumentCustomModifiers(int ordinal) => GetEmptyTypeArgumentCustomModifiers(ordinal); public override ImmutableArray GetMembers() diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEmbeddedAttributeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEmbeddedAttributeSymbol.cs new file mode 100644 index 0000000000000..1ba12346cfb67 --- /dev/null +++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEmbeddedAttributeSymbol.cs @@ -0,0 +1,194 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.Cci; +using Roslyn.Utilities; +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Runtime.InteropServices; +using System.Linq; +using Microsoft.CodeAnalysis.CSharp.Emit; +using System.Diagnostics; + +namespace Microsoft.CodeAnalysis.CSharp.Symbols +{ + /// + /// Represents a compiler generated and embedded attribute type. + /// This type has the following properties: + /// 1) It is non-generic, sealed, internal, non-static class. + /// 2) It derives from System.Attribute + /// 3) It has Microsoft.CodeAnalysis.EmbdeddedAttribute + /// 4) It has System.Runtime.CompilerServices.CompilerGeneratedAttribute + /// 5) It has a parameter-less constructor + /// + internal sealed class SynthesizedEmbeddedAttributeSymbol : NamedTypeSymbol + { + private readonly string _name; + private readonly NamedTypeSymbol _baseType; + private readonly NamespaceSymbol _namespace; + private readonly ImmutableArray _members; + private readonly ModuleSymbol _module; + + public SynthesizedEmbeddedAttributeSymbol(AttributeDescription description, CSharpCompilation compilation, DiagnosticBag diagnostics) + { + _name = description.Name; + _baseType = compilation.GetWellKnownType(WellKnownType.System_Attribute); + + // Report errors in case base type was missing or bad + Binder.ReportUseSiteDiagnostics(_baseType, diagnostics, Location.None); + + Constructor = new SynthesizedEmbeddedAttributeConstructorSymbol(this); + _members = ImmutableArray.Create(Constructor); + _module = compilation.SourceModule; + + _namespace = compilation.SourceModule.GlobalNamespace; + foreach (var part in description.Namespace.Split('.')) + { + _namespace = new MissingNamespaceSymbol(_namespace, part); + } + } + + public SynthesizedEmbeddedAttributeConstructorSymbol Constructor { get; private set; } + + public override int Arity => 0; + + public override ImmutableArray TypeParameters => ImmutableArray.Empty; + + public override NamedTypeSymbol ConstructedFrom => this; + + public override bool MightContainExtensionMethods => false; + + public override string Name => _name; + + public override IEnumerable MemberNames => SpecializedCollections.SingletonEnumerable(Constructor.Name); + + public override Accessibility DeclaredAccessibility => Accessibility.Internal; + + public override TypeKind TypeKind => TypeKind.Class; + + public override Symbol ContainingSymbol => _namespace; + + internal override ModuleSymbol ContainingModule => _module; + + public override AssemblySymbol ContainingAssembly => _module.ContainingAssembly; + + public override NamespaceSymbol ContainingNamespace => _namespace; + + public override ImmutableArray Locations => ImmutableArray.Empty; + + public override ImmutableArray DeclaringSyntaxReferences => ImmutableArray.Empty; + + public override bool IsStatic => false; + + public override bool IsAbstract => false; + + public override bool IsSealed => true; + + internal override bool HasTypeArgumentsCustomModifiers => false; + + internal override ImmutableArray TypeArgumentsNoUseSiteDiagnostics => ImmutableArray.Empty; + + internal override bool MangleName => false; + + internal override bool HasCodeAnalysisEmbeddedAttribute => true; + + internal override bool HasSpecialName => false; + + internal override bool IsComImport => false; + + internal override bool IsWindowsRuntimeImport => false; + + internal override bool ShouldAddWinRTMembers => false; + + internal override bool IsSerializable => false; + + internal override TypeLayout Layout => default(TypeLayout); + + internal override CharSet MarshallingCharSet => DefaultMarshallingCharSet; + + internal override bool HasDeclarativeSecurity => false; + + internal override bool IsInterface => false; + + internal override NamedTypeSymbol BaseTypeNoUseSiteDiagnostics => _baseType; + + internal override ObsoleteAttributeData ObsoleteAttributeData => null; + + public override ImmutableArray GetMembers() => _members; + + public override ImmutableArray GetMembers(string name) => Constructor.Name == name ? _members : ImmutableArray.Empty; + + public override ImmutableArray GetTypeArgumentCustomModifiers(int ordinal) => ImmutableArray.Empty; + + public override ImmutableArray GetTypeMembers() => ImmutableArray.Empty; + + public override ImmutableArray GetTypeMembers(string name) => ImmutableArray.Empty; + + public override ImmutableArray GetTypeMembers(string name, int arity) => ImmutableArray.Empty; + + internal override ImmutableArray GetAppliedConditionalSymbols() => ImmutableArray.Empty; + + internal override AttributeUsageInfo GetAttributeUsageInfo() => AttributeUsageInfo.Default; + + internal override NamedTypeSymbol GetDeclaredBaseType(ConsList basesBeingResolved) => _baseType; + + internal override ImmutableArray GetDeclaredInterfaces(ConsList basesBeingResolved) => ImmutableArray.Empty; + internal override ImmutableArray GetEarlyAttributeDecodingMembers() => GetMembers(); + + internal override ImmutableArray GetEarlyAttributeDecodingMembers(string name) => GetMembers(name); + + internal override IEnumerable GetFieldsToEmit() => SpecializedCollections.EmptyEnumerable(); + + internal override ImmutableArray GetInterfacesToEmit() => ImmutableArray.Empty; + + internal override IEnumerable GetSecurityInformation() => null; + + internal override ImmutableArray InterfacesNoUseSiteDiagnostics(ConsList basesBeingResolved = null) => ImmutableArray.Empty; + + internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, ref ArrayBuilder attributes) + { + base.AddSynthesizedAttributes(moduleBuilder, ref attributes); + + AddSynthesizedAttribute( + ref attributes, + moduleBuilder.Compilation.TrySynthesizeAttribute(WellKnownMember.System_Runtime_CompilerServices_CompilerGeneratedAttribute__ctor)); + + AddSynthesizedAttribute( + ref attributes, + moduleBuilder.SynthesizeEmbeddedAttribute()); + } + + internal sealed class SynthesizedEmbeddedAttributeConstructorSymbol : SynthesizedInstanceConstructor + { + public SynthesizedEmbeddedAttributeConstructorSymbol(NamedTypeSymbol containingType) + : base(containingType) + { + } + + internal override void GenerateMethodBody(TypeCompilationState compilationState, DiagnosticBag diagnostics) + { + if (ContainingType.BaseType is MissingMetadataTypeSymbol) + { + // System_Attribute is missing. Don't generate anything + return; + } + + var factory = new SyntheticBoundNodeFactory(this, this.GetNonNullSyntaxNode(), compilationState, diagnostics); + factory.CurrentMethod = this; + + var baseConstructorCall = MethodCompiler.GenerateBaseParameterlessConstructorInitializer(this, diagnostics); + if (baseConstructorCall == null) + { + // This may happen if Attribute..ctor is not found or is inaccessible + return; + } + + var block = factory.Block( + factory.ExpressionStatement(baseConstructorCall), + factory.Return()); + + factory.CloseMethod(block); + } + } + } +} diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEnumValueFieldSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEnumValueFieldSymbol.cs index cbd19c31f3d36..9a8da43e92c9c 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEnumValueFieldSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEnumValueFieldSymbol.cs @@ -1,5 +1,6 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using Microsoft.CodeAnalysis.CSharp.Emit; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.CSharp.Symbols @@ -24,7 +25,7 @@ internal override TypeSymbol GetFieldType(ConsList fieldsBeingBound return ((SourceNamedTypeSymbol)ContainingType).EnumUnderlyingType; } - internal override void AddSynthesizedAttributes(ModuleCompilationState compilationState, ref ArrayBuilder attributes) + internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, ref ArrayBuilder attributes) { // no attributes should be emitted } diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedFieldLikeEventAccessorSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedFieldLikeEventAccessorSymbol.cs index da2fb796efa37..6be069fc206b6 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedFieldLikeEventAccessorSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedFieldLikeEventAccessorSymbol.cs @@ -75,9 +75,9 @@ internal override OneOrMany> GetAttributeDeclara return OneOrMany.Create(this.AssociatedEvent.AttributeDeclarationSyntaxList); } - internal override void AddSynthesizedAttributes(ModuleCompilationState compilationState, ref ArrayBuilder attributes) + internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, ref ArrayBuilder attributes) { - base.AddSynthesizedAttributes(compilationState, ref attributes); + base.AddSynthesizedAttributes(moduleBuilder, ref attributes); var compilation = this.DeclaringCompilation; AddSynthesizedAttribute(ref attributes, compilation.TrySynthesizeAttribute(WellKnownMember.System_Runtime_CompilerServices_CompilerGeneratedAttribute__ctor)); diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedFieldSymbolBase.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedFieldSymbolBase.cs index 89c07c8c0bfc0..1d67b5d640ef3 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedFieldSymbolBase.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedFieldSymbolBase.cs @@ -2,6 +2,7 @@ using System.Collections.Immutable; using System.Diagnostics; +using Microsoft.CodeAnalysis.CSharp.Emit; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.CSharp.Symbols @@ -37,9 +38,9 @@ internal abstract bool SuppressDynamicAttribute get; } - internal override void AddSynthesizedAttributes(ModuleCompilationState compilationState, ref ArrayBuilder attributes) + internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, ref ArrayBuilder attributes) { - base.AddSynthesizedAttributes(compilationState, ref attributes); + base.AddSynthesizedAttributes(moduleBuilder, ref attributes); CSharpCompilation compilation = this.DeclaringCompilation; diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedImplementationMethod.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedImplementationMethod.cs index 82f1a714a60ac..ace2901efa452 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedImplementationMethod.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedImplementationMethod.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; +using Microsoft.CodeAnalysis.CSharp.Emit; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.CSharp.Symbols @@ -79,9 +80,9 @@ public sealed override ImmutableArray RefCustomModifiers #endregion - internal override void AddSynthesizedAttributes(ModuleCompilationState compilationState, ref ArrayBuilder attributes) + internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, ref ArrayBuilder attributes) { - base.AddSynthesizedAttributes(compilationState, ref attributes); + base.AddSynthesizedAttributes(moduleBuilder, ref attributes); var compilation = this.DeclaringCompilation; if (this.ReturnType.ContainsDynamic() && compilation.HasDynamicEmitAttributes() && compilation.CanEmitBoolean()) diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedInstanceConstructor.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedInstanceConstructor.cs index 13b2a5e99ffed..65a6b4f18d860 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedInstanceConstructor.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedInstanceConstructor.cs @@ -266,6 +266,10 @@ internal sealed override int CalculateLocalSyntaxOffset(int localPosition, Synta return containingType.CalculateSyntaxOffsetInSynthesizedConstructor(localPosition, localTree, isStatic: false); } + internal sealed override DiagnosticInfo GetUseSiteDiagnostic() + { + return ReturnType.GetUseSiteDiagnostic(); + } #endregion } } diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedParameterSymbol.cs index 9e70f8deeb713..a0de45a4f4075 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedParameterSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedParameterSymbol.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Immutable; using System.Diagnostics; +using Microsoft.CodeAnalysis.CSharp.Emit; using Microsoft.CodeAnalysis.CSharp.Symbols; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; @@ -140,7 +141,7 @@ public override ImmutableArray DeclaringSyntaxReferences } } - internal override void AddSynthesizedAttributes(ModuleCompilationState compilationState, ref ArrayBuilder attributes) + internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, ref ArrayBuilder attributes) { // Emit [Dynamic] on synthesized parameter symbols when the original parameter was dynamic // in order to facilitate debugging. In the case the necessary attributes are missing @@ -162,7 +163,7 @@ internal override void AddSynthesizedAttributes(ModuleCompilationState compilati if (this.RefKind == RefKind.RefReadOnly) { - AddSynthesizedAttribute(ref attributes, this.DeclaringCompilation.SynthesizeReadOnlyAttribute()); + AddSynthesizedAttribute(ref attributes, moduleBuilder.SynthesizeIsReadOnlyAttribute(this)); } } } diff --git a/src/Compilers/CSharp/Portable/Symbols/Tuples/TupleTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Tuples/TupleTypeSymbol.cs index 4d151c6bcc335..66f3a9e2f8b86 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Tuples/TupleTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Tuples/TupleTypeSymbol.cs @@ -8,6 +8,7 @@ using System.Runtime.InteropServices; using Microsoft.Cci; using Microsoft.CodeAnalysis.Collections; +using Microsoft.CodeAnalysis.CSharp.Emit; using Microsoft.CodeAnalysis.RuntimeMembers; using Roslyn.Utilities; @@ -1516,7 +1517,7 @@ internal override ImmutableArray GetInterfacesToEmit() throw ExceptionUtilities.Unreachable; } - internal override IEnumerable GetCustomAttributesToEmit(ModuleCompilationState compilationState) + internal override IEnumerable GetCustomAttributesToEmit(PEModuleBuilder moduleBuilder) { throw ExceptionUtilities.Unreachable; } diff --git a/src/Compilers/CSharp/Portable/Symbols/Wrapped/WrappedNamedTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Wrapped/WrappedNamedTypeSymbol.cs index bff2077bd12dd..abeb2846b6de0 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Wrapped/WrappedNamedTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Wrapped/WrappedNamedTypeSymbol.cs @@ -174,6 +174,8 @@ internal override bool IsMetadataSealed return _underlyingType.IsMetadataSealed; } } + + internal override bool HasCodeAnalysisEmbeddedAttribute => _underlyingType.HasCodeAnalysisEmbeddedAttribute; internal override ObsoleteAttributeData ObsoleteAttributeData { diff --git a/src/Compilers/CSharp/Portable/Symbols/Wrapped/WrappedParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Wrapped/WrappedParameterSymbol.cs index e7b86fe3b8c19..a2ed940161e3f 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Wrapped/WrappedParameterSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Wrapped/WrappedParameterSymbol.cs @@ -5,6 +5,7 @@ using System.Globalization; using System.Runtime.InteropServices; using System.Threading; +using Microsoft.CodeAnalysis.CSharp.Emit; namespace Microsoft.CodeAnalysis.CSharp.Symbols { @@ -71,9 +72,9 @@ public override ImmutableArray GetAttributes() return _underlyingParameter.GetAttributes(); } - internal override void AddSynthesizedAttributes(ModuleCompilationState compilationState, ref ArrayBuilder attributes) + internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, ref ArrayBuilder attributes) { - _underlyingParameter.AddSynthesizedAttributes(compilationState, ref attributes); + _underlyingParameter.AddSynthesizedAttributes(moduleBuilder, ref attributes); } internal sealed override ConstantValue ExplicitDefaultConstantValue diff --git a/src/Compilers/CSharp/Portable/Syntax/SyntaxNodeExtensions.cs b/src/Compilers/CSharp/Portable/Syntax/SyntaxNodeExtensions.cs index 550553f4eea7e..f20a08e78704e 100644 --- a/src/Compilers/CSharp/Portable/Syntax/SyntaxNodeExtensions.cs +++ b/src/Compilers/CSharp/Portable/Syntax/SyntaxNodeExtensions.cs @@ -154,6 +154,16 @@ internal static RefKind GetRefKind(this TypeSyntax syntax) return refKind; } + internal static TypeSyntax SkipRef(this TypeSyntax syntax) + { + if (syntax.Kind() == SyntaxKind.RefType) + { + syntax = ((RefTypeSyntax)syntax).Type; + } + + return syntax; + } + internal static TypeSyntax SkipRef(this TypeSyntax syntax, out RefKind refKind) { refKind = RefKind.None; diff --git a/src/Compilers/CSharp/Test/Emit/Attributes/AttributeTests.cs b/src/Compilers/CSharp/Test/Emit/Attributes/AttributeTests.cs index f95e768cb194a..6999c503286b9 100644 --- a/src/Compilers/CSharp/Test/Emit/Attributes/AttributeTests.cs +++ b/src/Compilers/CSharp/Test/Emit/Attributes/AttributeTests.cs @@ -897,8 +897,6 @@ static void Main() Assert.Equal(2, parameters.Length); Assert.Equal(0, parameters[0].GetAttributes().Length); Assert.Equal(0, parameters[1].GetAttributes().Length); - Assert.Equal(0, parameters[0].GetSynthesizedAttributes().Length); - Assert.Equal(0, parameters[1].GetSynthesizedAttributes().Length); // BeginInvoke method: Has parameter attributes from delegate declaration parameters syntax var beginInvokeMethod = (MethodSymbol)delegateType.GetMember("BeginInvoke"); diff --git a/src/Compilers/CSharp/Test/Emit/Attributes/AttributeTests_Assembly.cs b/src/Compilers/CSharp/Test/Emit/Attributes/AttributeTests_Assembly.cs index 5798e61b98e8d..833c43747d8cc 100644 --- a/src/Compilers/CSharp/Test/Emit/Attributes/AttributeTests_Assembly.cs +++ b/src/Compilers/CSharp/Test/Emit/Attributes/AttributeTests_Assembly.cs @@ -954,7 +954,7 @@ private static void TestDuplicateAssemblyAttributesNotEmitted(AssemblySymbol ass // We should get only unique netmodule/assembly attributes here, duplicate ones should not be emitted. int expectedEmittedAttrsCount = expectedSrcAttrCount - expectedDuplicateAttrCount; - var allEmittedAttrs = ((SourceAssemblySymbol)assembly).GetCustomAttributesToEmit(new ModuleCompilationState(), + var allEmittedAttrs = ((SourceAssemblySymbol)assembly).GetCustomAttributesToEmit(GetDefaultPEBuilder(assembly.DeclaringCompilation), emittingRefAssembly: false, emittingAssemblyAttributesInNetModule: false); var emittedAttrs = allEmittedAttrs.Where(a => string.Equals(a.AttributeClass.Name, attrTypeName, StringComparison.Ordinal)).AsImmutable(); @@ -1244,7 +1244,7 @@ static void Main(string[] args) { } expectedDuplicateAttrCount: 1, attrTypeName: "AssemblyTitleAttribute"); - var attrs = ((SourceAssemblySymbol)consoleappCompilation.Assembly).GetCustomAttributesToEmit(new ModuleCompilationState(), + var attrs = ((SourceAssemblySymbol)consoleappCompilation.Assembly).GetCustomAttributesToEmit(GetDefaultPEBuilder(consoleappCompilation), emittingRefAssembly: false, emittingAssemblyAttributesInNetModule: false); foreach (var a in attrs) { diff --git a/src/Compilers/CSharp/Test/Emit/Attributes/AttributeTests_Embedded.cs b/src/Compilers/CSharp/Test/Emit/Attributes/AttributeTests_Embedded.cs new file mode 100644 index 0000000000000..1e90d6a2a2775 --- /dev/null +++ b/src/Compilers/CSharp/Test/Emit/Attributes/AttributeTests_Embedded.cs @@ -0,0 +1,435 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.CodeAnalysis.CSharp.Test.Utilities; +using Microsoft.CodeAnalysis.Test.Utilities; +using System.Linq; +using Xunit; + +namespace Microsoft.CodeAnalysis.CSharp.UnitTests +{ + public class AttributeTests_Embedded : CSharpTestBase + { + [Fact] + public void ReferencingEmbeddedAttributesFromTheSameAssemblySucceeds() + { + var code = @" +namespace Microsoft.CodeAnalysis +{ + internal class EmbeddedAttribute : System.Attribute { } +} +namespace TestReference +{ + [Microsoft.CodeAnalysis.Embedded] + internal class TestType1 { } + + [Microsoft.CodeAnalysis.EmbeddedAttribute] + internal class TestType2 { } + + internal class TestType3 { } +} +class Program +{ + public static void Main() + { + var obj1 = new TestReference.TestType1(); + var obj2 = new TestReference.TestType2(); + var obj3 = new TestReference.TestType3(); + } +}"; + + CreateStandardCompilation(code).VerifyEmitDiagnostics(); + } + + [Fact] + public void ReferencingEmbeddedAttributesFromADifferentAssemblyFails_Internal() + { + var reference = CreateStandardCompilation(@" +[assembly:System.Runtime.CompilerServices.InternalsVisibleToAttribute(""Source"")] +namespace Microsoft.CodeAnalysis +{ + internal class EmbeddedAttribute : System.Attribute { } +} +namespace TestReference +{ + [Microsoft.CodeAnalysis.Embedded] + internal class TestType1 { } + + [Microsoft.CodeAnalysis.EmbeddedAttribute] + internal class TestType2 { } + + internal class TestType3 { } +}"); + + var code = @" +class Program +{ + public static void Main() + { + var obj1 = new TestReference.TestType1(); + var obj2 = new TestReference.TestType2(); + var obj3 = new TestReference.TestType3(); // This should be fine + } +}"; + + CreateStandardCompilation(code, references: new[] { reference.ToMetadataReference() }, assemblyName: "Source").VerifyDiagnostics( + // (6,38): error CS0234: The type or namespace name 'TestType1' does not exist in the namespace 'TestReference' (are you missing an assembly reference?) + // var obj1 = new TestReference.TestType1(); + Diagnostic(ErrorCode.ERR_DottedTypeNameNotFoundInNS, "TestType1").WithArguments("TestType1", "TestReference").WithLocation(6, 38), + // (7,38): error CS0234: The type or namespace name 'TestType2' does not exist in the namespace 'TestReference' (are you missing an assembly reference?) + // var obj2 = new TestReference.TestType2(); + Diagnostic(ErrorCode.ERR_DottedTypeNameNotFoundInNS, "TestType2").WithArguments("TestType2", "TestReference").WithLocation(7, 38)); + } + + [Fact] + public void ReferencingEmbeddedAttributesFromADifferentAssemblyFails_Module() + { + var module = CreateStandardCompilation(@" +namespace Microsoft.CodeAnalysis +{ + internal class EmbeddedAttribute : System.Attribute { } +} +namespace TestReference +{ + [Microsoft.CodeAnalysis.Embedded] + internal class TestType1 { } + + [Microsoft.CodeAnalysis.EmbeddedAttribute] + internal class TestType2 { } + + internal class TestType3 { } +}", options: TestOptions.ReleaseModule); + + var reference = ModuleMetadata.CreateFromImage(module.EmitToArray()).GetReference(); + + var code = @" +class Program +{ + public static void Main() + { + var obj1 = new TestReference.TestType1(); + var obj2 = new TestReference.TestType2(); + var obj3 = new TestReference.TestType3(); // This should be fine + } +}"; + + CreateStandardCompilation(code, references: new[] { reference }, assemblyName: "Source").VerifyDiagnostics( + // (6,38): error CS0234: The type or namespace name 'TestType1' does not exist in the namespace 'TestReference' (are you missing an assembly reference?) + // var obj1 = new TestReference.TestType1(); + Diagnostic(ErrorCode.ERR_DottedTypeNameNotFoundInNS, "TestType1").WithArguments("TestType1", "TestReference").WithLocation(6, 38), + // (7,38): error CS0234: The type or namespace name 'TestType2' does not exist in the namespace 'TestReference' (are you missing an assembly reference?) + // var obj2 = new TestReference.TestType2(); + Diagnostic(ErrorCode.ERR_DottedTypeNameNotFoundInNS, "TestType2").WithArguments("TestType2", "TestReference").WithLocation(7, 38)); + } + + [Fact] + public void ReferencingEmbeddedAttributesFromADifferentAssemblyFails_Public() + { + var reference = CreateStandardCompilation(@" +namespace Microsoft.CodeAnalysis +{ + internal class EmbeddedAttribute : System.Attribute { } +} +namespace TestReference +{ + [Microsoft.CodeAnalysis.Embedded] + public class TestType1 { } + + [Microsoft.CodeAnalysis.EmbeddedAttribute] + public class TestType2 { } + + public class TestType3 { } +}"); + + var code = @" +class Program +{ + public static void Main() + { + var obj1 = new TestReference.TestType1(); + var obj2 = new TestReference.TestType2(); + var obj3 = new TestReference.TestType3(); // This should be fine + } +}"; + + CreateStandardCompilation(code, references: new[] { reference.ToMetadataReference() }).VerifyDiagnostics( + // (6,38): error CS0234: The type or namespace name 'TestType1' does not exist in the namespace 'TestReference' (are you missing an assembly reference?) + // var obj1 = new TestReference.TestType1(); + Diagnostic(ErrorCode.ERR_DottedTypeNameNotFoundInNS, "TestType1").WithArguments("TestType1", "TestReference").WithLocation(6, 38), + // (7,38): error CS0234: The type or namespace name 'TestType2' does not exist in the namespace 'TestReference' (are you missing an assembly reference?) + // var obj2 = new TestReference.TestType2(); + Diagnostic(ErrorCode.ERR_DottedTypeNameNotFoundInNS, "TestType2").WithArguments("TestType2", "TestReference").WithLocation(7, 38)); + } + + [Fact] + public void EmbeddedAttributeInSourceIsAllowedIfCompilerDoesNotNeedToGenerateOne() + { + var code = @" +namespace Microsoft.CodeAnalysis +{ + public class EmbeddedAttribute : System.Attribute { } +} +namespace OtherNamespace +{ + [Microsoft.CodeAnalysis.EmbeddedAttribute] + public class TestReference + { + public static int GetValue() => 3; + } +} +class Test +{ + public static void Main() + { + // This should be fine, as the compiler doesn't need to use an embedded attribute for this compilation + System.Console.Write(OtherNamespace.TestReference.GetValue()); + } +}"; + + CompileAndVerify(code, verify: false, expectedOutput: "3"); + } + + [Fact] + public void EmbeddedAttributeInSourceShouldTriggerAnErrorIfCompilerNeedsToGenerateOne() + { + var code = @" +namespace Microsoft.CodeAnalysis +{ + public class EmbeddedAttribute : System.Attribute { } +} +class Test +{ + public void M(ref readonly int p) + { + // This should trigger generating another EmbeddedAttribute + } +}"; + + CreateStandardCompilation(code, assemblyName: "testModule").VerifyEmitDiagnostics( + // (4,18): error CS8413: The type name 'Microsoft.CodeAnalysis.EmbeddedAttribute' is reserved to be used by the compiler. + // public class EmbeddedAttribute : System.Attribute { } + Diagnostic(ErrorCode.ERR_TypeReserved, "EmbeddedAttribute").WithArguments("Microsoft.CodeAnalysis.EmbeddedAttribute").WithLocation(4, 18)); + } + + [Fact] + public void EmbeddedAttributeInReferencedModuleShouldTriggerAnErrorIfCompilerNeedsToGenerateOne() + { + var module = CreateStandardCompilation(options: TestOptions.ReleaseModule, assemblyName: "testModule", text: @" +namespace Microsoft.CodeAnalysis +{ + public class EmbeddedAttribute : System.Attribute { } +}"); + + var moduleRef = ModuleMetadata.CreateFromImage(module.EmitToArray()).GetReference(); + + var code = @" +class Test +{ + public void M(ref readonly int p) + { + // This should trigger generating another EmbeddedAttribute + } +}"; + + CreateStandardCompilation(code, references: new[] { moduleRef }).VerifyEmitDiagnostics( + // error CS8004: Type 'EmbeddedAttribute' exported from module 'testModule.netmodule' conflicts with type declared in primary module of this assembly. + Diagnostic(ErrorCode.ERR_ExportedTypeConflictsWithDeclaration).WithArguments("Microsoft.CodeAnalysis.EmbeddedAttribute", "testModule.netmodule").WithLocation(1, 1)); + } + + [Fact] + public void EmbeddedAttributeForwardedToAnotherAssemblyShouldTriggerAnError() + { + var reference = CreateStandardCompilation(@" +namespace Microsoft.CodeAnalysis +{ + public class EmbeddedAttribute : System.Attribute { } +}").ToMetadataReference(); + + var code = @" +[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(Microsoft.CodeAnalysis.EmbeddedAttribute))] +class Test +{ + public void M(ref readonly int p) + { + // This should trigger generating another EmbeddedAttribute + } +}"; + + CreateStandardCompilation(code, references: new[] { reference }).VerifyEmitDiagnostics( + // error CS8006: Forwarded type 'EmbeddedAttribute' conflicts with type declared in primary module of this assembly. + Diagnostic(ErrorCode.ERR_ForwardedTypeConflictsWithDeclaration).WithArguments("Microsoft.CodeAnalysis.EmbeddedAttribute").WithLocation(1, 1)); + } + + [Fact] + public void CompilerShouldIgnorePublicEmbeddedAttributesInReferencedAssemblies() + { + var reference = CreateStandardCompilation(assemblyName: "testRef", text: @" +namespace Microsoft.CodeAnalysis +{ + public class EmbeddedAttribute : System.Attribute { } +} +namespace OtherNamespace +{ + public class TestReference { } +}").ToMetadataReference(); + + var code = @" +class Test +{ + // This should trigger generating another EmbeddedAttribute + public void M(ref readonly int p) + { + var obj = new OtherNamespace.TestReference(); // This should be fine + } +}"; + + CompileAndVerify(code, verify: false, additionalRefs: new[] { reference }, symbolValidator: module => + { + var attributeName = AttributeDescription.CodeAnalysisEmbeddedAttribute.FullName; + + var referenceAttribute = module.GetReferencedAssemblySymbols().Single(assembly => assembly.Name == "testRef").GetTypeByMetadataName(attributeName); + Assert.NotNull(referenceAttribute); + + var generatedAttribute = module.ContainingAssembly.GetTypeByMetadataName(attributeName); + Assert.NotNull(generatedAttribute); + + Assert.False(referenceAttribute.Equals(generatedAttribute)); + }); + } + + [Fact] + public void SynthesizingAttributeRequiresSystemAttribute_NonExisting() + { + var code = @" +namespace System +{ + public class Object {} + public class Void {} +} +public class Test +{ + public void M(ref readonly object x) { } // should trigger synthesizing IsReadOnly +}"; + + CreateCompilation(code).VerifyEmitDiagnostics(CodeAnalysis.Emit.EmitOptions.Default.WithRuntimeMetadataVersion("v4.0.30319"), + // error CS0518: Predefined type 'System.Attribute' is not defined or imported + Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound).WithArguments("System.Attribute").WithLocation(1, 1), + // error CS0518: Predefined type 'System.Attribute' is not defined or imported + Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound).WithArguments("System.Attribute").WithLocation(1, 1)); + } + + [Fact] + public void SynthesizingAttributeRequiresSystemAttribute_NoSystemObject() + { + var code = @" +namespace System +{ + public class Attribute {} + public class Void {} +} +public class Test +{ + public object M(ref readonly object x) { return x; } // should trigger synthesizing IsReadOnly +}"; + + CreateCompilation(code).VerifyEmitDiagnostics(CodeAnalysis.Emit.EmitOptions.Default.WithRuntimeMetadataVersion("v4.0.30319"), + // (4,18): error CS0518: Predefined type 'System.Object' is not defined or imported + // public class Attribute {} + Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "Attribute").WithArguments("System.Object"), + // (7,14): error CS0518: Predefined type 'System.Object' is not defined or imported + // public class Test + Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "Test").WithArguments("System.Object"), + // (5,18): error CS0518: Predefined type 'System.Object' is not defined or imported + // public class Void {} + Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "Void").WithArguments("System.Object").WithLocation(5, 18), + // (9,34): error CS0518: Predefined type 'System.Object' is not defined or imported + // public object M(ref readonly object x) { return x; } // should trigger synthesizing IsReadOnly + Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "object").WithArguments("System.Object").WithLocation(9, 34), + // (9,12): error CS0518: Predefined type 'System.Object' is not defined or imported + // public object M(ref readonly object x) { return x; } // should trigger synthesizing IsReadOnly + Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "object").WithArguments("System.Object").WithLocation(9, 12), + // (5,18): error CS1729: 'object' does not contain a constructor that takes 0 arguments + // public class Void {} + Diagnostic(ErrorCode.ERR_BadCtorArgCount, "Void").WithArguments("object", "0").WithLocation(5, 18), + // (4,18): error CS1729: 'object' does not contain a constructor that takes 0 arguments + // public class Attribute {} + Diagnostic(ErrorCode.ERR_BadCtorArgCount, "Attribute").WithArguments("object", "0").WithLocation(4, 18), + // (7,14): error CS1729: 'object' does not contain a constructor that takes 0 arguments + // public class Test + Diagnostic(ErrorCode.ERR_BadCtorArgCount, "Test").WithArguments("object", "0").WithLocation(7, 14)); + } + + [Fact] + public void SynthesizingAttributeRequiresSystemAttribute_NoSystemVoid() + { + var code = @" +namespace System +{ + public class Attribute {} + public class Object {} +} +public class Test +{ + public object M(ref readonly object x) { return x; } // should trigger synthesizing IsReadOnly +}"; + + CreateCompilation(code).VerifyEmitDiagnostics(CodeAnalysis.Emit.EmitOptions.Default.WithRuntimeMetadataVersion("v4.0.30319"), + // (7,14): error CS0518: Predefined type 'System.Void' is not defined or imported + // public class Test + Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "Test").WithArguments("System.Void").WithLocation(7, 14), + // (4,18): error CS0518: Predefined type 'System.Void' is not defined or imported + // public class Attribute {} + Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "Attribute").WithArguments("System.Void").WithLocation(4, 18), + // error CS0518: Predefined type 'System.Void' is not defined or imported + Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound).WithArguments("System.Void").WithLocation(1, 1), + // error CS0518: Predefined type 'System.Void' is not defined or imported + Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound).WithArguments("System.Void").WithLocation(1, 1)); + } + + [Fact] + public void SynthesizingAttributeRequiresSystemAttribute_NoDefaultConstructor() + { + var code = @" +namespace System +{ + public class Object {} + public class Void {} + public class Attribute + { + public Attribute(object p) { } + } +} +public class Test +{ + public void M(ref readonly object x) { } // should trigger synthesizing IsReadOnly +}"; + + CreateCompilation(code).VerifyEmitDiagnostics(CodeAnalysis.Emit.EmitOptions.Default.WithRuntimeMetadataVersion("v4.0.30319"), + // error CS1729: 'Attribute' does not contain a constructor that takes 0 arguments + Diagnostic(ErrorCode.ERR_BadCtorArgCount).WithArguments("System.Attribute", "0").WithLocation(1, 1), + // error CS1729: 'Attribute' does not contain a constructor that takes 0 arguments + Diagnostic(ErrorCode.ERR_BadCtorArgCount).WithArguments("System.Attribute", "0").WithLocation(1, 1)); + } + + [Fact] + public void EmbeddedTypesInAnAssemblyAreNotExposedExternally() + { + var compilation1 = CreateStandardCompilation(@" +namespace Microsoft.CodeAnalysis +{ + public class EmbeddedAttribute : System.Attribute { } +} +[Microsoft.CodeAnalysis.Embedded] +public class TestReference1 { } +public class TestReference2 { } +"); + + Assert.NotNull(compilation1.GetTypeByMetadataName("TestReference1")); + Assert.NotNull(compilation1.GetTypeByMetadataName("TestReference2")); + + var compilation2 = CreateStandardCompilation("", references: new[] { compilation1.EmitToImageReference() }); + + Assert.Null(compilation2.GetTypeByMetadataName("TestReference1")); + Assert.NotNull(compilation2.GetTypeByMetadataName("TestReference2")); + } + } +} diff --git a/src/Compilers/CSharp/Test/Emit/Attributes/AttributeTests_RefReadOnly.cs b/src/Compilers/CSharp/Test/Emit/Attributes/AttributeTests_RefReadOnly.cs index 0e86c3d1f6167..8e1bd360ec2a2 100644 --- a/src/Compilers/CSharp/Test/Emit/Attributes/AttributeTests_RefReadOnly.cs +++ b/src/Compilers/CSharp/Test/Emit/Attributes/AttributeTests_RefReadOnly.cs @@ -1,8 +1,11 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using Microsoft.CodeAnalysis.CSharp.Symbols; +using Microsoft.CodeAnalysis.CSharp.Symbols.Metadata.PE; +using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp.Test.Utilities; using Microsoft.CodeAnalysis.CSharp.UnitTests; +using Microsoft.CodeAnalysis.Test.Utilities; using Roslyn.Test.Utilities; using System.Collections.Immutable; using System.Linq; @@ -18,7 +21,7 @@ public void RefReadOnlyIsWrittenToMetadata_SameAssembly_Method() var text = @" namespace System.Runtime.CompilerServices { - public class ReadOnlyAttribute : System.Attribute { } + public class IsReadOnlyAttribute : System.Attribute { } } class Test { @@ -35,8 +38,48 @@ class Test var parameter = method.GetParameters().Single(); Assert.Equal(RefKind.RefReadOnly, parameter.RefKind); - AssertSingleReadOnlyAttribute(parameter.GetAttributes(), module.ContainingAssembly.Name); - AssertSingleReadOnlyAttribute(method.GetReturnTypeAttributes(), module.ContainingAssembly.Name); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, parameter.GetAttributes(), module.ContainingAssembly.Name); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, method.GetReturnTypeAttributes(), module.ContainingAssembly.Name); + }); + } + + [Fact] + public void RefReadOnlyIsWrittenToMetadata_NeedsToBeGenerated_Method_Parameter() + { + var text = @" +class Test +{ + public void M(ref readonly int x) { } +} +"; + + CompileAndVerify(text, symbolValidator: module => + { + var parameter = module.ContainingAssembly.GetTypeByMetadataName("Test").GetMethod("M").GetParameters().Single(); + Assert.Equal(RefKind.RefReadOnly, parameter.RefKind); + + AssertReferencedIsReadOnlyAttribute(Accessibility.Internal, parameter.GetAttributes(), module.ContainingAssembly.Name); + }); + } + + [Fact] + public void RefReadOnlyIsWrittenToMetadata_NeedsToBeGenerated_Method_ReturnType() + { + var text = @" +class Test +{ + private int x; + public ref readonly int M() { return ref x; } +} +"; + + CompileAndVerify(text, symbolValidator: module => + { + var method = module.ContainingAssembly.GetTypeByMetadataName("Test").GetMethod("M"); + Assert.Equal(RefKind.RefReadOnly, method.RefKind); + Assert.True(method.ReturnsByRefReadonly); + + AssertReferencedIsReadOnlyAttribute(Accessibility.Internal, method.GetReturnTypeAttributes(), module.ContainingAssembly.Name); }); } @@ -46,7 +89,7 @@ public void RefReadOnlyIsWrittenToMetadata_DifferentAssembly_Method() var codeA = @" namespace System.Runtime.CompilerServices { - public class ReadOnlyAttribute : System.Attribute { } + public class IsReadOnlyAttribute : System.Attribute { } }"; var referenceA = CreateStandardCompilation(codeA).VerifyDiagnostics().ToMetadataReference(); @@ -67,8 +110,162 @@ class Test var parameter = method.GetParameters().Single(); Assert.Equal(RefKind.RefReadOnly, parameter.RefKind); - AssertSingleReadOnlyAttribute(parameter.GetAttributes(), referenceA.Compilation.AssemblyName); - AssertSingleReadOnlyAttribute(method.GetReturnTypeAttributes(), referenceA.Compilation.AssemblyName); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, parameter.GetAttributes(), referenceA.Compilation.AssemblyName); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, method.GetReturnTypeAttributes(), referenceA.Compilation.AssemblyName); + + AssertNoIsReadOnlyAttributeExists(module.ContainingAssembly); + }); + } + + [Fact] + public void RefReadOnlyIsWrittenToMetadata_SameAssembly_Operator() + { + var text = @" +namespace System.Runtime.CompilerServices +{ + public class IsReadOnlyAttribute : System.Attribute { } +} +struct Test +{ + public static int operator +(ref readonly Test x, ref readonly Test y) { return 0; } +} +"; + + CompileAndVerify(text, symbolValidator: module => + { + var method = module.ContainingAssembly.GetTypeByMetadataName("Test").GetMethod("op_Addition"); + Assert.Equal(2, method.ParameterCount); + + foreach (var parameter in method.Parameters) + { + Assert.Equal(RefKind.RefReadOnly, parameter.RefKind); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, parameter.GetAttributes(), module.ContainingAssembly.Name); + } + }); + } + + [Fact] + public void RefReadOnlyIsWrittenToMetadata_NeedsToBeGenerated_Operator_Parameter() + { + var text = @" +struct Test +{ + public static int operator +(ref readonly Test x, ref readonly Test y) { return 0; } +} +"; + + CompileAndVerify(text, symbolValidator: module => + { + var method = module.ContainingAssembly.GetTypeByMetadataName("Test").GetMethod("op_Addition"); + Assert.Equal(2, method.ParameterCount); + + foreach (var parameter in method.Parameters) + { + AssertReferencedIsReadOnlyAttribute(Accessibility.Internal, parameter.GetAttributes(), module.ContainingAssembly.Name); + } + }); + } + + [Fact] + public void RefReadOnlyIsWrittenToMetadata_Operator_Method() + { + var codeA = @" +namespace System.Runtime.CompilerServices +{ + public class IsReadOnlyAttribute : System.Attribute { } +}"; + + var referenceA = CreateStandardCompilation(codeA).VerifyDiagnostics().ToMetadataReference(); + + var codeB = @" +struct Test +{ + public static int operator +(ref readonly Test x, ref readonly Test y) { return 0; } +} +"; + + CompileAndVerify(codeB, additionalRefs: new[] { referenceA }, symbolValidator: module => + { + var method = module.ContainingAssembly.GetTypeByMetadataName("Test").GetMethod("op_Addition"); + Assert.Equal(2, method.ParameterCount); + foreach (var parameter in method.Parameters) + { + Assert.Equal(RefKind.RefReadOnly, parameter.RefKind); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, parameter.GetAttributes(), referenceA.Compilation.AssemblyName); + } + + AssertNoIsReadOnlyAttributeExists(module.ContainingAssembly); + + }); + } + + [Fact] + public void RefReadOnlyIsWrittenToMetadata_SameAssembly_Constructor() + { + var text = @" +namespace System.Runtime.CompilerServices +{ + public class IsReadOnlyAttribute : System.Attribute { } +} +class Test +{ + public Test(ref readonly int x) { } +} +"; + + CompileAndVerify(text, symbolValidator: module => + { + var parameter = module.ContainingAssembly.GetTypeByMetadataName("Test").GetMethod(".ctor").Parameters.Single(); + + Assert.Equal(RefKind.RefReadOnly, parameter.RefKind); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, parameter.GetAttributes(), module.ContainingAssembly.Name); + }); + } + + [Fact] + public void RefReadOnlyIsWrittenToMetadata_NeedsToBeGenerated_Constructor_Parameter() + { + var text = @" +class Test +{ + public Test(ref readonly int x) { } +} +"; + + CompileAndVerify(text, symbolValidator: module => + { + var parameter = module.ContainingAssembly.GetTypeByMetadataName("Test").GetMethod(".ctor").Parameters.Single(); + AssertReferencedIsReadOnlyAttribute(Accessibility.Internal, parameter.GetAttributes(), module.ContainingAssembly.Name); + }); + } + + [Fact] + public void RefReadOnlyIsWrittenToMetadata_Constructor_Method() + { + var codeA = @" +namespace System.Runtime.CompilerServices +{ + public class IsReadOnlyAttribute : System.Attribute { } +}"; + + var referenceA = CreateStandardCompilation(codeA).VerifyDiagnostics().ToMetadataReference(); + + var codeB = @" +class Test +{ + public Test(ref readonly int x) { } +} +"; + + CompileAndVerify(codeB, additionalRefs: new[] { referenceA }, symbolValidator: module => + { + var parameter = module.ContainingAssembly.GetTypeByMetadataName("Test").GetMethod(".ctor").Parameters.Single(); + + Assert.Equal(RefKind.RefReadOnly, parameter.RefKind); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, parameter.GetAttributes(), referenceA.Compilation.AssemblyName); + + AssertNoIsReadOnlyAttributeExists(module.ContainingAssembly); + }); } @@ -78,7 +275,7 @@ public void RefReadOnlyIsWrittenToMetadata_SameAssembly_Property() var text = @" namespace System.Runtime.CompilerServices { - public class ReadOnlyAttribute : System.Attribute { } + public class IsReadOnlyAttribute : System.Attribute { } } class Test { @@ -88,7 +285,36 @@ class Test } "; - CompileAndVerify(text, verify: false, symbolValidator: module => + CompileAndVerify(text, symbolValidator: module => + { + var type = module.ContainingAssembly.GetTypeByMetadataName("Test"); + + AssertProperty(type.GetProperty("P1")); + AssertProperty(type.GetProperty("P2")); + + void AssertProperty(PropertySymbol property) + { + Assert.Equal(RefKind.RefReadOnly, property.RefKind); + Assert.True(property.ReturnsByRefReadonly); + + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, property.GetAttributes(), module.ContainingAssembly.Name); + } + }); + } + + [Fact] + public void RefReadOnlyIsWrittenToMetadata_NeedsToBeGenerated_Property() + { + var text = @" +class Test +{ + private int x = 0; + public ref readonly int P1 { get { return ref x; } } + public ref readonly int P2 => ref x; +} +"; + + CompileAndVerify(text, symbolValidator: module => { var type = module.ContainingAssembly.GetTypeByMetadataName("Test"); @@ -100,7 +326,7 @@ void AssertProperty(PropertySymbol property) Assert.Equal(RefKind.RefReadOnly, property.RefKind); Assert.True(property.ReturnsByRefReadonly); - AssertSingleReadOnlyAttribute(property.GetAttributes(), module.ContainingAssembly.Name); + AssertReferencedIsReadOnlyAttribute(Accessibility.Internal, property.GetAttributes(), module.ContainingAssembly.Name); } }); } @@ -111,7 +337,7 @@ public void RefReadOnlyIsWrittenToMetadata_DifferentAssembly_Property() var codeA = @" namespace System.Runtime.CompilerServices { - public class ReadOnlyAttribute : System.Attribute { } + public class IsReadOnlyAttribute : System.Attribute { } }"; var referenceA = CreateStandardCompilation(codeA).VerifyDiagnostics().ToMetadataReference(); @@ -125,7 +351,7 @@ class Test } "; - CompileAndVerify(codeB, verify: false, additionalRefs: new[] { referenceA }, symbolValidator: module => + CompileAndVerify(codeB, additionalRefs: new[] { referenceA }, symbolValidator: module => { var type = module.ContainingAssembly.GetTypeByMetadataName("Test"); @@ -137,7 +363,9 @@ void AssertProperty(PropertySymbol property) Assert.Equal(RefKind.RefReadOnly, property.RefKind); Assert.True(property.ReturnsByRefReadonly); - AssertSingleReadOnlyAttribute(property.GetAttributes(), referenceA.Compilation.AssemblyName); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, property.GetAttributes(), referenceA.Compilation.AssemblyName); + + AssertNoIsReadOnlyAttributeExists(module.ContainingAssembly); } }); } @@ -148,7 +376,7 @@ public void RefReadOnlyIsWrittenToMetadata_SameAssembly_Indexer() var text = @" namespace System.Runtime.CompilerServices { - public class ReadOnlyAttribute : System.Attribute { } + public class IsReadOnlyAttribute : System.Attribute { } } class Test { @@ -164,9 +392,49 @@ class Test var parameter = indexer.GetParameters().Single(); Assert.Equal(RefKind.RefReadOnly, parameter.RefKind); - - AssertSingleReadOnlyAttribute(parameter.GetAttributes(), module.ContainingAssembly.Name); - AssertSingleReadOnlyAttribute(indexer.GetAttributes(), module.ContainingAssembly.Name); + + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, parameter.GetAttributes(), module.ContainingAssembly.Name); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, indexer.GetAttributes(), module.ContainingAssembly.Name); + }); + } + + [Fact] + public void RefReadOnlyIsWrittenToMetadata_NeedsToBeGenerated_Indexer_Parameter() + { + var text = @" +class Test +{ + public int this[ref readonly int x] { get { return x; } } +} +"; + + CompileAndVerify(text, symbolValidator: module => + { + var parameter = module.ContainingAssembly.GetTypeByMetadataName("Test").GetProperty("this[]").GetParameters().Single(); + Assert.Equal(RefKind.RefReadOnly, parameter.RefKind); + + AssertReferencedIsReadOnlyAttribute(Accessibility.Internal, parameter.GetAttributes(), module.ContainingAssembly.Name); + }); + } + + [Fact] + public void RefReadOnlyIsWrittenToMetadata_NeedsToBeGenerated_Indexer_ReturnType() + { + var text = @" +class Test +{ + private int x; + public ref readonly int this[int p] { get { return ref x; } } +} +"; + + CompileAndVerify(text, symbolValidator: module => + { + var indexer = module.ContainingAssembly.GetTypeByMetadataName("Test").GetProperty("this[]"); + Assert.Equal(RefKind.RefReadOnly, indexer.RefKind); + Assert.True(indexer.ReturnsByRefReadonly); + + AssertReferencedIsReadOnlyAttribute(Accessibility.Internal, indexer.GetAttributes(), module.ContainingAssembly.Name); }); } @@ -176,7 +444,7 @@ public void RefReadOnlyIsWrittenToMetadata_DifferentAssembly_Indexer() var codeA = @" namespace System.Runtime.CompilerServices { - public class ReadOnlyAttribute : System.Attribute { } + public class IsReadOnlyAttribute : System.Attribute { } }"; var referenceA = CreateStandardCompilation(codeA).VerifyDiagnostics().ToMetadataReference(); @@ -197,8 +465,10 @@ class Test var parameter = indexer.GetParameters().Single(); Assert.Equal(RefKind.RefReadOnly, parameter.RefKind); - AssertSingleReadOnlyAttribute(parameter.GetAttributes(), referenceA.Compilation.AssemblyName); - AssertSingleReadOnlyAttribute(indexer.GetAttributes(), referenceA.Compilation.AssemblyName); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, parameter.GetAttributes(), referenceA.Compilation.AssemblyName); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, indexer.GetAttributes(), referenceA.Compilation.AssemblyName); + + AssertNoIsReadOnlyAttributeExists(module.ContainingAssembly); }); } @@ -208,12 +478,12 @@ public void RefReadOnlyIsWrittenToMetadata_SameAssembly_Delegate() var text = @" namespace System.Runtime.CompilerServices { - public class ReadOnlyAttribute : System.Attribute { } + public class IsReadOnlyAttribute : System.Attribute { } } public delegate ref readonly int D(ref readonly int x); "; - CompileAndVerify(text, verify: false, symbolValidator: module => + CompileAndVerify(text, symbolValidator: module => { var method = module.ContainingAssembly.GetTypeByMetadataName("D").DelegateInvokeMethod; Assert.Equal(RefKind.RefReadOnly, method.RefKind); @@ -222,8 +492,41 @@ public class ReadOnlyAttribute : System.Attribute { } var parameter = method.GetParameters().Single(); Assert.Equal(RefKind.RefReadOnly, parameter.RefKind); - AssertSingleReadOnlyAttribute(parameter.GetAttributes(), module.ContainingAssembly.Name); - AssertSingleReadOnlyAttribute(method.GetReturnTypeAttributes(), module.ContainingAssembly.Name); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, parameter.GetAttributes(), module.ContainingAssembly.Name); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, method.GetReturnTypeAttributes(), module.ContainingAssembly.Name); + }); + } + + [Fact] + public void RefReadOnlyIsWrittenToMetadata_NeedsToBeGenerated_Delegate_Parameter() + { + var text = @" +public delegate void D(ref readonly int x); +"; + + CompileAndVerify(text, symbolValidator: module => + { + var parameter = module.ContainingAssembly.GetTypeByMetadataName("D").DelegateInvokeMethod.GetParameters().Single(); + Assert.Equal(RefKind.RefReadOnly, parameter.RefKind); + + AssertReferencedIsReadOnlyAttribute(Accessibility.Internal, parameter.GetAttributes(), module.ContainingAssembly.Name); + }); + } + + [Fact] + public void RefReadOnlyIsWrittenToMetadata_NeedsToBeGenerated_Delegate_ReturnType() + { + var text = @" +public delegate ref readonly int D(); +"; + + CompileAndVerify(text, symbolValidator: module => + { + var method = module.ContainingAssembly.GetTypeByMetadataName("D").DelegateInvokeMethod; + Assert.Equal(RefKind.RefReadOnly, method.RefKind); + Assert.True(method.ReturnsByRefReadonly); + + AssertReferencedIsReadOnlyAttribute(Accessibility.Internal, method.GetReturnTypeAttributes(), module.ContainingAssembly.Name); }); } @@ -233,7 +536,7 @@ public void RefReadOnlyIsWrittenToMetadata_DifferentAssembly_Delegate() var codeA = @" namespace System.Runtime.CompilerServices { - public class ReadOnlyAttribute : System.Attribute { } + public class IsReadOnlyAttribute : System.Attribute { } }"; var referenceA = CreateStandardCompilation(codeA).VerifyDiagnostics().ToMetadataReference(); @@ -242,7 +545,7 @@ public class ReadOnlyAttribute : System.Attribute { } public delegate ref readonly int D(ref readonly int x); "; - CompileAndVerify(codeB, verify: false, additionalRefs: new[] { referenceA }, symbolValidator: module => + CompileAndVerify(codeB, additionalRefs: new[] { referenceA }, symbolValidator: module => { var method = module.ContainingAssembly.GetTypeByMetadataName("D").DelegateInvokeMethod; Assert.Equal(RefKind.RefReadOnly, method.RefKind); @@ -251,8 +554,10 @@ public class ReadOnlyAttribute : System.Attribute { } var parameter = method.GetParameters().Single(); Assert.Equal(RefKind.RefReadOnly, parameter.RefKind); - AssertSingleReadOnlyAttribute(parameter.GetAttributes(), referenceA.Compilation.AssemblyName); - AssertSingleReadOnlyAttribute(method.GetReturnTypeAttributes(), referenceA.Compilation.AssemblyName); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, parameter.GetAttributes(), referenceA.Compilation.AssemblyName); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, method.GetReturnTypeAttributes(), referenceA.Compilation.AssemblyName); + + AssertNoIsReadOnlyAttributeExists(module.ContainingAssembly); }); } @@ -262,7 +567,7 @@ public void RefReadOnlyIsWrittenToMetadata_SameAssembly_LocalFunctions() var text = @" namespace System.Runtime.CompilerServices { - public class ReadOnlyAttribute : System.Attribute { } + public class IsReadOnlyAttribute : System.Attribute { } } public class Test { @@ -286,56 +591,109 @@ ref readonly int Inner(ref readonly int x) var parameter = method.GetParameters().Single(); Assert.Equal(RefKind.RefReadOnly, parameter.RefKind); - AssertSingleReadOnlyAttribute(parameter.GetAttributes(), module.ContainingAssembly.Name); - AssertSingleReadOnlyAttribute(method.GetReturnTypeAttributes(), module.ContainingAssembly.Name); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, parameter.GetAttributes(), module.ContainingAssembly.Name); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, method.GetReturnTypeAttributes(), module.ContainingAssembly.Name); }); } [Fact] - public void RefReadOnlyIsWrittenToMetadata_DifferentAssembly_LocalFunctions() + public void RefReadOnlyIsWrittenToMetadata_NeedsToBeGenerated_LocalFunctions_Parameters() { - var codeA = @" -namespace System.Runtime.CompilerServices + var text = @" +public class Test { - public class ReadOnlyAttribute : System.Attribute { } -}"; + public void M() + { + void Inner(ref readonly int x) { } + } +} +"; - var referenceA = CreateStandardCompilation(codeA).VerifyDiagnostics().ToMetadataReference(); + var options = TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All); + CompileAndVerify(text, options: options, symbolValidator: module => + { + var parameter = module.ContainingAssembly.GetTypeByMetadataName("Test").GetMethod("g__Inner0_0").GetParameters().Single(); + Assert.Equal(RefKind.RefReadOnly, parameter.RefKind); - var codeB = @" + AssertReferencedIsReadOnlyAttribute(Accessibility.Internal, parameter.GetAttributes(), module.ContainingAssembly.Name); + }); + } + + [Fact] + public void RefReadOnlyIsWrittenToMetadata_NeedsToBeGenerated_LocalFunctions_ReturnType() + { + var text = @" public class Test { + private int x; public void M() { - ref readonly int Inner(ref readonly int x) + ref readonly int Inner() { return ref x; } } } "; + var options = TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All); - CompileAndVerify(codeB, verify: false, additionalRefs: new[] { referenceA }, options: options, symbolValidator: module => + CompileAndVerify(text, verify: false, options: options, symbolValidator: module => { - var method = module.ContainingAssembly.GetTypeByMetadataName("Test").GetMethod("g__Inner0_0"); + var method = module.ContainingAssembly.GetTypeByMetadataName("Test").GetMethod("g__Inner1_0"); Assert.Equal(RefKind.RefReadOnly, method.RefKind); Assert.True(method.ReturnsByRefReadonly); - var parameter = method.GetParameters().Single(); - Assert.Equal(RefKind.RefReadOnly, parameter.RefKind); - - AssertSingleReadOnlyAttribute(parameter.GetAttributes(), referenceA.Compilation.AssemblyName); - AssertSingleReadOnlyAttribute(method.GetReturnTypeAttributes(), referenceA.Compilation.AssemblyName); + AssertReferencedIsReadOnlyAttribute(Accessibility.Internal, method.GetReturnTypeAttributes(), module.ContainingAssembly.Name); }); } [Fact] - public void RefReadOnlyIsWrittenToMetadata_SameAssembly_Lambda() + public void RefReadOnlyIsWrittenToMetadata_DifferentAssembly_LocalFunctions() + { + var codeA = @" +namespace System.Runtime.CompilerServices +{ + public class IsReadOnlyAttribute : System.Attribute { } +}"; + + var referenceA = CreateStandardCompilation(codeA).VerifyDiagnostics().ToMetadataReference(); + + var codeB = @" +public class Test +{ + public void M() + { + ref readonly int Inner(ref readonly int x) + { + return ref x; + } + } +} +"; + var options = TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All); + CompileAndVerify(codeB, verify: false, additionalRefs: new[] { referenceA }, options: options, symbolValidator: module => + { + var method = module.ContainingAssembly.GetTypeByMetadataName("Test").GetMethod("g__Inner0_0"); + Assert.Equal(RefKind.RefReadOnly, method.RefKind); + Assert.True(method.ReturnsByRefReadonly); + + var parameter = method.GetParameters().Single(); + Assert.Equal(RefKind.RefReadOnly, parameter.RefKind); + + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, parameter.GetAttributes(), referenceA.Compilation.AssemblyName); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, method.GetReturnTypeAttributes(), referenceA.Compilation.AssemblyName); + + AssertNoIsReadOnlyAttributeExists(module.ContainingAssembly); + }); + } + + [Fact] + public void RefReadOnlyIsWrittenToMetadata_SameAssembly_Lambda() { var text = @" namespace System.Runtime.CompilerServices { - public class ReadOnlyAttribute : System.Attribute { } + public class IsReadOnlyAttribute : System.Attribute { } } delegate ref readonly int D(ref readonly int x); @@ -361,8 +719,64 @@ public void M2(D value) { } var parameter = method.GetParameters().Single(); Assert.Equal(RefKind.RefReadOnly, parameter.RefKind); - AssertSingleReadOnlyAttribute(parameter.GetAttributes(), module.ContainingAssembly.Name); - AssertSingleReadOnlyAttribute(method.GetReturnTypeAttributes(), module.ContainingAssembly.Name); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, parameter.GetAttributes(), module.ContainingAssembly.Name); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, method.GetReturnTypeAttributes(), module.ContainingAssembly.Name); + }); + } + + [Fact] + public void RefReadOnlyIsWrittenToMetadata_NeedsToBeGenerated_Lambda_Parameter() + { + var text = @" +delegate void D(ref readonly int x); + +class Test +{ + public void M1() + { + M2((ref readonly int x) => {}); + } + + public void M2(D value) { } +} +"; + + var options = TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All); + CompileAndVerify(text, options: options, symbolValidator: module => + { + var parameter = module.GlobalNamespace.GetMember("Test.<>c.b__0_0").GetParameters().Single(); + Assert.Equal(RefKind.RefReadOnly, parameter.RefKind); + + AssertReferencedIsReadOnlyAttribute(Accessibility.Internal, parameter.GetAttributes(), module.ContainingAssembly.Name); + }); + } + + [Fact] + public void RefReadOnlyIsWrittenToMetadata_NeedsToBeGenerated_Lambda_ReturnType() + { + var text = @" +delegate ref readonly int D(); + +class Test +{ + private int x; + public void M1() + { + M2(() => ref x); + } + + public void M2(D value) { } +} +"; + + var options = TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All); + CompileAndVerify(text, options: options, symbolValidator: module => + { + var method = module.GlobalNamespace.GetMember("Test.b__1_0"); + Assert.Equal(RefKind.RefReadOnly, method.RefKind); + Assert.True(method.ReturnsByRefReadonly); + + AssertReferencedIsReadOnlyAttribute(Accessibility.Internal, method.GetReturnTypeAttributes(), module.ContainingAssembly.Name); }); } @@ -372,7 +786,7 @@ public void RefReadOnlyIsWrittenToMetadata_DifferentAssembly_Lambda() var codeA = @" namespace System.Runtime.CompilerServices { - public class ReadOnlyAttribute : System.Attribute { } + public class IsReadOnlyAttribute : System.Attribute { } }"; var referenceA = CreateStandardCompilation(codeA).VerifyDiagnostics().ToMetadataReference(); @@ -401,18 +815,20 @@ public void M2(D value) { } var parameter = method.GetParameters().Single(); Assert.Equal(RefKind.RefReadOnly, parameter.RefKind); - AssertSingleReadOnlyAttribute(parameter.GetAttributes(), referenceA.Compilation.AssemblyName); - AssertSingleReadOnlyAttribute(method.GetReturnTypeAttributes(), referenceA.Compilation.AssemblyName); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, parameter.GetAttributes(), referenceA.Compilation.AssemblyName); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, method.GetReturnTypeAttributes(), referenceA.Compilation.AssemblyName); + + AssertNoIsReadOnlyAttributeExists(module.ContainingAssembly); }); } - + [Fact] - public void ReadOnlyAttributeIsDisallowedEverywhereInSource_Delegates() + public void IsReadOnlyAttributeIsDisallowedEverywhereInSource_Delegates() { var codeA = @" namespace System.Runtime.CompilerServices { - public class ReadOnlyAttribute : System.Attribute { } + public class IsReadOnlyAttribute : System.Attribute { } }"; var referenceA = CreateStandardCompilation(codeA).VerifyDiagnostics().ToMetadataReference(); @@ -420,26 +836,26 @@ public class ReadOnlyAttribute : System.Attribute { } var codeB = @" using System.Runtime.CompilerServices; -[ReadOnly] -public delegate ref readonly int D([ReadOnly] ref readonly int x); +[IsReadOnly] +public delegate ref readonly int D([IsReadOnly]ref readonly int x); "; CreateStandardCompilation(codeB, references: new[] { referenceA }).VerifyDiagnostics( - // (4,2): error CS8412: Do not use 'System.Runtime.CompilerServices.ReadOnlyAttribute'. This is reserved for compiler usage. - // [ReadOnly] - Diagnostic(ErrorCode.ERR_ExplicitReadOnlyAttr, "ReadOnly").WithLocation(4, 2), - // (5,37): error CS8412: Do not use 'System.Runtime.CompilerServices.ReadOnlyAttribute'. This is reserved for compiler usage. - // public delegate ref readonly int D([ReadOnly] ref readonly int x); - Diagnostic(ErrorCode.ERR_ExplicitReadOnlyAttr, "ReadOnly").WithLocation(5, 37)); + // (4,2): error CS8412: Do not use 'System.Runtime.CompilerServices.IsReadOnlyAttribute'. This is reserved for compiler usage. + // [IsReadOnly] + Diagnostic(ErrorCode.ERR_ExplicitReadOnlyAttr, "IsReadOnly").WithLocation(4, 2), + // (5,37): error CS8412: Do not use 'System.Runtime.CompilerServices.IsReadOnlyAttribute'. This is reserved for compiler usage. + // public delegate ref readonly int D([IsReadOnly]ref readonly int x); + Diagnostic(ErrorCode.ERR_ExplicitReadOnlyAttr, "IsReadOnly").WithLocation(5, 37)); } [Fact] - public void ReadOnlyAttributeIsDisallowedEverywhereInSource_Types() + public void IsReadOnlyAttributeIsDisallowedEverywhereInSource_Types() { var codeA = @" namespace System.Runtime.CompilerServices { - public class ReadOnlyAttribute : System.Attribute { } + public class IsReadOnlyAttribute : System.Attribute { } }"; var referenceA = CreateStandardCompilation(codeA).VerifyDiagnostics().ToMetadataReference(); @@ -447,25 +863,25 @@ public class ReadOnlyAttribute : System.Attribute { } var codeB = @" using System.Runtime.CompilerServices; -[ReadOnly] +[IsReadOnly] public class Test { } "; CreateStandardCompilation(codeB, references: new[] { referenceA }).VerifyDiagnostics( - // (4,2): error CS8412: Do not use 'System.Runtime.CompilerServices.ReadOnlyAttribute'. This is reserved for compiler usage. - // [ReadOnly] - Diagnostic(ErrorCode.ERR_ExplicitReadOnlyAttr, "ReadOnly").WithLocation(4, 2)); + // (4,2): error CS8412: Do not use 'System.Runtime.CompilerServices.IsReadOnlyAttribute'. This is reserved for compiler usage. + // [IsReadOnly] + Diagnostic(ErrorCode.ERR_ExplicitReadOnlyAttr, "IsReadOnly").WithLocation(4, 2)); } [Fact] - public void ReadOnlyAttributeIsDisallowedEverywhereInSource_Fields() + public void IsReadOnlyAttributeIsDisallowedEverywhereInSource_Fields() { var codeA = @" namespace System.Runtime.CompilerServices { - public class ReadOnlyAttribute : System.Attribute { } + public class IsReadOnlyAttribute : System.Attribute { } }"; var referenceA = CreateStandardCompilation(codeA).VerifyDiagnostics().ToMetadataReference(); @@ -475,7 +891,7 @@ public class ReadOnlyAttribute : System.Attribute { } public class Test { - [ReadOnly] + [IsReadOnly] private int x = 0; public int X => x; @@ -483,18 +899,18 @@ public class Test "; CreateStandardCompilation(codeB, references: new[] { referenceA }).VerifyDiagnostics( - // (6,6): error CS8412: Do not use 'System.Runtime.CompilerServices.ReadOnlyAttribute'. This is reserved for compiler usage. - // [ReadOnly] - Diagnostic(ErrorCode.ERR_ExplicitReadOnlyAttr, "ReadOnly").WithLocation(6, 6)); + // (6,6): error CS8412: Do not use 'System.Runtime.CompilerServices.IsReadOnlyAttribute'. This is reserved for compiler usage. + // [IsReadOnly] + Diagnostic(ErrorCode.ERR_ExplicitReadOnlyAttr, "IsReadOnly").WithLocation(6, 6)); } [Fact] - public void ReadOnlyAttributeIsDisallowedEverywhereInSource_Properties() + public void IsReadOnlyAttributeIsDisallowedEverywhereInSource_Properties() { var codeA = @" namespace System.Runtime.CompilerServices { - public class ReadOnlyAttribute : System.Attribute { } + public class IsReadOnlyAttribute : System.Attribute { } }"; var referenceA = CreateStandardCompilation(codeA).VerifyDiagnostics().ToMetadataReference(); @@ -506,24 +922,24 @@ public class Test { private int x = 0; - [ReadOnly] + [IsReadOnly] public ref readonly int Property => ref x; } "; CreateStandardCompilation(codeB, references: new[] { referenceA }).VerifyDiagnostics( - // (8,6): error CS8412: Do not use 'System.Runtime.CompilerServices.ReadOnlyAttribute'. This is reserved for compiler usage. - // [ReadOnly] - Diagnostic(ErrorCode.ERR_ExplicitReadOnlyAttr, "ReadOnly").WithLocation(8, 6)); + // (8,6): error CS8412: Do not use 'System.Runtime.CompilerServices.IsReadOnlyAttribute'. This is reserved for compiler usage. + // [IsReadOnly] + Diagnostic(ErrorCode.ERR_ExplicitReadOnlyAttr, "IsReadOnly").WithLocation(8, 6)); } [Fact] - public void ReadOnlyAttributeIsDisallowedEverywhereInSource_Methods() + public void IsReadOnlyAttributeIsDisallowedEverywhereInSource_Methods() { var codeA = @" namespace System.Runtime.CompilerServices { - public class ReadOnlyAttribute : System.Attribute { } + public class IsReadOnlyAttribute : System.Attribute { } }"; var referenceA = CreateStandardCompilation(codeA).VerifyDiagnostics().ToMetadataReference(); @@ -533,34 +949,34 @@ public class ReadOnlyAttribute : System.Attribute { } public class Test { - [ReadOnly] - [return: ReadOnly] - public ref readonly int Method([ReadOnly] ref readonly int x) + [IsReadOnly] + [return: IsReadOnly] + public ref readonly int Method([IsReadOnly]ref readonly int x) { return ref x; } } "; - CreateCompilationWithMscorlibAndSystemCore(codeB, references: new[] { referenceA }).VerifyDiagnostics( - // (6,6): error CS8412: Do not use 'System.Runtime.CompilerServices.ReadOnlyAttribute'. This is reserved for compiler usage. - // [ReadOnly] - Diagnostic(ErrorCode.ERR_ExplicitReadOnlyAttr, "ReadOnly").WithLocation(6, 6), - // (7,14): error CS8412: Do not use 'System.Runtime.CompilerServices.ReadOnlyAttribute'. This is reserved for compiler usage. - // [return: ReadOnly] - Diagnostic(ErrorCode.ERR_ExplicitReadOnlyAttr, "ReadOnly").WithLocation(7, 14), - // (8,37): error CS8412: Do not use 'System.Runtime.CompilerServices.ReadOnlyAttribute'. This is reserved for compiler usage. - // public ref readonly int Method([ReadOnly] ref readonly int x) - Diagnostic(ErrorCode.ERR_ExplicitReadOnlyAttr, "ReadOnly").WithLocation(8, 37)); + CreateStandardCompilation(codeB, references: new[] { referenceA }).VerifyDiagnostics( + // (6,6): error CS8412: Do not use 'System.Runtime.CompilerServices.IsReadOnlyAttribute'. This is reserved for compiler usage. + // [IsReadOnly] + Diagnostic(ErrorCode.ERR_ExplicitReadOnlyAttr, "IsReadOnly").WithLocation(6, 6), + // (7,14): error CS8412: Do not use 'System.Runtime.CompilerServices.IsReadOnlyAttribute'. This is reserved for compiler usage. + // [return: IsReadOnly] + Diagnostic(ErrorCode.ERR_ExplicitReadOnlyAttr, "IsReadOnly").WithLocation(7, 14), + // (8,37): error CS8412: Do not use 'System.Runtime.CompilerServices.IsReadOnlyAttribute'. This is reserved for compiler usage. + // public ref readonly int Method([IsReadOnly]ref readonly int x) + Diagnostic(ErrorCode.ERR_ExplicitReadOnlyAttr, "IsReadOnly").WithLocation(8, 37)); } [Fact] - public void ReadOnlyAttributeIsDisallowedEverywhereInSource_Indexers() + public void IsReadOnlyAttributeIsDisallowedEverywhereInSource_Indexers() { var codeA = @" namespace System.Runtime.CompilerServices { - public class ReadOnlyAttribute : System.Attribute { } + public class IsReadOnlyAttribute : System.Attribute { } }"; var referenceA = CreateStandardCompilation(codeA).VerifyDiagnostics().ToMetadataReference(); @@ -570,25 +986,1389 @@ public class ReadOnlyAttribute : System.Attribute { } public class Test { - [ReadOnly] - public ref readonly int this[[ReadOnly] ref readonly int x] { get { return ref x; } } + [IsReadOnly] + public ref readonly int this[[IsReadOnly]ref readonly int x] { get { return ref x; } } } "; CreateStandardCompilation(codeB, references: new[] { referenceA }).VerifyDiagnostics( - // (6,6): error CS8412: Do not use 'System.Runtime.CompilerServices.ReadOnlyAttribute'. This is reserved for compiler usage. - // [ReadOnly] - Diagnostic(ErrorCode.ERR_ExplicitReadOnlyAttr, "ReadOnly").WithLocation(6, 6), - // (7,35): error CS8412: Do not use 'System.Runtime.CompilerServices.ReadOnlyAttribute'. This is reserved for compiler usage. - // public ref readonly int this[[ReadOnly] ref readonly int x] { get { return ref x; } } - Diagnostic(ErrorCode.ERR_ExplicitReadOnlyAttr, "ReadOnly").WithLocation(7, 35)); + // (6,6): error CS8412: Do not use 'System.Runtime.CompilerServices.IsReadOnlyAttribute'. This is reserved for compiler usage. + // [IsReadOnly] + Diagnostic(ErrorCode.ERR_ExplicitReadOnlyAttr, "IsReadOnly").WithLocation(6, 6), + // (7,35): error CS8412: Do not use 'System.Runtime.CompilerServices.IsReadOnlyAttribute'. This is reserved for compiler usage. + // public ref readonly int this[[IsReadOnly]ref readonly int x] { get { return ref x; } } + Diagnostic(ErrorCode.ERR_ExplicitReadOnlyAttr, "IsReadOnly").WithLocation(7, 35)); } - private void AssertSingleReadOnlyAttribute(ImmutableArray attributes, string assemblyName) + [Fact] + public void UserReferencingEmbeddedAttributeShouldResultInAnError() { - var attributeType = attributes.Single().AttributeClass; - Assert.Equal("ReadOnlyAttribute", attributeType.MetadataName); - Assert.Equal(assemblyName, attributeType.ContainingAssembly.Name); + var code = @" +[Embedded] +public class Test +{ + public ref readonly int M(ref readonly int p) => ref p; +}"; + + CreateStandardCompilation(code).VerifyDiagnostics( + // (2,2): error CS0246: The type or namespace name 'EmbeddedAttribute' could not be found (are you missing a using directive or an assembly reference?) + // [Embedded] + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "Embedded").WithArguments("EmbeddedAttribute").WithLocation(2, 2), + // (2,2): error CS0246: The type or namespace name 'Embedded' could not be found (are you missing a using directive or an assembly reference?) + // [Embedded] + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "Embedded").WithArguments("Embedded").WithLocation(2, 2)); + } + + [Fact] + public void UserReferencingIsReadOnlyAttributeShouldResultInAnError() + { + var code = @" +[IsReadOnly] +public class Test +{ + public ref readonly int M(ref readonly int p) => ref p; +}"; + + CreateStandardCompilation(code).VerifyDiagnostics( + // (2,2): error CS0246: The type or namespace name 'IsReadOnlyAttribute' could not be found (are you missing a using directive or an assembly reference?) + // [IsReadOnly] + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "IsReadOnly").WithArguments("IsReadOnlyAttribute").WithLocation(2, 2), + // (2,2): error CS0246: The type or namespace name 'IsReadOnly' could not be found (are you missing a using directive or an assembly reference?) + // [IsReadOnly] + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "IsReadOnly").WithArguments("IsReadOnly").WithLocation(2, 2)); + } + + [Fact] + public void TypeReferencingAnotherTypeThatUsesAPublicAttributeFromAThirdNotReferencedAssemblyShouldGenerateItsOwn() + { + var options = TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All); + + var code1 = CreateStandardCompilation(@" +namespace System.Runtime.CompilerServices +{ + public class IsReadOnlyAttribute : System.Attribute { } +}"); + + var code2 = CreateStandardCompilation(@" +public class Test1 +{ + public static ref readonly int M(ref readonly int p) => ref p; +}", references: new[] { code1.ToMetadataReference() }, options: options); + + CompileAndVerify(code2, verify: false, symbolValidator: module => + { + // IsReadOnly is not generated in assembly + var isReadOnlyAttributeName = WellKnownTypes.GetMetadataName(WellKnownType.System_Runtime_CompilerServices_IsReadOnlyAttribute); + Assert.Null(module.ContainingAssembly.GetTypeByMetadataName(isReadOnlyAttributeName)); + }); + + var code3 = CreateStandardCompilation(@" +public class Test2 +{ + public static ref readonly int M(ref readonly int p) => ref Test1.M(p); +}", references: new[] { code2.ToMetadataReference() }, options: options); + + CompileAndVerify(code3, symbolValidator: module => + { + // IsReadOnly is generated in assembly + AssertGeneratedEmbeddedAttribute(module.ContainingAssembly, AttributeDescription.CodeAnalysisEmbeddedAttribute.FullName); + AssertGeneratedEmbeddedAttribute(module.ContainingAssembly, AttributeDescription.IsReadOnlyAttribute.FullName); + }); + } + + [Fact] + public void BuildingAModuleRequiresIsReadOnlyAttributeToBeThere_Missing_SourceMethod() + { + var code = @" +public class Test +{ + public void M(ref readonly int x) { } +}"; + + CreateStandardCompilation(code, options: TestOptions.ReleaseModule).VerifyDiagnostics( + // (4,19): error CS0518: Predefined type 'System.Runtime.CompilerServices.IsReadOnlyAttribute' is not defined or imported + // public void M(ref readonly int x) { } + Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "ref readonly int x").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute").WithLocation(4, 19)); + } + + [Fact] + public void BuildingAModuleRequiresIsReadOnlyAttributeToBeThere_Missing_SourceMethod_MultipleLocations() + { + var code = @" +public class Test +{ + public void M1(ref readonly int x) { } + public void M2(ref readonly int x) { } +}"; + + CreateStandardCompilation(code, options: TestOptions.ReleaseModule).VerifyDiagnostics( + // (4,20): error CS0518: Predefined type 'System.Runtime.CompilerServices.IsReadOnlyAttribute' is not defined or imported + // public void M1(ref readonly int x) { } + Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "ref readonly int x").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute").WithLocation(4, 20), + // (5,20): error CS0518: Predefined type 'System.Runtime.CompilerServices.IsReadOnlyAttribute' is not defined or imported + // public void M2(ref readonly int x) { } + Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "ref readonly int x").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute").WithLocation(5, 20)); + } + + [Fact] + public void BuildingAModuleRequiresIsReadOnlyAttributeToBeThere_Missing_LocalFunctions() + { + var code = @" +public class Test +{ + public void Parent() + { + void child(ref readonly int p) { } + + int x = 0; + child(x); + } +}"; + + CreateStandardCompilation(code, options: TestOptions.ReleaseModule).VerifyDiagnostics( + // (6,20): error CS0518: Predefined type 'System.Runtime.CompilerServices.IsReadOnlyAttribute' is not defined or imported + // void child(ref readonly int p) { } + Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "ref readonly int p").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute").WithLocation(6, 20)); + } + + [Fact] + public void BuildingAModuleRequiresIsReadOnlyAttributeToBeThere_InAReference() + { + var reference = CreateStandardCompilation(@" +namespace System.Runtime.CompilerServices +{ + public class IsReadOnlyAttribute : System.Attribute { } +}").ToMetadataReference(); + + var code = @" +public class Test +{ + public void M(ref readonly int x) { } +}"; + + CompileAndVerify(code, verify: false, additionalRefs: new[] { reference }, options: TestOptions.ReleaseModule, symbolValidator: module => + { + AssertNoIsReadOnlyAttributeExists(module.ContainingAssembly); + + var parameter = module.ContainingAssembly.GetTypeByMetadataName("Test").GetMethod("M").GetParameters().Single(); + Assert.Equal(RefKind.RefReadOnly, parameter.RefKind); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, parameter.GetAttributes(), reference.Display); + }); + } + + [Fact] + public void ReferencingAnEmbeddedIsReadOnlyAttributeDoesNotUseIt_InternalsVisible() + { + var options = TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All); + + var code1 = @" +[assembly:System.Runtime.CompilerServices.InternalsVisibleToAttribute(""Assembly2"")] +public class Test1 +{ + public static ref readonly int M(ref readonly int p) => ref p; +}"; + + var comp1 = CompileAndVerify(code1, options: options, verify: false, symbolValidator: module => + { + AssertGeneratedEmbeddedAttribute(module.ContainingAssembly, AttributeDescription.CodeAnalysisEmbeddedAttribute.FullName); + AssertGeneratedEmbeddedAttribute(module.ContainingAssembly, AttributeDescription.IsReadOnlyAttribute.FullName); + }); + + var code2 = @" +public class Test2 +{ + public static ref readonly int M(ref readonly int p) => ref Test1.M(p); +}"; + + CompileAndVerify(code2, options: options.WithModuleName("Assembly2"), additionalRefs: new[] { comp1.Compilation.ToMetadataReference() }, symbolValidator: module => + { + AssertGeneratedEmbeddedAttribute(module.ContainingAssembly, AttributeDescription.CodeAnalysisEmbeddedAttribute.FullName); + AssertGeneratedEmbeddedAttribute(module.ContainingAssembly, AttributeDescription.IsReadOnlyAttribute.FullName); + }); + } + + [Fact] + public void IfIsReadOnlyAttributeIsDefinedThenEmbeddedIsNotGenerated() + { + var text = @" +namespace System.Runtime.CompilerServices +{ + public class IsReadOnlyAttribute : System.Attribute { } +} +class Test +{ + public ref readonly int M(ref readonly int x) { return ref x; } +} +"; + + CompileAndVerify(text, verify: false, symbolValidator: module => + { + Assert.Null(module.ContainingAssembly.GetTypeByMetadataName(AttributeDescription.CodeAnalysisEmbeddedAttribute.FullName)); + }); + } + + [Fact] + public void IsReadOnlyAttributeExistsWithWrongConstructorSignature_NetModule() + { + var text = @" +namespace System.Runtime.CompilerServices +{ + public class IsReadOnlyAttribute : System.Attribute + { + public IsReadOnlyAttribute(int p) { } + } +} +class Test +{ + public void M(ref readonly int x) { } +}"; + + CreateStandardCompilation(text, options: TestOptions.ReleaseModule).VerifyDiagnostics( + // (11,19): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.IsReadOnlyAttribute..ctor' + // public void M(ref readonly int x) { } + Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "ref readonly int x").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute", ".ctor").WithLocation(11, 19)); + } + + [Fact] + public void IsReadOnlyAttributeExistsWithWrongConstructorSignature_Assembly() + { + var text = @" +namespace System.Runtime.CompilerServices +{ + public class IsReadOnlyAttribute : System.Attribute + { + public IsReadOnlyAttribute(int p) { } + } +} +class Test +{ + public void M(ref readonly int x) { } +}"; + + CreateStandardCompilation(text).VerifyEmitDiagnostics( + // (11,19): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.IsReadOnlyAttribute..ctor' + // public void M(ref readonly int x) { } + Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "ref readonly int x").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute", ".ctor").WithLocation(11, 19)); + } + + [Fact] + public void IsReadOnlyAttributeExistsWithWrongConstructorSignature_PrivateConstructor() + { + var text = @" +namespace System.Runtime.CompilerServices +{ + public class IsReadOnlyAttribute : System.Attribute + { + private IsReadOnlyAttribute() { } + } +} +class Test +{ + public void M(ref readonly int x) { } +}"; + + CreateStandardCompilation(text).VerifyEmitDiagnostics( + // (11,19): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.IsReadOnlyAttribute..ctor' + // public void M(ref readonly int x) { } + Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "ref readonly int x").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute", ".ctor").WithLocation(11, 19)); + } + + [Fact] + public void IsReadOnlyAttributesAreNotPortedInNoPia() + { + var comAssembly = CreateStandardCompilation(@" +using System; +using System.Runtime.InteropServices; +[assembly: ImportedFromTypeLib(""test.dll"")] +[assembly: Guid(""9784f9a1-594a-4351-8f69-0fd2d2df03d3"")] +[ComImport()] +[Guid(""9784f9a1-594a-4351-8f69-0fd2d2df03d3"")] +public interface Test +{ + ref readonly int Property { get; } + ref readonly int Method(ref readonly int x); +}"); + + CompileAndVerify(comAssembly, symbolValidator: module => + { + var type = module.ContainingAssembly.GetTypeByMetadataName("Test"); + + var property = type.GetMember("Property"); + Assert.NotNull(property); + AssertReferencedIsReadOnlyAttribute(Accessibility.Internal, property.GetAttributes(), module.ContainingAssembly.Name); + + var method = type.GetMethod("Method"); + Assert.NotNull(method); + AssertReferencedIsReadOnlyAttribute(Accessibility.Internal, method.GetReturnTypeAttributes(), module.ContainingAssembly.Name); + + var paramater = method.Parameters.Single(); + Assert.NotNull(paramater); + AssertReferencedIsReadOnlyAttribute(Accessibility.Internal, paramater.GetAttributes(), module.ContainingAssembly.Name); + }); + + var code = @" +class User +{ + public void M(Test p) + { + p.Method(p.Property); + } +}"; + + + var options = TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All); + + var compilation_CompilationReference = CreateStandardCompilation(code, options: options, references: new[] { comAssembly.ToMetadataReference(embedInteropTypes: true) }); + CompileAndVerify(compilation_CompilationReference, symbolValidator: symbolValidator); + + var compilation_BinaryReference = CreateStandardCompilation(code, options: options, references: new[] { comAssembly.EmitToImageReference(embedInteropTypes: true) }); + CompileAndVerify(compilation_BinaryReference, symbolValidator: symbolValidator); + + void symbolValidator(ModuleSymbol module) + { + // No attribute is copied + AssertNoIsReadOnlyAttributeExists(module.ContainingAssembly); + + var type = module.ContainingAssembly.GetTypeByMetadataName("Test"); + + var property = type.GetMember("Property"); + Assert.NotNull(property); + Assert.Empty(property.GetAttributes()); + + var method = type.GetMethod("Method"); + Assert.NotNull(method); + Assert.Empty(method.GetReturnTypeAttributes()); + + var paramater = method.Parameters.Single(); + Assert.NotNull(paramater); + Assert.Empty(paramater.GetAttributes()); + } + } + + [Fact] + public void TryingToBindFromSemanticModelDoesNotPolluteCompilation_Lambdas_Parameters() + { + var reference = CreateStandardCompilation(@" +public delegate int D (ref readonly int x); +").VerifyEmitDiagnostics(); + + Assert.True(reference.NeedsGeneratedIsReadOnlyAttribute); + + var compilation = CreateStandardCompilation(@" +public class Test +{ + public void Process(D lambda) { } + + void User() + { + } +}", references: new[] { reference.ToMetadataReference() }); + + compilation.VerifyEmitDiagnostics(); + Assert.False(compilation.NeedsGeneratedIsReadOnlyAttribute); + + var tree = compilation.SyntaxTrees.Single(); + var model = compilation.GetSemanticModel(tree, ignoreAccessibility: false); + + var userFunction = tree.GetRoot().DescendantNodes().OfType().Single(method => method.Identifier.Text == "User"); + var position = userFunction.Body.CloseBraceToken.Position; + var newInvocation = SyntaxFactory.ParseExpression("Process((ref readonly int x) => x)"); + + var result = model.GetSpeculativeSymbolInfo(position, newInvocation, SpeculativeBindingOption.BindAsExpression); + Assert.NotNull(result.Symbol); + Assert.Equal(CandidateReason.None, result.CandidateReason); + Assert.Empty(result.CandidateSymbols); + + Assert.False(compilation.NeedsGeneratedIsReadOnlyAttribute); + } + + [Fact] + public void TryingToBindFromSemanticModelDoesNotPolluteCompilation_Lambdas_ReturnTypes() + { + var reference = CreateStandardCompilation(@" +public delegate ref readonly int D (); +").VerifyEmitDiagnostics(); + + Assert.True(reference.NeedsGeneratedIsReadOnlyAttribute); + + var compilation = CreateStandardCompilation(@" +public class Test +{ + private int x; + + public void Process(D lambda) + { + x = lambda(); + } + + void User() + { + } +}", references: new[] { reference.ToMetadataReference() }); + + compilation.VerifyEmitDiagnostics(); + Assert.False(compilation.NeedsGeneratedIsReadOnlyAttribute); + + var tree = compilation.SyntaxTrees.Single(); + var model = compilation.GetSemanticModel(tree, ignoreAccessibility: false); + + var userFunction = tree.GetRoot().DescendantNodes().OfType().Single(method => method.Identifier.Text == "User"); + var position = userFunction.Body.CloseBraceToken.Position; + var newInvocation = SyntaxFactory.ParseExpression("Process(() => ref x)"); + + var result = model.GetSpeculativeSymbolInfo(position, newInvocation, SpeculativeBindingOption.BindAsExpression); + Assert.NotNull(result.Symbol); + Assert.Equal(CandidateReason.None, result.CandidateReason); + Assert.Empty(result.CandidateSymbols); + + Assert.False(compilation.NeedsGeneratedIsReadOnlyAttribute); + } + + [Fact] + public void TryingToBindFromSemanticModelDoesNotPolluteCompilation_LocalFunctions_Parameters() + { + var compilation = CreateStandardCompilation(@" +public class Test +{ + void User() + { + } +}"); + + compilation.VerifyEmitDiagnostics(); + Assert.False(compilation.NeedsGeneratedIsReadOnlyAttribute); + + var tree = compilation.SyntaxTrees.Single(); + var model = compilation.GetSemanticModel(tree, ignoreAccessibility: false); + + var userFunction = tree.GetRoot().DescendantNodes().OfType().Single(method => method.Identifier.Text == "User"); + var position = userFunction.Body.CloseBraceToken.Position; + var localfunction = SyntaxFactory.ParseStatement("int localFunction(ref readonly int x) { return x; }"); + + Assert.True(model.TryGetSpeculativeSemanticModel(position, localfunction, out var newModel)); + var localFunctionSymbol = newModel.GetDeclaredSymbol(localfunction); + Assert.NotNull(localFunctionSymbol); + Assert.False(compilation.NeedsGeneratedIsReadOnlyAttribute); + } + + [Fact] + public void TryingToBindFromSemanticModelDoesNotPolluteCompilation_LocalFunctions_ReturnTypes() + { + var compilation = CreateStandardCompilation(@" +public class Test +{ + void User() + { + } +}"); + + compilation.VerifyEmitDiagnostics(); + Assert.False(compilation.NeedsGeneratedIsReadOnlyAttribute); + + var tree = compilation.SyntaxTrees.Single(); + var model = compilation.GetSemanticModel(tree, ignoreAccessibility: false); + + var userFunction = tree.GetRoot().DescendantNodes().OfType().Single(method => method.Identifier.Text == "User"); + var position = userFunction.Body.CloseBraceToken.Position; + var localfunction = SyntaxFactory.ParseStatement("ref readonly int localFunction(int x) { return ref x; }"); + + Assert.True(model.TryGetSpeculativeSemanticModel(position, localfunction, out var newModel)); + var localFunctionSymbol = newModel.GetDeclaredSymbol(localfunction); + Assert.NotNull(localFunctionSymbol); + Assert.False(compilation.NeedsGeneratedIsReadOnlyAttribute); + } + + [Fact] + public void TryingPossibleBindingsForRefReadOnlyDoesNotPolluteCompilationForInvalidOnes() + { + var reference = CreateStandardCompilation(@" +public delegate ref readonly int D1 (); +public delegate ref int D2 (); +").VerifyEmitDiagnostics(); + + Assert.True(reference.NeedsGeneratedIsReadOnlyAttribute); + + var compilation = CreateStandardCompilation(@" +public class Test +{ + public void Process(D1 lambda, int x) { } + public void Process(D2 lambda, byte x) { } + + void User() + { + byte byteVar = 0; + Process(() => { throw null; }, byteVar); + } +}", references: new[] { reference.ToMetadataReference() }); + + compilation.VerifyEmitDiagnostics(); + Assert.False(compilation.NeedsGeneratedIsReadOnlyAttribute); + } + + [Fact] + public void RefReadOnlyErrorsForLambdasDoNotPolluteCompilationDeclarationsDiagnostics() + { + var reference = CreateStandardCompilation(@" +public delegate int D (ref readonly int x); +").EmitToImageReference(); + + var code = @" +public class Test +{ + public void Process(D lambda) { } + + void User() + { + Process((ref readonly int p) => p); + } +}"; + + var compilation = CreateStandardCompilation(code, options: TestOptions.ReleaseModule, references: new[] { reference }); + + compilation.DeclarationDiagnostics.Verify(); + + compilation.VerifyDiagnostics( + // (8,18): error CS0518: Predefined type 'System.Runtime.CompilerServices.IsReadOnlyAttribute' is not defined or imported + // Process((ref readonly int p) => p); + Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "ref readonly int p").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute").WithLocation(8, 18)); + } + + [Fact] + public void RefReadOnlyErrorsForLocalFunctionsDoNotPolluteCompilationDeclarationsDiagnostics() + { + var code = @" +public class Test +{ + private int x = 0; + void User() + { + void local(ref readonly int x) { } + local(x); + } +}"; + + var compilation = CreateStandardCompilation(code, options: TestOptions.ReleaseModule); + + compilation.DeclarationDiagnostics.Verify(); + + compilation.VerifyDiagnostics( + // (7,20): error CS0518: Predefined type 'System.Runtime.CompilerServices.IsReadOnlyAttribute' is not defined or imported + // void local(ref readonly int x) { } + Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "ref readonly int x").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute").WithLocation(7, 20)); + } + + [Fact] + public void RefReadOnlyDefinitionsInsideUserDefinedIsReadOnlyAttribute_Class_NoParent() + { + // PROTOTYPE(readonlyRefs) when the following bug is fixed that test should fail: + // https://github.com/dotnet/roslyn/issues/19395 + + var code = @" +namespace System.Runtime.CompilerServices +{ + public class IsReadOnlyAttribute + { + private int value; + + public ref readonly int Method(ref readonly int x) => ref value; + + public static int operator +(ref readonly IsReadOnlyAttribute x, ref readonly IsReadOnlyAttribute y) => 0; + + public ref readonly int Property => ref value; + + public ref readonly int this[ref readonly int x] => ref value; + } +}"; + + CompileAndVerify(code, verify: false, symbolValidator: module => + { + var isReadOnlyAttributeName = WellKnownTypes.GetMetadataName(WellKnownType.System_Runtime_CompilerServices_IsReadOnlyAttribute); + var type = module.ContainingAssembly.GetTypeByMetadataName(isReadOnlyAttributeName); + + var method = type.GetMethod("Method"); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, method.GetReturnTypeAttributes(), module.ContainingAssembly.Name); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, method.Parameters.Single().GetAttributes(), module.ContainingAssembly.Name); + + var @operator = type.GetMethod("op_Addition"); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, @operator.Parameters[0].GetAttributes(), module.ContainingAssembly.Name); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, @operator.Parameters[1].GetAttributes(), module.ContainingAssembly.Name); + + var property = type.GetProperty("Property"); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, property.GetAttributes(), module.ContainingAssembly.Name); + + var indexer = type.GetProperty("this[]"); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, indexer.GetAttributes(), module.ContainingAssembly.Name); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, indexer.Parameters.Single().GetAttributes(), module.ContainingAssembly.Name); + }); + } + + [Fact] + public void RefReadOnlyDefinitionsInsideUserDefinedIsReadOnlyAttribute_Class_CorrectParent() + { + var code = @" +namespace System.Runtime.CompilerServices +{ + public class IsReadOnlyAttribute : System.Attribute + { + private int value; + + public ref readonly int Method(ref readonly int x) => ref value; + + public static int operator +(ref readonly IsReadOnlyAttribute x, ref readonly IsReadOnlyAttribute y) => 0; + + public ref readonly int Property => ref value; + + public ref readonly int this[ref readonly int x] => ref value; + } +}"; + + CompileAndVerify(code, verify: false, symbolValidator: module => + { + var isReadOnlyAttributeName = WellKnownTypes.GetMetadataName(WellKnownType.System_Runtime_CompilerServices_IsReadOnlyAttribute); + var type = module.ContainingAssembly.GetTypeByMetadataName(isReadOnlyAttributeName); + + var method = type.GetMethod("Method"); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, method.GetReturnTypeAttributes(), module.ContainingAssembly.Name); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, method.Parameters.Single().GetAttributes(), module.ContainingAssembly.Name); + + var @operator = type.GetMethod("op_Addition"); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, @operator.Parameters[0].GetAttributes(), module.ContainingAssembly.Name); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, @operator.Parameters[1].GetAttributes(), module.ContainingAssembly.Name); + + var property = type.GetProperty("Property"); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, property.GetAttributes(), module.ContainingAssembly.Name); + + var indexer = type.GetProperty("this[]"); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, indexer.GetAttributes(), module.ContainingAssembly.Name); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, indexer.Parameters.Single().GetAttributes(), module.ContainingAssembly.Name); + }); + } + + [Fact] + public void RefReadOnlyDefinitionsInsideUserDefinedIsReadOnlyAttribute_ClassInherit() + { + var code = @" +namespace System.Runtime.CompilerServices +{ + public class IsReadOnlyAttribute : System.Attribute + { + } +} +public class Child : System.Runtime.CompilerServices.IsReadOnlyAttribute +{ + private int value; + + public ref readonly int Method(ref readonly int x) => ref value; + + public static int operator +(ref readonly Child x, ref readonly Child y) => 0; + + public ref readonly int Property => ref value; + + public ref readonly int this[ref readonly int x] => ref value; +}"; + + CompileAndVerify(code, verify: false, symbolValidator: module => + { + var type = module.ContainingAssembly.GetTypeByMetadataName("Child"); + + var method = type.GetMethod("Method"); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, method.GetReturnTypeAttributes(), module.ContainingAssembly.Name); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, method.Parameters.Single().GetAttributes(), module.ContainingAssembly.Name); + + var @operator = type.GetMethod("op_Addition"); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, @operator.Parameters[0].GetAttributes(), module.ContainingAssembly.Name); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, @operator.Parameters[1].GetAttributes(), module.ContainingAssembly.Name); + + var property = type.GetProperty("Property"); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, property.GetAttributes(), module.ContainingAssembly.Name); + + var indexer = type.GetProperty("this[]"); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, indexer.GetAttributes(), module.ContainingAssembly.Name); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, indexer.Parameters.Single().GetAttributes(), module.ContainingAssembly.Name); + }); + } + + [Fact] + public void RefReadOnlyDefinitionsInsideUserDefinedIsReadOnlyAttribute_ClassOverride_SameAssembly() + { + var code = @" +namespace System.Runtime.CompilerServices +{ + public abstract class IsReadOnlyAttribute : System.Attribute + { + public IsReadOnlyAttribute() { } + + public abstract ref readonly int Method(ref readonly int x); + + public abstract ref readonly int Property { get; } + + public abstract ref readonly int this[ref readonly int x] { get; } + } +} +public class Child : System.Runtime.CompilerServices.IsReadOnlyAttribute +{ + private int value; + + public override ref readonly int Method(ref readonly int x) => ref value; + + public override ref readonly int Property => ref value; + + public override ref readonly int this[ref readonly int x] => ref value; +}"; + + CompileAndVerify(code, verify: false, symbolValidator: module => + { + var type = module.ContainingAssembly.GetTypeByMetadataName("Child"); + + var method = type.GetMethod("Method"); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, method.GetReturnTypeAttributes(), module.ContainingAssembly.Name); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, method.Parameters.Single().GetAttributes(), module.ContainingAssembly.Name); + + var property = type.GetProperty("Property"); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, property.GetAttributes(), module.ContainingAssembly.Name); + + var indexer = type.GetProperty("this[]"); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, indexer.GetAttributes(), module.ContainingAssembly.Name); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, indexer.Parameters.Single().GetAttributes(), module.ContainingAssembly.Name); + }); + } + + [Fact] + public void RefReadOnlyDefinitionsInsideUserDefinedIsReadOnlyAttribute_ClassOverride_ExternalAssembly() + { + var reference = CreateStandardCompilation(@" +namespace System.Runtime.CompilerServices +{ + public abstract class IsReadOnlyAttribute : System.Attribute + { + public IsReadOnlyAttribute() { } + + public abstract ref readonly int Method(ref readonly int x); + + public abstract ref readonly int Property { get; } + + public abstract ref readonly int this[ref readonly int x] { get; } + } +}", assemblyName: "testRef").ToMetadataReference(); + + var code = @" +public class Child : System.Runtime.CompilerServices.IsReadOnlyAttribute +{ + private int value; + + public override ref readonly int Method(ref readonly int x) => ref value; + + public override ref readonly int Property => ref value; + + public override ref readonly int this[ref readonly int x] => ref value; +}"; + + CompileAndVerify(code, verify: false, additionalRefs: new[] { reference }, symbolValidator: module => + { + var type = module.ContainingAssembly.GetTypeByMetadataName("Child"); + + var method = type.GetMethod("Method"); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, method.GetReturnTypeAttributes(), "testRef"); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, method.Parameters.Single().GetAttributes(), "testRef"); + + var property = type.GetProperty("Property"); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, property.GetAttributes(), "testRef"); + + var indexer = type.GetProperty("this[]"); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, indexer.GetAttributes(), "testRef"); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, indexer.Parameters.Single().GetAttributes(), "testRef"); + }); + } + + [Fact] + public void RefReadOnlyDefinitionsInsideUserDefinedIsReadOnlyAttribute_ClassOverridden_SameAssembly() + { + var code = @" +namespace System.Runtime.CompilerServices +{ + public abstract class Parent : System.Attribute + { + public abstract ref readonly int Method(ref readonly int x); + + public abstract ref readonly int Property { get; } + + public abstract ref readonly int this[ref readonly int x] { get; } + } + public class IsReadOnlyAttribute : Parent + { + private int value; + + public override ref readonly int Method(ref readonly int x) => ref value; + + public override ref readonly int Property => ref value; + + public override ref readonly int this[ref readonly int x] => ref value; + } +}"; + + CompileAndVerify(code, verify: false, symbolValidator: module => + { + var typeName = WellKnownTypes.GetMetadataName(WellKnownType.System_Runtime_CompilerServices_IsReadOnlyAttribute); + var type = module.ContainingAssembly.GetTypeByMetadataName(typeName); + + var method = type.GetMethod("Method"); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, method.GetReturnTypeAttributes(), module.ContainingAssembly.Name); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, method.Parameters.Single().GetAttributes(), module.ContainingAssembly.Name); + + var property = type.GetProperty("Property"); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, property.GetAttributes(), module.ContainingAssembly.Name); + + var indexer = type.GetProperty("this[]"); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, indexer.GetAttributes(), module.ContainingAssembly.Name); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, indexer.Parameters.Single().GetAttributes(), module.ContainingAssembly.Name); + }); + } + + [Fact] + public void RefReadOnlyDefinitionsInsideUserDefinedIsReadOnlyAttribute_ClassOverridden_ExternalAssembly() + { + var reference = CreateStandardCompilation(@" +namespace System.Runtime.CompilerServices +{ + public abstract class Parent : System.Attribute + { + public abstract ref readonly int Method(ref readonly int x); + + public abstract ref readonly int Property { get; } + + public abstract ref readonly int this[ref readonly int x] { get; } + } +}").ToMetadataReference(); + + var code = @" +namespace System.Runtime.CompilerServices +{ + public class IsReadOnlyAttribute : Parent + { + private int value; + + public override ref readonly int Method(ref readonly int x) => ref value; + + public override ref readonly int Property => ref value; + + public override ref readonly int this[ref readonly int x] => ref value; + } +}"; + + CompileAndVerify(code, verify: false, additionalRefs: new[] { reference }, symbolValidator: module => + { + var typeName = WellKnownTypes.GetMetadataName(WellKnownType.System_Runtime_CompilerServices_IsReadOnlyAttribute); + var type = module.ContainingAssembly.GetTypeByMetadataName(typeName); + + var method = type.GetMethod("Method"); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, method.GetReturnTypeAttributes(), module.ContainingAssembly.Name); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, method.Parameters.Single().GetAttributes(), module.ContainingAssembly.Name); + + var property = type.GetProperty("Property"); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, property.GetAttributes(), module.ContainingAssembly.Name); + + var indexer = type.GetProperty("this[]"); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, indexer.GetAttributes(), module.ContainingAssembly.Name); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, indexer.Parameters.Single().GetAttributes(), module.ContainingAssembly.Name); + }); + } + + [Fact] + public void RefReadOnlyDefinitionsInsideUserDefinedIsReadOnlyAttribute_Class_WrongParent() + { + // PROTOTYPE(readonlyRefs) when the following bug is fixed that test should fail: + // https://github.com/dotnet/roslyn/issues/19395 + + var code = @" +namespace System.Runtime.CompilerServices +{ + public class TestParent { } + + public class IsReadOnlyAttribute : TestParent + { + private int value; + + public ref readonly int Method(ref readonly int x) => ref value; + + public static int operator +(ref readonly IsReadOnlyAttribute x, ref readonly IsReadOnlyAttribute y) => 0; + + public ref readonly int Property => ref value; + + public ref readonly int this[ref readonly int x] => ref value; + } +}"; + + CompileAndVerify(code, verify: false, symbolValidator: module => + { + var isReadOnlyAttributeName = WellKnownTypes.GetMetadataName(WellKnownType.System_Runtime_CompilerServices_IsReadOnlyAttribute); + var type = module.ContainingAssembly.GetTypeByMetadataName(isReadOnlyAttributeName); + + var method = type.GetMethod("Method"); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, method.GetReturnTypeAttributes(), module.ContainingAssembly.Name); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, method.Parameters.Single().GetAttributes(), module.ContainingAssembly.Name); + + var @operator = type.GetMethod("op_Addition"); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, @operator.Parameters[0].GetAttributes(), module.ContainingAssembly.Name); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, @operator.Parameters[1].GetAttributes(), module.ContainingAssembly.Name); + + var property = type.GetProperty("Property"); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, property.GetAttributes(), module.ContainingAssembly.Name); + + var indexer = type.GetProperty("this[]"); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, indexer.GetAttributes(), module.ContainingAssembly.Name); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, indexer.Parameters.Single().GetAttributes(), module.ContainingAssembly.Name); + }); + } + + [Fact(Skip = "https://github.com/dotnet/roslyn/issues/19394")] + public void RefReadOnlyDefinitionsInsideUserDefinedIsReadOnlyAttribute_Struct() + { + // PROTOTYPE(readonlyRefs) verify bug is fixed and enable the test + // https://github.com/dotnet/roslyn/issues/19394 + + var code = @" +namespace System.Runtime.CompilerServices +{ + public struct IsReadOnlyAttribute + { + public ref readonly int Method(ref readonly int x) => ref x; + } +}"; + + CreateStandardCompilation(code).VerifyEmitDiagnostics(/* there should be an error */); + Assert.False(true, "It must produce an error about not being able to find the correct signature"); + } + + [Fact] + public void RefReadOnlyDefinitionsInsideUserDefinedIsReadOnlyAttribute_Interface() + { + var code = @" +namespace System.Runtime.CompilerServices +{ + public interface IsReadOnlyAttribute + { + ref readonly int Method(ref readonly int x); + } +}"; + + CreateStandardCompilation(code).VerifyEmitDiagnostics( + // (6,9): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.IsReadOnlyAttribute..ctor' + // ref readonly int Method(ref readonly int x); + Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "ref readonly int").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute", ".ctor").WithLocation(6, 9), + // (6,33): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.IsReadOnlyAttribute..ctor' + // ref readonly int Method(ref readonly int x); + Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "ref readonly int x").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute", ".ctor").WithLocation(6, 33)); + } + + [Fact] + public void RefReadOnlyDefinitionsInsideUserDefinedIsReadOnlyAttribute_ExplicitInterfaceImplementation_SameAssembly() + { + var code = @" +namespace System.Runtime.CompilerServices +{ + public interface ITest + { + ref readonly int Method(ref readonly int x); + + ref readonly int Property { get; } + + ref readonly int this[ref readonly int x] { get; } + } + public class IsReadOnlyAttribute : ITest + { + private int value; + + ref readonly int ITest.Method(ref readonly int x) => ref value; + + ref readonly int ITest.Property => ref value; + + ref readonly int ITest.this[ref readonly int x] => ref value; + } +}"; + + CompileAndVerify(code, verify: false, symbolValidator: module => + { + var typeName = WellKnownTypes.GetMetadataName(WellKnownType.System_Runtime_CompilerServices_IsReadOnlyAttribute); + var type = module.ContainingAssembly.GetTypeByMetadataName(typeName); + + var method = type.GetMethod("System.Runtime.CompilerServices.ITest.Method"); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, method.GetReturnTypeAttributes(), module.ContainingAssembly.Name); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, method.Parameters.Single().GetAttributes(), module.ContainingAssembly.Name); + + var property = type.GetProperty("System.Runtime.CompilerServices.ITest.Property"); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, property.GetAttributes(), module.ContainingAssembly.Name); + + var indexer = type.GetProperty("System.Runtime.CompilerServices.ITest.Item"); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, indexer.GetAttributes(), module.ContainingAssembly.Name); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, indexer.Parameters.Single().GetAttributes(), module.ContainingAssembly.Name); + }); + } + + [Fact] + public void RefReadOnlyDefinitionsInsideUserDefinedIsReadOnlyAttribute_ExplicitInterfaceImplementation_ExternalAssembly() + { + var reference = CreateStandardCompilation(@" +namespace System.Runtime.CompilerServices +{ + public interface ITest + { + ref readonly int Method(ref readonly int x); + + ref readonly int Property { get; } + + ref readonly int this[ref readonly int x] { get; } + } +}").ToMetadataReference(); + + var code = @" +namespace System.Runtime.CompilerServices +{ + public class IsReadOnlyAttribute : ITest + { + private int value; + + ref readonly int ITest.Method(ref readonly int x) => ref value; + + ref readonly int ITest.Property => ref value; + + ref readonly int ITest.this[ref readonly int x] => ref value; + } +}"; + + CompileAndVerify(code, verify: false, additionalRefs: new[] { reference }, symbolValidator: module => + { + var typeName = WellKnownTypes.GetMetadataName(WellKnownType.System_Runtime_CompilerServices_IsReadOnlyAttribute); + var type = module.ContainingAssembly.GetTypeByMetadataName(typeName); + + var method = type.GetMethod("System.Runtime.CompilerServices.ITest.Method"); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, method.GetReturnTypeAttributes(), module.ContainingAssembly.Name); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, method.Parameters.Single().GetAttributes(), module.ContainingAssembly.Name); + + var property = type.GetProperty("System.Runtime.CompilerServices.ITest.Property"); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, property.GetAttributes(), module.ContainingAssembly.Name); + + var indexer = type.GetProperty("System.Runtime.CompilerServices.ITest.Item"); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, indexer.GetAttributes(), module.ContainingAssembly.Name); + AssertReferencedIsReadOnlyAttribute(Accessibility.Public, indexer.Parameters.Single().GetAttributes(), module.ContainingAssembly.Name); + }); + } + + [Fact] + public void IsReadOnlyAttributeIsGenerated_ExplicitInterfaceImplementation_SameAssembly() + { + var code = @" +public interface ITest +{ + ref readonly int Method(ref readonly int x); + + ref readonly int Property { get; } + + ref readonly int this[ref readonly int x] { get; } +} +public class TestImpl : ITest +{ + private int value; + + ref readonly int ITest.Method(ref readonly int x) => ref value; + + ref readonly int ITest.Property => ref value; + + ref readonly int ITest.this[ref readonly int x] => ref value; +}"; + + CompileAndVerify(code, verify: false, symbolValidator: module => + { + var type = module.ContainingAssembly.GetTypeByMetadataName("TestImpl"); + + var method = type.GetMethod("ITest.Method"); + AssertReferencedIsReadOnlyAttribute(Accessibility.Internal, method.GetReturnTypeAttributes(), module.ContainingAssembly.Name); + AssertReferencedIsReadOnlyAttribute(Accessibility.Internal, method.Parameters.Single().GetAttributes(), module.ContainingAssembly.Name); + + var property = type.GetProperty("ITest.Property"); + AssertReferencedIsReadOnlyAttribute(Accessibility.Internal, property.GetAttributes(), module.ContainingAssembly.Name); + + var indexer = type.GetProperty("ITest.Item"); + AssertReferencedIsReadOnlyAttribute(Accessibility.Internal, indexer.GetAttributes(), module.ContainingAssembly.Name); + AssertReferencedIsReadOnlyAttribute(Accessibility.Internal, indexer.Parameters.Single().GetAttributes(), module.ContainingAssembly.Name); + }); + } + + [Fact] + public void IsReadOnlyAttributeIsGenerated_ExplicitInterfaceImplementation_ExternalAssembly() + { + var reference = CreateStandardCompilation(@" +public interface ITest +{ + ref readonly int Method(ref readonly int x); + + ref readonly int Property { get; } + + ref readonly int this[ref readonly int x] { get; } +}").ToMetadataReference(); + + var code = @" +public class TestImpl : ITest +{ + private int value; + + ref readonly int ITest.Method(ref readonly int x) => ref value; + + ref readonly int ITest.Property => ref value; + + ref readonly int ITest.this[ref readonly int x] => ref value; +}"; + + CompileAndVerify(code, verify: false, additionalRefs: new[] { reference }, symbolValidator: module => + { + var type = module.ContainingAssembly.GetTypeByMetadataName("TestImpl"); + + var method = type.GetMethod("ITest.Method"); + AssertReferencedIsReadOnlyAttribute(Accessibility.Internal, method.GetReturnTypeAttributes(), module.ContainingAssembly.Name); + AssertReferencedIsReadOnlyAttribute(Accessibility.Internal, method.Parameters.Single().GetAttributes(), module.ContainingAssembly.Name); + + var property = type.GetProperty("ITest.Property"); + AssertReferencedIsReadOnlyAttribute(Accessibility.Internal, property.GetAttributes(), module.ContainingAssembly.Name); + + var indexer = type.GetProperty("ITest.Item"); + AssertReferencedIsReadOnlyAttribute(Accessibility.Internal, indexer.GetAttributes(), module.ContainingAssembly.Name); + AssertReferencedIsReadOnlyAttribute(Accessibility.Internal, indexer.Parameters.Single().GetAttributes(), module.ContainingAssembly.Name); + }); + } + + [Fact] + public void RefReadOnlyDefinitionsInsideUserDefinedIsReadOnlyAttribute_Delegate() + { + var code = @" +namespace System.Runtime.CompilerServices +{ + public delegate ref readonly int IsReadOnlyAttribute(ref readonly int x); +}"; + + CreateStandardCompilation(code).VerifyEmitDiagnostics( + // (4,21): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.IsReadOnlyAttribute..ctor' + // public delegate ref readonly int IsReadOnlyAttribute(ref readonly int x); + Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "ref readonly int").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute", ".ctor").WithLocation(4, 21), + // (4,58): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.IsReadOnlyAttribute..ctor' + // public delegate ref readonly int IsReadOnlyAttribute(ref readonly int x); + Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "ref readonly int x").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute", ".ctor").WithLocation(4, 58)); + } + + [Fact] + public void MissingRequiredConstructorWillReportErrorsOnApproriateSyntax_Constructor() + { + var text = @" +namespace System.Runtime.CompilerServices +{ + public class IsReadOnlyAttribute : System.Attribute + { + public IsReadOnlyAttribute(int p) { } + } +} +public class Test +{ + public Test(ref readonly int x) { } +}"; + + CreateStandardCompilation(text).VerifyEmitDiagnostics( + // (11,17): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.IsReadOnlyAttribute..ctor' + // public Test(ref readonly int x) { } + Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "ref readonly int x").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute", ".ctor").WithLocation(11, 17)); + } + + [Fact] + public void MissingRequiredConstructorWillReportErrorsOnApproriateSyntax_Method() + { + var text = @" +namespace System.Runtime.CompilerServices +{ + public class IsReadOnlyAttribute : System.Attribute + { + public IsReadOnlyAttribute(int p) { } + } +} +public class Test +{ + public ref readonly int Method(ref readonly int x) => ref x; +}"; + + CreateStandardCompilation(text).VerifyEmitDiagnostics( + // (11,12): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.IsReadOnlyAttribute..ctor' + // public ref readonly int Method(ref readonly int x) => ref x; + Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "ref readonly int").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute", ".ctor").WithLocation(11, 12), + // (11,36): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.IsReadOnlyAttribute..ctor' + // public ref readonly int Method(ref readonly int x) => ref x; + Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "ref readonly int x").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute", ".ctor").WithLocation(11, 36)); + } + + [Fact] + public void MissingRequiredConstructorWillReportErrorsOnApproriateSyntax_LocalFunction() + { + var text = @" +namespace System.Runtime.CompilerServices +{ + public class IsReadOnlyAttribute : System.Attribute + { + public IsReadOnlyAttribute(int p) { } + } +} +public class Test +{ + public void M() + { + int x = 0; + + ref readonly int local(ref readonly int p) + { + return ref p; + } + + local(x); + } +}"; + + CreateStandardCompilation(text).VerifyEmitDiagnostics( + // (15,9): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.IsReadOnlyAttribute..ctor' + // ref readonly int local(ref readonly int p) + Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "ref readonly int").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute", ".ctor").WithLocation(15, 9), + // (15,32): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.IsReadOnlyAttribute..ctor' + // ref readonly int local(ref readonly int p) + Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "ref readonly int p").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute", ".ctor").WithLocation(15, 32)); + } + + [Fact] + public void MissingRequiredConstructorWillReportErrorsOnApproriateSyntax_Lambda() + { + var reference = CreateStandardCompilation(@" +public delegate ref readonly int D(ref readonly int x); +").EmitToImageReference(); + + var text = @" +namespace System.Runtime.CompilerServices +{ + public class IsReadOnlyAttribute : System.Attribute + { + public IsReadOnlyAttribute(int p) { } + } +} + +class Test +{ + public void M1() + { + M2((ref readonly int x) => ref x); + } + + public void M2(D value) { } +}"; + + CreateStandardCompilation(text, references: new[] { reference }).VerifyEmitDiagnostics( + // (14,33): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.IsReadOnlyAttribute..ctor' + // M2((ref readonly int x) => ref x); + Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "=>").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute", ".ctor").WithLocation(14, 33), + // (14,13): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.IsReadOnlyAttribute..ctor' + // M2((ref readonly int x) => ref x); + Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "ref readonly int x").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute", ".ctor").WithLocation(14, 13)); + } + + [Fact] + public void MissingRequiredConstructorWillReportErrorsOnApproriateSyntax_Property() + { + var text = @" +namespace System.Runtime.CompilerServices +{ + public class IsReadOnlyAttribute : System.Attribute + { + public IsReadOnlyAttribute(int p) { } + } +} +public class Test +{ + private int value; + public ref readonly int Property => ref value; +}"; + + CreateStandardCompilation(text).VerifyEmitDiagnostics( + // (12,12): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.IsReadOnlyAttribute..ctor' + // public ref readonly int Property => ref value; + Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "ref readonly int").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute", ".ctor").WithLocation(12, 12)); + } + + [Fact] + public void MissingRequiredConstructorWillReportErrorsOnApproriateSyntax_Indexer() + { + var text = @" +namespace System.Runtime.CompilerServices +{ + public class IsReadOnlyAttribute : System.Attribute + { + public IsReadOnlyAttribute(int p) { } + } +} +public class Test +{ + + public ref readonly int this[ref readonly int x] => ref x; +}"; + + CreateStandardCompilation(text).VerifyEmitDiagnostics( + // (12,12): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.IsReadOnlyAttribute..ctor' + // public ref readonly int this[ref readonly int x] => ref x; + Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "ref readonly int").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute", ".ctor").WithLocation(12, 12), + // (12,34): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.IsReadOnlyAttribute..ctor' + // public ref readonly int this[ref readonly int x] => ref x; + Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "ref readonly int x").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute", ".ctor").WithLocation(12, 34)); + } + + [Fact] + public void MissingRequiredConstructorWillReportErrorsOnApproriateSyntax_Operator() + { + var text = @" +namespace System.Runtime.CompilerServices +{ + public class IsReadOnlyAttribute : System.Attribute + { + public IsReadOnlyAttribute(int p) { } + } +} +public class Test +{ + public static int operator + (ref readonly Test x, ref readonly Test y) => 0; +}"; + + CreateStandardCompilation(text).VerifyEmitDiagnostics( + // (11,35): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.IsReadOnlyAttribute..ctor' + // public static int operator + (ref readonly Test x, ref readonly Test y) => 0; + Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "ref readonly Test x").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute", ".ctor").WithLocation(11, 35), + // (11,56): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.IsReadOnlyAttribute..ctor' + // public static int operator + (ref readonly Test x, ref readonly Test y) => 0; + Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "ref readonly Test y").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute", ".ctor").WithLocation(11, 56)); + } + + private void AssertReferencedIsReadOnlyAttribute(Accessibility accessibility, ImmutableArray attributes, string assemblyName) + { + var attributeType = attributes.Single().AttributeClass; + Assert.Equal("IsReadOnlyAttribute", attributeType.Name); + Assert.Equal(assemblyName, attributeType.ContainingAssembly.Name); + Assert.Equal(accessibility, attributeType.DeclaredAccessibility); + } + + private void AssertNoIsReadOnlyAttributeExists(AssemblySymbol assembly) + { + var isReadOnlyAttributeTypeName = WellKnownTypes.GetMetadataName(WellKnownType.System_Runtime_CompilerServices_IsReadOnlyAttribute); + Assert.Null(assembly.GetTypeByMetadataName(isReadOnlyAttributeTypeName)); + } + + private void AssertGeneratedEmbeddedAttribute(AssemblySymbol assembly, string expectedTypeName) + { + var typeSymbol = assembly.GetTypeByMetadataName(expectedTypeName); + Assert.NotNull(typeSymbol); + Assert.Equal(Accessibility.Internal, typeSymbol.DeclaredAccessibility); + + var attributes = typeSymbol.GetAttributes().OrderBy(attribute => attribute.AttributeClass.Name).ToArray(); + Assert.Equal(2, attributes.Length); + + Assert.Equal(WellKnownTypes.GetMetadataName(WellKnownType.System_Runtime_CompilerServices_CompilerGeneratedAttribute), attributes[0].AttributeClass.ToDisplayString()); + Assert.Equal(AttributeDescription.CodeAnalysisEmbeddedAttribute.FullName, attributes[1].AttributeClass.ToDisplayString()); } } } diff --git a/src/Compilers/CSharp/Test/Emit/CSharpCompilerEmitTest.csproj b/src/Compilers/CSharp/Test/Emit/CSharpCompilerEmitTest.csproj index bb2cc61607927..45029fccc45b9 100644 --- a/src/Compilers/CSharp/Test/Emit/CSharpCompilerEmitTest.csproj +++ b/src/Compilers/CSharp/Test/Emit/CSharpCompilerEmitTest.csproj @@ -66,6 +66,7 @@ + diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncMainTests.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncMainTests.cs index 34bd9f103093a..64bb0c7e5c38a 100644 --- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncMainTests.cs +++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncMainTests.cs @@ -346,6 +346,7 @@ public void EmitTaskOfIntReturningMainWithoutInt() var corAssembly = @" namespace System { public class Object {} + public class Void {} public abstract class ValueType{} public struct Int32{} }"; diff --git a/src/Compilers/CSharp/Test/Emit/Emit/OptionalArgumentsTests.cs b/src/Compilers/CSharp/Test/Emit/Emit/OptionalArgumentsTests.cs index bc29dc1c7dc23..38b404047575f 100644 --- a/src/Compilers/CSharp/Test/Emit/Emit/OptionalArgumentsTests.cs +++ b/src/Compilers/CSharp/Test/Emit/Emit/OptionalArgumentsTests.cs @@ -210,7 +210,7 @@ static partial void F([DecimalConstant(0, 0, 0, 0, 2)]decimal o) { } private static void VerifyDefaultValueAttribute(ParameterSymbol parameter, string expectedAttributeName, object expectedDefault, bool hasDefault) { - var attributes = parameter.GetCustomAttributesToEmit(new ModuleCompilationState()).ToArray(); + var attributes = parameter.GetCustomAttributesToEmit(GetDefaultPEBuilder(parameter.DeclaringCompilation)).ToArray(); if (expectedAttributeName == null) { Assert.Equal(attributes.Length, 0); @@ -440,7 +440,7 @@ class C ); var c = comp.GetTypeByMetadataName("C"); - Assert.Equal(1, c.GetMember("F15").GetCustomAttributesToEmit(new ModuleCompilationState()).Count()); + Assert.Equal(1, c.GetMember("F15").GetCustomAttributesToEmit(GetDefaultPEBuilder(comp)).Count()); } } } diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/CorLibrary/CorTypes.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/CorLibrary/CorTypes.cs index 3436f415b8aa2..8e2c6bea3af74 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/CorLibrary/CorTypes.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/CorLibrary/CorTypes.cs @@ -177,6 +177,10 @@ public class Object { } + public class Void + { + } + public class Array : Object { } diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/GenericConstraintTests.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/GenericConstraintTests.cs index 4390aa56d72c7..93aee2e6f7bed 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/GenericConstraintTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/GenericConstraintTests.cs @@ -5593,15 +5593,23 @@ internal override void M() { } }"; CreateCompilation(source).VerifyDiagnostics( // (2,16): error CS0518: Predefined type 'System.Object' is not defined or imported + // abstract class A Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "A").WithArguments("System.Object").WithLocation(2, 16), // (1,8): error CS0518: Predefined type 'System.ValueType' is not defined or imported + // struct S { } Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "S").WithArguments("System.ValueType").WithLocation(1, 8), // (4,23): error CS0518: Predefined type 'System.Void' is not defined or imported + // internal abstract void M() where U : struct, T; Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "void").WithArguments("System.Void").WithLocation(4, 23), // (8,23): error CS0518: Predefined type 'System.Void' is not defined or imported + // internal override void M() { } Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "void").WithArguments("System.Void").WithLocation(8, 23), // (2,16): error CS1729: 'object' does not contain a constructor that takes 0 arguments - Diagnostic(ErrorCode.ERR_BadCtorArgCount, "A").WithArguments("object", "0").WithLocation(2, 16)); + // abstract class A + Diagnostic(ErrorCode.ERR_BadCtorArgCount, "A").WithArguments("object", "0").WithLocation(2, 16), + // (6,7): error CS0518: Predefined type 'System.Void' is not defined or imported + // class B : A + Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "B").WithArguments("System.Void").WithLocation(6, 7)); } [WorkItem(11243, "DevDiv_Projects/Roslyn")] diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/IndexerTests.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/IndexerTests.cs index eeb5a1d33c593..3fd4bb93872ab 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/IndexerTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/IndexerTests.cs @@ -2113,7 +2113,7 @@ int this[int x] Assert.True(attribute.IsTargetAttribute(indexer, AttributeDescription.IndexerNameAttribute)); // Not emitted. - Assert.Equal(0, indexer.GetCustomAttributesToEmit(new ModuleCompilationState()).Count()); + Assert.Equal(0, indexer.GetCustomAttributesToEmit(GetDefaultPEBuilder(compilation)).Count()); } [WorkItem(545884, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545884")] diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/Metadata/PE/LoadingAttributes.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/Metadata/PE/LoadingAttributes.cs index 0d3b06e63dfd4..473bbc2802aa9 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/Metadata/PE/LoadingAttributes.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/Metadata/PE/LoadingAttributes.cs @@ -1403,13 +1403,13 @@ public void M1(decimal d1 = -7) var d1 = class1.GetMember("d1"); var m1 = class1.GetMember("M1"); - var state = new ModuleCompilationState(); + var builder = GetDefaultPEBuilder(c1); Assert.Empty(d1.GetAttributes()); - Assert.Equal("System.Runtime.CompilerServices.DecimalConstantAttribute(0, 128, 0, 0, 7)", d1.GetCustomAttributesToEmit(state).Single().ToString()); + Assert.Equal("System.Runtime.CompilerServices.DecimalConstantAttribute(0, 128, 0, 0, 7)", d1.GetCustomAttributesToEmit(builder).Single().ToString()); Assert.Equal(d1.ConstantValue, -7m); Assert.Empty(m1.Parameters[0].GetAttributes()); - Assert.Equal("System.Runtime.CompilerServices.DecimalConstantAttribute(0, 128, 0, 0, 7)", m1.Parameters[0].GetCustomAttributesToEmit(state).Single().ToString()); + Assert.Equal("System.Runtime.CompilerServices.DecimalConstantAttribute(0, 128, 0, 0, 7)", m1.Parameters[0].GetCustomAttributesToEmit(builder).Single().ToString()); Assert.Equal(m1.Parameters[0].ExplicitDefaultValue, -7m); var c2 = CreateCompilationWithCustomILSource("", ilSource); @@ -1420,16 +1420,16 @@ public void M1(decimal d1 = -7) m1 = class1.GetMember("M1"); Assert.Empty(d1.GetAttributes()); - Assert.Equal("System.Runtime.CompilerServices.DecimalConstantAttribute(0, 128, 0, 0, 7)", d1.GetCustomAttributesToEmit(state).Single().ToString()); + Assert.Equal("System.Runtime.CompilerServices.DecimalConstantAttribute(0, 128, 0, 0, 7)", d1.GetCustomAttributesToEmit(builder).Single().ToString()); Assert.Equal(d1.ConstantValue, -7m); Assert.Equal(2, d2.GetAttributes().Length); - Assert.Equal(2, d2.GetCustomAttributesToEmit(state).Count()); + Assert.Equal(2, d2.GetCustomAttributesToEmit(builder).Count()); Assert.Null(d2.ConstantValue); Assert.Empty(m1.Parameters[0].GetAttributes()); - Assert.Equal("System.Runtime.CompilerServices.DecimalConstantAttribute(0, 128, 0, 0, 7)", m1.Parameters[0].GetCustomAttributesToEmit(state).Single().ToString()); + Assert.Equal("System.Runtime.CompilerServices.DecimalConstantAttribute(0, 128, 0, 0, 7)", m1.Parameters[0].GetCustomAttributesToEmit(builder).Single().ToString()); Assert.Equal(m1.Parameters[0].ExplicitDefaultValue, -7m); Assert.Empty(m1.Parameters[1].GetAttributes()); - Assert.Equal("System.Runtime.CompilerServices.DateTimeConstantAttribute(634925952000000000)", m1.Parameters[1].GetCustomAttributesToEmit(state).Single().ToString()); + Assert.Equal("System.Runtime.CompilerServices.DateTimeConstantAttribute(634925952000000000)", m1.Parameters[1].GetCustomAttributesToEmit(builder).Single().ToString()); Assert.Equal(m1.Parameters[1].ExplicitDefaultValue, new DateTime(2013, 1, 1)); var c3 = CreateCompilationWithCustomILSource("", ilSource); @@ -1441,16 +1441,16 @@ public void M1(decimal d1 = -7) Assert.Equal(d1.ConstantValue, -7m); Assert.Empty(d1.GetAttributes()); - Assert.Equal("System.Runtime.CompilerServices.DecimalConstantAttribute(0, 128, 0, 0, 7)", d1.GetCustomAttributesToEmit(state).Single().ToString()); + Assert.Equal("System.Runtime.CompilerServices.DecimalConstantAttribute(0, 128, 0, 0, 7)", d1.GetCustomAttributesToEmit(builder).Single().ToString()); Assert.Null(d2.ConstantValue); Assert.Equal(2, d2.GetAttributes().Length); - Assert.Equal(2, d2.GetCustomAttributesToEmit(state).Count()); + Assert.Equal(2, d2.GetCustomAttributesToEmit(builder).Count()); Assert.Equal(m1.Parameters[0].ExplicitDefaultValue, -7m); Assert.Empty(m1.Parameters[0].GetAttributes()); - Assert.Equal("System.Runtime.CompilerServices.DecimalConstantAttribute(0, 128, 0, 0, 7)", m1.Parameters[0].GetCustomAttributesToEmit(state).Single().ToString()); + Assert.Equal("System.Runtime.CompilerServices.DecimalConstantAttribute(0, 128, 0, 0, 7)", m1.Parameters[0].GetCustomAttributesToEmit(builder).Single().ToString()); Assert.Equal(m1.Parameters[1].ExplicitDefaultValue, new DateTime(2013, 1, 1)); Assert.Empty(m1.Parameters[1].GetAttributes()); - Assert.Equal("System.Runtime.CompilerServices.DateTimeConstantAttribute(634925952000000000)", m1.Parameters[1].GetCustomAttributesToEmit(state).Single().ToString()); + Assert.Equal("System.Runtime.CompilerServices.DateTimeConstantAttribute(634925952000000000)", m1.Parameters[1].GetCustomAttributesToEmit(builder).Single().ToString()); } [ClrOnlyFact(ClrOnlyReason.Ilasm)] diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/MissingSpecialMember.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/MissingSpecialMember.cs index 9cb718067cb00..d0f9b9f7309ba 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/MissingSpecialMember.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/MissingSpecialMember.cs @@ -558,7 +558,7 @@ public void AllWellKnownTypes() continue; case WellKnownType.System_FormattableString: case WellKnownType.System_Runtime_CompilerServices_FormattableStringFactory: - case WellKnownType.System_Runtime_CompilerServices_ReadOnlyAttribute: + case WellKnownType.System_Runtime_CompilerServices_IsReadOnlyAttribute: case WellKnownType.System_Runtime_CompilerServices_IsByRefLikeAttribute: // Not yet in the platform. case WellKnownType.Microsoft_CodeAnalysis_Runtime_Instrumentation: @@ -861,7 +861,7 @@ public void AllWellKnownTypeMembers() // Not yet in the platform. continue; case WellKnownMember.Microsoft_CodeAnalysis_Runtime_Instrumentation__CreatePayload: - case WellKnownMember.System_Runtime_CompilerServices_ReadOnlyAttribute__ctor: + case WellKnownMember.System_Runtime_CompilerServices_IsReadOnlyAttribute__ctor: case WellKnownMember.System_Runtime_CompilerServices_IsByRefLikeAttribute__ctor: // Not always available. continue; diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/MockNamedTypeSymbol.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/MockNamedTypeSymbol.cs index 33f1d0da2dc90..578be2e4c8e70 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/MockNamedTypeSymbol.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/MockNamedTypeSymbol.cs @@ -243,6 +243,8 @@ internal override ImmutableArray GetDeclaredInterfaces(ConsList throw new NotImplementedException(); } + internal override bool HasCodeAnalysisEmbeddedAttribute => false; + internal sealed override bool IsManagedType { get diff --git a/src/Compilers/Core/Portable/Emit/NoPia/CommonEmbeddedMember.cs b/src/Compilers/Core/Portable/Emit/NoPia/CommonEmbeddedMember.cs index 75fe92532454c..ae83ce969609f 100644 --- a/src/Compilers/Core/Portable/Emit/NoPia/CommonEmbeddedMember.cs +++ b/src/Compilers/Core/Portable/Emit/NoPia/CommonEmbeddedMember.cs @@ -45,14 +45,14 @@ protected CommonEmbeddedMember(TMember underlyingSymbol) this.UnderlyingSymbol = underlyingSymbol; } - protected abstract IEnumerable GetCustomAttributesToEmit(TModuleCompilationState compilationState); + protected abstract IEnumerable GetCustomAttributesToEmit(TPEModuleBuilder moduleBuilder); protected virtual TAttributeData PortAttributeIfNeedTo(TAttributeData attrData, TSyntaxNode syntaxNodeOpt, DiagnosticBag diagnostics) { return null; } - private ImmutableArray GetAttributes(TModuleCompilationState compilationState, TSyntaxNode syntaxNodeOpt, DiagnosticBag diagnostics) + private ImmutableArray GetAttributes(TPEModuleBuilder moduleBuilder, TSyntaxNode syntaxNodeOpt, DiagnosticBag diagnostics) { var builder = ArrayBuilder.GetInstance(); @@ -62,7 +62,7 @@ private ImmutableArray GetAttributes(TModuleCompilationState com // The constructors might be missing (for example, in metadata case) and doing lookup // will ensure that we report appropriate errors. - foreach (var attrData in GetCustomAttributesToEmit(compilationState)) + foreach (var attrData in GetCustomAttributesToEmit(moduleBuilder)) { if (TypeManager.IsTargetAttribute(UnderlyingSymbol, attrData, AttributeDescription.DispIdAttribute)) { @@ -85,7 +85,7 @@ private ImmutableArray GetAttributes(TModuleCompilationState com if (_lazyAttributes.IsDefault) { var diagnostics = DiagnosticBag.GetInstance(); - var attributes = GetAttributes((TModuleCompilationState)context.Module.CommonModuleCompilationState, (TSyntaxNode)context.SyntaxNodeOpt, diagnostics); + var attributes = GetAttributes((TPEModuleBuilder)context.Module, (TSyntaxNode)context.SyntaxNodeOpt, diagnostics); if (ImmutableInterlocked.InterlockedInitialize(ref _lazyAttributes, attributes)) { diff --git a/src/Compilers/Core/Portable/Emit/NoPia/CommonEmbeddedMethod.cs b/src/Compilers/Core/Portable/Emit/NoPia/CommonEmbeddedMethod.cs index 44feee06c3041..51c3b864283ec 100644 --- a/src/Compilers/Core/Portable/Emit/NoPia/CommonEmbeddedMethod.cs +++ b/src/Compilers/Core/Portable/Emit/NoPia/CommonEmbeddedMethod.cs @@ -204,13 +204,10 @@ System.Reflection.MethodImplAttributes Cci.IMethodDefinition.GetImplementationAt bool Cci.IMethodDefinition.RequiresSecurityObject => false; - IEnumerable Cci.IMethodDefinition.ReturnValueAttributes + IEnumerable Cci.IMethodDefinition.GetReturnValueAttributes(EmitContext context) { - get - { - // TODO: - return SpecializedCollections.EmptyEnumerable(); - } + // TODO: + return SpecializedCollections.EmptyEnumerable(); } bool Cci.IMethodDefinition.ReturnValueIsMarshalledExplicitly => ReturnValueIsMarshalledExplicitly; diff --git a/src/Compilers/Core/Portable/Emit/NoPia/CommonEmbeddedParameter.cs b/src/Compilers/Core/Portable/Emit/NoPia/CommonEmbeddedParameter.cs index fb11ff3cf46e9..07cb21098a61d 100644 --- a/src/Compilers/Core/Portable/Emit/NoPia/CommonEmbeddedParameter.cs +++ b/src/Compilers/Core/Portable/Emit/NoPia/CommonEmbeddedParameter.cs @@ -62,14 +62,14 @@ protected TEmbeddedTypesManager TypeManager protected abstract string Name { get; } protected abstract Cci.IParameterTypeInformation UnderlyingParameterTypeInformation { get; } protected abstract ushort Index { get; } - protected abstract IEnumerable GetCustomAttributesToEmit(TModuleCompilationState compilationState); + protected abstract IEnumerable GetCustomAttributesToEmit(TPEModuleBuilder moduleBuilder); private bool IsTargetAttribute(TAttributeData attrData, AttributeDescription description) { return TypeManager.IsTargetAttribute(UnderlyingParameter, attrData, description); } - private ImmutableArray GetAttributes(TModuleCompilationState compilationState, TSyntaxNode syntaxNodeOpt, DiagnosticBag diagnostics) + private ImmutableArray GetAttributes(TPEModuleBuilder moduleBuilder, TSyntaxNode syntaxNodeOpt, DiagnosticBag diagnostics) { var builder = ArrayBuilder.GetInstance(); @@ -79,7 +79,7 @@ private ImmutableArray GetAttributes(TModuleCompilationState com // The constructors might be missing (for example, in metadata case) and doing lookup // will ensure that we report appropriate errors. - foreach (var attrData in GetCustomAttributesToEmit(compilationState)) + foreach (var attrData in GetCustomAttributesToEmit(moduleBuilder)) { if (IsTargetAttribute(attrData, AttributeDescription.ParamArrayAttribute)) { @@ -189,7 +189,7 @@ ImmutableArray Cci.IParameterDefinition.MarshallingDescriptor if (_lazyAttributes.IsDefault) { var diagnostics = DiagnosticBag.GetInstance(); - var attributes = GetAttributes((TModuleCompilationState)context.Module.CommonModuleCompilationState, (TSyntaxNode)context.SyntaxNodeOpt, diagnostics); + var attributes = GetAttributes((TPEModuleBuilder)context.Module, (TSyntaxNode)context.SyntaxNodeOpt, diagnostics); if (ImmutableInterlocked.InterlockedInitialize(ref _lazyAttributes, attributes)) { diff --git a/src/Compilers/Core/Portable/Emit/NoPia/CommonEmbeddedType.cs b/src/Compilers/Core/Portable/Emit/NoPia/CommonEmbeddedType.cs index 704346c9a7d64..8ef75c6b9da2e 100644 --- a/src/Compilers/Core/Portable/Emit/NoPia/CommonEmbeddedType.cs +++ b/src/Compilers/Core/Portable/Emit/NoPia/CommonEmbeddedType.cs @@ -70,7 +70,7 @@ protected CommonEmbeddedType(TEmbeddedTypesManager typeManager, TNamedTypeSymbol protected abstract System.Runtime.InteropServices.CharSet StringFormat { get; } protected abstract TAttributeData CreateTypeIdentifierAttribute(bool hasGuid, TSyntaxNode syntaxNodeOpt, DiagnosticBag diagnostics); protected abstract void EmbedDefaultMembers(string defaultMember, TSyntaxNode syntaxNodeOpt, DiagnosticBag diagnostics); - protected abstract IEnumerable GetCustomAttributesToEmit(TModuleCompilationState compilationState); + protected abstract IEnumerable GetCustomAttributesToEmit(TPEModuleBuilder moduleBuilder); protected abstract void ReportMissingAttribute(AttributeDescription description, TSyntaxNode syntaxNodeOpt, DiagnosticBag diagnostics); private bool IsTargetAttribute(TAttributeData attrData, AttributeDescription description) @@ -78,7 +78,7 @@ private bool IsTargetAttribute(TAttributeData attrData, AttributeDescription des return TypeManager.IsTargetAttribute(UnderlyingNamedType, attrData, description); } - private ImmutableArray GetAttributes(TModuleCompilationState compilationState, TSyntaxNode syntaxNodeOpt, DiagnosticBag diagnostics) + private ImmutableArray GetAttributes(TPEModuleBuilder moduleBuilder, TSyntaxNode syntaxNodeOpt, DiagnosticBag diagnostics) { var builder = ArrayBuilder.GetInstance(); @@ -95,7 +95,7 @@ private ImmutableArray GetAttributes(TModuleCompilationState com // The constructors might be missing (for example, in metadata case) and doing lookup // will ensure that we report appropriate errors. - foreach (var attrData in GetCustomAttributesToEmit(compilationState)) + foreach (var attrData in GetCustomAttributesToEmit(moduleBuilder)) { if (IsTargetAttribute(attrData, AttributeDescription.GuidAttribute)) { @@ -518,7 +518,7 @@ System.Runtime.InteropServices.CharSet Cci.ITypeDefinition.StringFormat if (_lazyAttributes.IsDefault) { var diagnostics = DiagnosticBag.GetInstance(); - var attributes = GetAttributes((TModuleCompilationState)context.Module.CommonModuleCompilationState, (TSyntaxNode)context.SyntaxNodeOpt, diagnostics); + var attributes = GetAttributes((TPEModuleBuilder)context.Module, (TSyntaxNode)context.SyntaxNodeOpt, diagnostics); if (ImmutableInterlocked.InterlockedInitialize(ref _lazyAttributes, attributes)) { diff --git a/src/Compilers/Core/Portable/Emit/NoPia/VtblGap.cs b/src/Compilers/Core/Portable/Emit/NoPia/VtblGap.cs index 19c38d304e529..2d5cb6bfb3862 100644 --- a/src/Compilers/Core/Portable/Emit/NoPia/VtblGap.cs +++ b/src/Compilers/Core/Portable/Emit/NoPia/VtblGap.cs @@ -117,9 +117,9 @@ bool Cci.IMethodDefinition.RequiresSecurityObject get { return false; } } - IEnumerable Cci.IMethodDefinition.ReturnValueAttributes + IEnumerable Cci.IMethodDefinition.GetReturnValueAttributes(EmitContext context) { - get { return SpecializedCollections.EmptyEnumerable(); } + return SpecializedCollections.EmptyEnumerable(); } bool Cci.IMethodDefinition.ReturnValueIsMarshalledExplicitly diff --git a/src/Compilers/Core/Portable/MetadataReader/PEModule.cs b/src/Compilers/Core/Portable/MetadataReader/PEModule.cs index ebae2f1473e0a..468311220b14c 100644 --- a/src/Compilers/Core/Portable/MetadataReader/PEModule.cs +++ b/src/Compilers/Core/Portable/MetadataReader/PEModule.cs @@ -938,9 +938,9 @@ internal bool HasParamsAttribute(EntityHandle token) return FindTargetAttribute(token, AttributeDescription.ParamArrayAttribute).HasValue; } - internal bool HasReadOnlyAttribute(EntityHandle token) + internal bool HasIsReadOnlyAttribute(EntityHandle token) { - return FindTargetAttribute(token, AttributeDescription.ReadOnlyAttribute).HasValue; + return FindTargetAttribute(token, AttributeDescription.IsReadOnlyAttribute).HasValue; } internal bool HasExtensionAttribute(EntityHandle token, bool ignoreCase) @@ -953,6 +953,11 @@ internal bool HasVisualBasicEmbeddedAttribute(EntityHandle token) return FindTargetAttribute(token, AttributeDescription.VisualBasicEmbeddedAttribute).HasValue; } + internal bool HasCodeAnalysisEmbeddedAttribute(EntityHandle token) + { + return FindTargetAttribute(token, AttributeDescription.CodeAnalysisEmbeddedAttribute).HasValue; + } + internal bool HasDefaultMemberAttribute(EntityHandle token, out string memberName) { return HasStringValuedAttribute(token, AttributeDescription.DefaultMemberAttribute, out memberName); diff --git a/src/Compilers/Core/Portable/PEWriter/Members.cs b/src/Compilers/Core/Portable/PEWriter/Members.cs index 60736f6385a25..c5e3e4cca74c8 100644 --- a/src/Compilers/Core/Portable/PEWriter/Members.cs +++ b/src/Compilers/Core/Portable/PEWriter/Members.cs @@ -547,7 +547,7 @@ IPlatformInvokeInformation PlatformInvokeData /// /// Custom attributes associated with the method's return value. /// - IEnumerable ReturnValueAttributes { get; } + IEnumerable GetReturnValueAttributes(EmitContext context); /// /// The return value has associated marshalling information. diff --git a/src/Compilers/Core/Portable/PEWriter/MetadataVisitor.cs b/src/Compilers/Core/Portable/PEWriter/MetadataVisitor.cs index 165b05231543d..0db0c2ba58dd0 100644 --- a/src/Compilers/Core/Portable/PEWriter/MetadataVisitor.cs +++ b/src/Compilers/Core/Portable/PEWriter/MetadataVisitor.cs @@ -271,7 +271,7 @@ public void Visit(IEnumerable methods) public virtual void Visit(IMethodDefinition method) { - this.Visit(method.ReturnValueAttributes); + this.Visit(method.GetReturnValueAttributes(Context)); this.Visit(method.ReturnValueCustomModifiers); if (method.HasDeclarativeSecurity) diff --git a/src/Compilers/Core/Portable/PEWriter/MetadataWriter.cs b/src/Compilers/Core/Portable/PEWriter/MetadataWriter.cs index 8372f8038ffbc..20fefdf6fc280 100644 --- a/src/Compilers/Core/Portable/PEWriter/MetadataWriter.cs +++ b/src/Compilers/Core/Portable/PEWriter/MetadataWriter.cs @@ -597,7 +597,7 @@ private List GetConsolidatedTypeParameters(ITypeDefinitio protected ImmutableArray GetParametersToEmit(IMethodDefinition methodDef) { - if (methodDef.ParameterCount == 0 && !(methodDef.ReturnValueIsMarshalledExplicitly || IteratorHelper.EnumerableIsNotEmpty(methodDef.ReturnValueAttributes))) + if (methodDef.ParameterCount == 0 && !(methodDef.ReturnValueIsMarshalledExplicitly || IteratorHelper.EnumerableIsNotEmpty(methodDef.GetReturnValueAttributes(Context)))) { return ImmutableArray.Empty; } @@ -610,7 +610,7 @@ private ImmutableArray GetParametersToEmitCore(IMethodDefi ArrayBuilder builder = null; var parameters = methodDef.Parameters; - if (methodDef.ReturnValueIsMarshalledExplicitly || IteratorHelper.EnumerableIsNotEmpty(methodDef.ReturnValueAttributes)) + if (methodDef.ReturnValueIsMarshalledExplicitly || IteratorHelper.EnumerableIsNotEmpty(methodDef.GetReturnValueAttributes(Context))) { builder = ArrayBuilder.GetInstance(parameters.Length + 1); builder.Add(new ReturnValueParameter(methodDef)); diff --git a/src/Compilers/Core/Portable/PEWriter/ReturnValueParameter.cs b/src/Compilers/Core/Portable/PEWriter/ReturnValueParameter.cs index 16c978e83a438..e4979b423390b 100644 --- a/src/Compilers/Core/Portable/PEWriter/ReturnValueParameter.cs +++ b/src/Compilers/Core/Portable/PEWriter/ReturnValueParameter.cs @@ -16,7 +16,7 @@ internal ReturnValueParameter(IMethodDefinition containingMethod) public IEnumerable GetAttributes(EmitContext context) { - return _containingMethod.ReturnValueAttributes; + return _containingMethod.GetReturnValueAttributes(context); } public ISignature ContainingSignature diff --git a/src/Compilers/Core/Portable/Symbols/Attributes/AttributeDescription.cs b/src/Compilers/Core/Portable/Symbols/Attributes/AttributeDescription.cs index 77d28afcba536..ea72272358e4c 100644 --- a/src/Compilers/Core/Portable/Symbols/Attributes/AttributeDescription.cs +++ b/src/Compilers/Core/Portable/Symbols/Attributes/AttributeDescription.cs @@ -256,7 +256,7 @@ static AttributeDescription() private static readonly byte[][] s_signaturesOfSerializableAttribute = { s_signature_HasThis_Void }; private static readonly byte[][] s_signaturesOfInAttribute = { s_signature_HasThis_Void }; private static readonly byte[][] s_signaturesOfOutAttribute = { s_signature_HasThis_Void }; - private static readonly byte[][] s_signaturesOfReadOnlyAttribute = { s_signature_HasThis_Void }; + private static readonly byte[][] s_signaturesOfIsReadOnlyAttribute = { s_signature_HasThis_Void }; private static readonly byte[][] s_signaturesOfFixedBufferAttribute = { s_signature_HasThis_Void_Type_Int32 }; private static readonly byte[][] s_signaturesOfSuppressUnmanagedCodeSecurityAttribute = { s_signature_HasThis_Void }; private static readonly byte[][] s_signaturesOfPrincipalPermissionAttribute = { s_signature_HasThis_Void_SecurityAction }; @@ -297,6 +297,8 @@ static AttributeDescription() private static readonly byte[][] s_signaturesOfVisualBasicEmbedded = { s_signature_HasThis_Void }; + private static readonly byte[][] s_signaturesOfCodeAnalysisEmbedded = { s_signature_HasThis_Void }; + private static readonly byte[][] s_signaturesOfVisualBasicComClassAttribute = { s_signature_HasThis_Void, @@ -450,7 +452,7 @@ static AttributeDescription() internal static readonly AttributeDescription MarshalAsAttribute = new AttributeDescription("System.Runtime.InteropServices", "MarshalAsAttribute", s_signaturesOfMarshalAsAttribute); internal static readonly AttributeDescription InAttribute = new AttributeDescription("System.Runtime.InteropServices", "InAttribute", s_signaturesOfInAttribute); internal static readonly AttributeDescription OutAttribute = new AttributeDescription("System.Runtime.InteropServices", "OutAttribute", s_signaturesOfOutAttribute); - internal static readonly AttributeDescription ReadOnlyAttribute = new AttributeDescription("System.Runtime.CompilerServices", "ReadOnlyAttribute", s_signaturesOfReadOnlyAttribute); + internal static readonly AttributeDescription IsReadOnlyAttribute = new AttributeDescription("System.Runtime.CompilerServices", "IsReadOnlyAttribute", s_signaturesOfIsReadOnlyAttribute); internal static readonly AttributeDescription CoClassAttribute = new AttributeDescription("System.Runtime.InteropServices", "CoClassAttribute", s_signaturesOfCoClassAttribute); internal static readonly AttributeDescription GuidAttribute = new AttributeDescription("System.Runtime.InteropServices", "GuidAttribute", s_signaturesOfGuidAttribute); internal static readonly AttributeDescription CLSCompliantAttribute = new AttributeDescription("System", "CLSCompliantAttribute", s_signaturesOfCLSCompliantAttribute); @@ -460,6 +462,7 @@ static AttributeDescription() internal static readonly AttributeDescription PermissionSetAttribute = new AttributeDescription("System.Security.Permissions", "PermissionSetAttribute", s_signaturesOfPermissionSetAttribute); internal static readonly AttributeDescription TypeIdentifierAttribute = new AttributeDescription("System.Runtime.InteropServices", "TypeIdentifierAttribute", s_signaturesOfTypeIdentifierAttribute); internal static readonly AttributeDescription VisualBasicEmbeddedAttribute = new AttributeDescription("Microsoft.VisualBasic", "Embedded", s_signaturesOfVisualBasicEmbedded); + internal static readonly AttributeDescription CodeAnalysisEmbeddedAttribute = new AttributeDescription("Microsoft.CodeAnalysis", "EmbeddedAttribute", s_signaturesOfCodeAnalysisEmbedded); internal static readonly AttributeDescription VisualBasicComClassAttribute = new AttributeDescription("Microsoft.VisualBasic", "ComClassAttribute", s_signaturesOfVisualBasicComClassAttribute); internal static readonly AttributeDescription StandardModuleAttribute = new AttributeDescription("Microsoft.VisualBasic.CompilerServices", "StandardModuleAttribute", s_signaturesOfStandardModuleAttribute); internal static readonly AttributeDescription OptionCompareAttribute = new AttributeDescription("Microsoft.VisualBasic.CompilerServices", "OptionCompareAttribute", s_signaturesOfOptionCompareAttribute); diff --git a/src/Compilers/Core/Portable/Symbols/Attributes/CommonTypeEarlyWellKnownAttributeData.cs b/src/Compilers/Core/Portable/Symbols/Attributes/CommonTypeEarlyWellKnownAttributeData.cs index af8ba8128f004..ae801b63d1163 100644 --- a/src/Compilers/Core/Portable/Symbols/Attributes/CommonTypeEarlyWellKnownAttributeData.cs +++ b/src/Compilers/Core/Portable/Symbols/Attributes/CommonTypeEarlyWellKnownAttributeData.cs @@ -91,5 +91,23 @@ public ObsoleteAttributeData ObsoleteAttributeData } } #endregion + + #region CodeAnalysisEmbeddedAttribute + private bool _hasCodeAnalysisEmbeddedAttribute; + public bool HasCodeAnalysisEmbeddedAttribute + { + get + { + VerifySealed(expected: true); + return _hasCodeAnalysisEmbeddedAttribute; + } + set + { + VerifySealed(expected: false); + _hasCodeAnalysisEmbeddedAttribute = value; + SetDataStored(); + } + } + #endregion } } diff --git a/src/Compilers/Core/Portable/WellKnownMember.cs b/src/Compilers/Core/Portable/WellKnownMember.cs index 45c838dd6fd10..416edb70fa555 100644 --- a/src/Compilers/Core/Portable/WellKnownMember.cs +++ b/src/Compilers/Core/Portable/WellKnownMember.cs @@ -417,7 +417,7 @@ internal enum WellKnownMember Microsoft_CodeAnalysis_Runtime_Instrumentation__CreatePayload, System_Runtime_CompilerServices_ReferenceAssemblyAttribute__ctor, - System_Runtime_CompilerServices_ReadOnlyAttribute__ctor, + System_Runtime_CompilerServices_IsReadOnlyAttribute__ctor, System_Runtime_CompilerServices_IsByRefLikeAttribute__ctor, diff --git a/src/Compilers/Core/Portable/WellKnownMembers.cs b/src/Compilers/Core/Portable/WellKnownMembers.cs index e69c796f46084..0954d85609db1 100644 --- a/src/Compilers/Core/Portable/WellKnownMembers.cs +++ b/src/Compilers/Core/Portable/WellKnownMembers.cs @@ -2886,9 +2886,9 @@ static WellKnownMembers() 0, // Method Signature (byte)SignatureTypeCode.TypeHandle, (byte)SpecialType.System_Void, - // System_Runtime_CompilerServices_ReadOnlyAttribute__ctor + // System_Runtime_CompilerServices_IsReadOnlyAttribute__ctor (byte)(MemberFlags.Constructor), // Flags - (byte)WellKnownType.ExtSentinel, (byte)(WellKnownType.System_Runtime_CompilerServices_ReadOnlyAttribute - WellKnownType.ExtSentinel), // DeclaringTypeId + (byte)WellKnownType.ExtSentinel, (byte)(WellKnownType.System_Runtime_CompilerServices_IsReadOnlyAttribute - WellKnownType.ExtSentinel), // DeclaringTypeId 0, // Arity 0, // Method Signature (byte)SignatureTypeCode.TypeHandle, (byte)SpecialType.System_Void, @@ -3259,7 +3259,7 @@ static WellKnownMembers() "CreatePayload", // Microsoft_CodeAnalysis_Runtime_Instrumentation__CreatePayload ".ctor", // System_Runtime_CompilerServices_ReferenceAssemblyAttribute__ctor - ".ctor", // System_Runtime_CompilerServices_ReadOnlyAttribute__ctor + ".ctor", // System_Runtime_CompilerServices_IsReadOnlyAttribute__ctor ".ctor", // System_Runtime_CompilerServices_IsByRefLikeAttribute__ctor }; diff --git a/src/Compilers/Core/Portable/WellKnownTypes.cs b/src/Compilers/Core/Portable/WellKnownTypes.cs index c31c54bcc7527..16e568b7ab8c0 100644 --- a/src/Compilers/Core/Portable/WellKnownTypes.cs +++ b/src/Compilers/Core/Portable/WellKnownTypes.cs @@ -265,7 +265,7 @@ internal enum WellKnownType Microsoft_CodeAnalysis_Runtime_Instrumentation, System_Runtime_CompilerServices_ReferenceAssemblyAttribute, - System_Runtime_CompilerServices_ReadOnlyAttribute, + System_Runtime_CompilerServices_IsReadOnlyAttribute, System_Runtime_CompilerServices_IsByRefLikeAttribute, NextAvailable, @@ -527,7 +527,7 @@ internal static class WellKnownTypes "System.Runtime.CompilerServices.ReferenceAssemblyAttribute", - "System.Runtime.CompilerServices.ReadOnlyAttribute", + "System.Runtime.CompilerServices.IsReadOnlyAttribute", "System.Runtime.CompilerServices.IsByRefLikeAttribute", }; diff --git a/src/Compilers/Test/Utilities/CSharp/CSharpTestBase.cs b/src/Compilers/Test/Utilities/CSharp/CSharpTestBase.cs index 917788c4d65bb..13a206189f804 100644 --- a/src/Compilers/Test/Utilities/CSharp/CSharpTestBase.cs +++ b/src/Compilers/Test/Utilities/CSharp/CSharpTestBase.cs @@ -24,6 +24,7 @@ using System.Threading; using Xunit; using static TestReferences; +using Microsoft.CodeAnalysis.CSharp.Emit; namespace Microsoft.CodeAnalysis.CSharp.Test.Utilities { @@ -237,6 +238,17 @@ internal override IEnumerable ReferencesToModuleSymbols(IEnumerab }); } + internal static PEAssemblyBuilder GetDefaultPEBuilder(CSharpCompilation compilation) + { + // PROTOTYPE(readonlyRefs): Using a PEAssemblyBuilder here is a hack till https://github.com/dotnet/roslyn/issues/18799 is fixed. + return new PEAssemblyBuilder( + (SourceAssemblySymbol)compilation.Assembly, + EmitOptions.Default, + compilation.Options.OutputKind, + GetDefaultModulePropertiesForSerialization(), + SpecializedCollections.EmptyEnumerable()); + } + protected override CompilationOptions CompilationOptionsReleaseDll { get { return TestOptions.ReleaseDll; } diff --git a/src/Compilers/Test/Utilities/CSharp/CompilationTestUtils.cs b/src/Compilers/Test/Utilities/CSharp/CompilationTestUtils.cs index 30c4054aacea6..1d234158abe22 100644 --- a/src/Compilers/Test/Utilities/CSharp/CompilationTestUtils.cs +++ b/src/Compilers/Test/Utilities/CSharp/CompilationTestUtils.cs @@ -1,16 +1,18 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Linq; using Microsoft.CodeAnalysis.CSharp.Emit; using Microsoft.CodeAnalysis.CSharp.Symbols; using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Text; +using Microsoft.CodeAnalysis.Emit; +using Microsoft.CodeAnalysis.Test.Utilities; using Roslyn.Test.Utilities; using Roslyn.Utilities; +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; using Xunit; +using Microsoft.CodeAnalysis.CSharp.Test.Utilities; namespace Microsoft.CodeAnalysis.CSharp.UnitTests { @@ -266,20 +268,21 @@ public static SemanticInfoSummary GetSpeculativeSemanticInfoSummary(this Semanti return summary; } - internal static ImmutableArray GetSynthesizedAttributes(this ISymbol symbol, bool forReturnType = false) + internal static ImmutableArray GetSynthesizedAttributes(this Symbol symbol, bool forReturnType = false) { + var builder = CSharpTestBase.GetDefaultPEBuilder(symbol.DeclaringCompilation); ArrayBuilder attributes = null; + if (!forReturnType) { - var context = new ModuleCompilationState(); - ((Symbol)symbol).AddSynthesizedAttributes(context, ref attributes); + symbol.AddSynthesizedAttributes(builder, ref attributes); } else { Assert.True(symbol.Kind == SymbolKind.Method, "Incorrect usage of GetSynthesizedAttributes"); - ((MethodSymbol)symbol).AddSynthesizedReturnTypeAttributes(ref attributes); + ((MethodSymbol)symbol).AddSynthesizedReturnTypeAttributes(builder, ref attributes); } - + return attributes != null ? attributes.ToImmutableAndFree() : ImmutableArray.Create(); } diff --git a/src/Compilers/Test/Utilities/VisualBasic/MockSymbols.vb b/src/Compilers/Test/Utilities/VisualBasic/MockSymbols.vb index 828a0c6cc137c..5d9874f341194 100644 --- a/src/Compilers/Test/Utilities/VisualBasic/MockSymbols.vb +++ b/src/Compilers/Test/Utilities/VisualBasic/MockSymbols.vb @@ -295,7 +295,13 @@ Friend Class MockNamedTypeSymbol End Get End Property - Friend Overrides ReadOnly Property HasEmbeddedAttribute As Boolean + Friend Overrides ReadOnly Property HasCodeAnalysisEmbeddedAttribute As Boolean + Get + Throw New NotImplementedException() + End Get + End Property + + Friend Overrides ReadOnly Property HasVisualBasicEmbeddedAttribute As Boolean Get Throw New NotImplementedException() End Get diff --git a/src/Compilers/VisualBasic/Portable/Binding/Binder_Lookup.vb b/src/Compilers/VisualBasic/Portable/Binding/Binder_Lookup.vb index dce5f17d4a6d7..e7632325a8e92 100644 --- a/src/Compilers/VisualBasic/Portable/Binding/Binder_Lookup.vb +++ b/src/Compilers/VisualBasic/Portable/Binding/Binder_Lookup.vb @@ -106,7 +106,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ' A non-empty SingleLookupResult with the result is returned. ' ' For symbols from outside of this compilation the method also checks - ' if the symbol is marked with 'Microsoft.VisualBasic.Embedded' attribute. + ' if the symbol is marked with 'Microsoft.VisualBasic.Embedded' or 'Microsoft.CodeAnalysis.Embedded' attributes. ' ' If arity passed in is -1, no arity checks are done. Friend Function CheckViability(sym As Symbol, @@ -152,9 +152,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic unwrappedSym = asAlias.Target End If - ' Check for external symbols marked with 'Microsoft.VisualBasic.Embedded' attribute - If unwrappedSym.ContainingModule IsNot Me.ContainingModule AndAlso unwrappedSym.IsHiddenByEmbeddedAttribute() Then - Return SingleLookupResult.Empty + ' Check for external symbols marked with 'Microsoft.VisualBasic.Embedded' or 'Microsoft.CodeAnalysis.Embedded' attributes + If unwrappedSym.ContainingModule IsNot Me.ContainingModule Then + If unwrappedSym.IsHiddenByVisualBasicEmbeddedAttribute() OrElse unwrappedSym.IsHiddenByCodeAnalysisEmbeddedAttribute() Then + Return SingleLookupResult.Empty + End If End If If unwrappedSym.Kind = SymbolKind.NamedType AndAlso unwrappedSym.EmbeddedSymbolKind = EmbeddedSymbolKind.EmbeddedAttribute AndAlso diff --git a/src/Compilers/VisualBasic/Portable/Emit/MethodSymbolAdapter.vb b/src/Compilers/VisualBasic/Portable/Emit/MethodSymbolAdapter.vb index f03aee2824bc4..e7111b9536f18 100644 --- a/src/Compilers/VisualBasic/Portable/Emit/MethodSymbolAdapter.vb +++ b/src/Compilers/VisualBasic/Portable/Emit/MethodSymbolAdapter.vb @@ -457,13 +457,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols End Get End Property - Private ReadOnly Property IMethodDefinitionReturnValueAttributes As IEnumerable(Of Cci.ICustomAttribute) Implements Cci.IMethodDefinition.ReturnValueAttributes - Get - Return GetReturnValueCustomAttributesToEmit() - End Get - End Property - - Private Function GetReturnValueCustomAttributesToEmit() As IEnumerable(Of Cci.ICustomAttribute) + Private Function IMethodDefinitionGetReturnValueAttributes(context As EmitContext) As IEnumerable(Of Cci.ICustomAttribute) Implements Cci.IMethodDefinition.GetReturnValueAttributes CheckDefinitionInvariant() Dim userDefined As ImmutableArray(Of VisualBasicAttributeData) diff --git a/src/Compilers/VisualBasic/Portable/Emit/NoPia/EmbeddedEvent.vb b/src/Compilers/VisualBasic/Portable/Emit/NoPia/EmbeddedEvent.vb index 42a4dbae71bbc..98fd6e97c7167 100644 --- a/src/Compilers/VisualBasic/Portable/Emit/NoPia/EmbeddedEvent.vb +++ b/src/Compilers/VisualBasic/Portable/Emit/NoPia/EmbeddedEvent.vb @@ -12,8 +12,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Emit.NoPia MyBase.New(underlyingEvent, adder, remover, caller) End Sub - Protected Overrides Function GetCustomAttributesToEmit(compilationSatte As ModuleCompilationState) As IEnumerable(Of VisualBasicAttributeData) - Return UnderlyingEvent.GetCustomAttributesToEmit(compilationSatte) + Protected Overrides Function GetCustomAttributesToEmit(moduleBuilder As PEModuleBuilder) As IEnumerable(Of VisualBasicAttributeData) + Return UnderlyingEvent.GetCustomAttributesToEmit(moduleBuilder.CompilationState) End Function Protected Overrides ReadOnly Property IsRuntimeSpecial As Boolean diff --git a/src/Compilers/VisualBasic/Portable/Emit/NoPia/EmbeddedField.vb b/src/Compilers/VisualBasic/Portable/Emit/NoPia/EmbeddedField.vb index 704169dea3838..f74972cc6440b 100644 --- a/src/Compilers/VisualBasic/Portable/Emit/NoPia/EmbeddedField.vb +++ b/src/Compilers/VisualBasic/Portable/Emit/NoPia/EmbeddedField.vb @@ -20,8 +20,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Emit.NoPia End Get End Property - Protected Overrides Function GetCustomAttributesToEmit(compilationState As ModuleCompilationState) As IEnumerable(Of VisualBasicAttributeData) - Return UnderlyingField.GetCustomAttributesToEmit(compilationState) + Protected Overrides Function GetCustomAttributesToEmit(moduleBuilder As PEModuleBuilder) As IEnumerable(Of VisualBasicAttributeData) + Return UnderlyingField.GetCustomAttributesToEmit(moduleBuilder.CompilationState) End Function Protected Overrides Function GetCompileTimeValue(context As EmitContext) As MetadataConstant diff --git a/src/Compilers/VisualBasic/Portable/Emit/NoPia/EmbeddedMethod.vb b/src/Compilers/VisualBasic/Portable/Emit/NoPia/EmbeddedMethod.vb index 7e863361b0c04..3246077d6df3b 100644 --- a/src/Compilers/VisualBasic/Portable/Emit/NoPia/EmbeddedMethod.vb +++ b/src/Compilers/VisualBasic/Portable/Emit/NoPia/EmbeddedMethod.vb @@ -20,8 +20,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Emit.NoPia End Get End Property - Protected Overrides Function GetCustomAttributesToEmit(compilationState As ModuleCompilationState) As IEnumerable(Of VisualBasicAttributeData) - Return UnderlyingMethod.GetCustomAttributesToEmit(compilationState) + Protected Overrides Function GetCustomAttributesToEmit(moduleBuilder As PEModuleBuilder) As IEnumerable(Of VisualBasicAttributeData) + Return UnderlyingMethod.GetCustomAttributesToEmit(moduleBuilder.CompilationState) End Function Protected Overrides Function GetParameters() As ImmutableArray(Of EmbeddedParameter) diff --git a/src/Compilers/VisualBasic/Portable/Emit/NoPia/EmbeddedParameter.vb b/src/Compilers/VisualBasic/Portable/Emit/NoPia/EmbeddedParameter.vb index 889871e1795b5..925abeebdb887 100644 --- a/src/Compilers/VisualBasic/Portable/Emit/NoPia/EmbeddedParameter.vb +++ b/src/Compilers/VisualBasic/Portable/Emit/NoPia/EmbeddedParameter.vb @@ -15,8 +15,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Emit.NoPia Debug.Assert(underlyingParameter.IsDefinition) End Sub - Protected Overrides Function GetCustomAttributesToEmit(compilationState As ModuleCompilationState) As IEnumerable(Of VisualBasicAttributeData) - Return UnderlyingParameter.GetCustomAttributesToEmit(compilationState) + Protected Overrides Function GetCustomAttributesToEmit(moduleBuilder As PEModuleBuilder) As IEnumerable(Of VisualBasicAttributeData) + Return UnderlyingParameter.GetCustomAttributesToEmit(moduleBuilder.CompilationState) End Function Protected Overrides ReadOnly Property HasDefaultValue As Boolean diff --git a/src/Compilers/VisualBasic/Portable/Emit/NoPia/EmbeddedProperty.vb b/src/Compilers/VisualBasic/Portable/Emit/NoPia/EmbeddedProperty.vb index 696f12c9f0e35..1865ce5869666 100644 --- a/src/Compilers/VisualBasic/Portable/Emit/NoPia/EmbeddedProperty.vb +++ b/src/Compilers/VisualBasic/Portable/Emit/NoPia/EmbeddedProperty.vb @@ -14,8 +14,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Emit.NoPia MyBase.New(underlyingProperty, getter, setter) End Sub - Protected Overrides Function GetCustomAttributesToEmit(compilationState As ModuleCompilationState) As IEnumerable(Of VisualBasicAttributeData) - Return UnderlyingProperty.GetCustomAttributesToEmit(compilationState) + Protected Overrides Function GetCustomAttributesToEmit(moduleBuilder As PEModuleBuilder) As IEnumerable(Of VisualBasicAttributeData) + Return UnderlyingProperty.GetCustomAttributesToEmit(moduleBuilder.CompilationState) End Function Protected Overrides Function GetParameters() As ImmutableArray(Of EmbeddedParameter) diff --git a/src/Compilers/VisualBasic/Portable/Emit/NoPia/EmbeddedType.vb b/src/Compilers/VisualBasic/Portable/Emit/NoPia/EmbeddedType.vb index 1b65d32ea120e..7d18a31910777 100644 --- a/src/Compilers/VisualBasic/Portable/Emit/NoPia/EmbeddedType.vb +++ b/src/Compilers/VisualBasic/Portable/Emit/NoPia/EmbeddedType.vb @@ -154,8 +154,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Emit.NoPia End Get End Property - Protected Overrides Function GetCustomAttributesToEmit(compilationState As ModuleCompilationState) As IEnumerable(Of VisualBasicAttributeData) - Return UnderlyingNamedType.GetCustomAttributesToEmit(compilationState) + Protected Overrides Function GetCustomAttributesToEmit(moduleBuilder As PEModuleBuilder) As IEnumerable(Of VisualBasicAttributeData) + Return UnderlyingNamedType.GetCustomAttributesToEmit(moduleBuilder.CompilationState) End Function Protected Overrides Function CreateTypeIdentifierAttribute(hasGuid As Boolean, syntaxNodeOpt As SyntaxNode, diagnostics As DiagnosticBag) As VisualBasicAttributeData diff --git a/src/Compilers/VisualBasic/Portable/Lowering/StateMachineRewriter/SynthesizedContainer.vb b/src/Compilers/VisualBasic/Portable/Lowering/StateMachineRewriter/SynthesizedContainer.vb index c3864ccd5035b..df22c8284ffa0 100644 --- a/src/Compilers/VisualBasic/Portable/Lowering/StateMachineRewriter/SynthesizedContainer.vb +++ b/src/Compilers/VisualBasic/Portable/Lowering/StateMachineRewriter/SynthesizedContainer.vb @@ -129,7 +129,13 @@ Namespace Microsoft.CodeAnalysis.VisualBasic End Get End Property - Friend NotOverridable Overrides ReadOnly Property HasEmbeddedAttribute As Boolean + Friend NotOverridable Overrides ReadOnly Property HasCodeAnalysisEmbeddedAttribute As Boolean + Get + Return False + End Get + End Property + + Friend NotOverridable Overrides ReadOnly Property HasVisualBasicEmbeddedAttribute As Boolean Get Return False End Get diff --git a/src/Compilers/VisualBasic/Portable/Symbols/AnonymousTypes/PublicSymbols/AnonymousTypeOrDelegatePublicSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/AnonymousTypes/PublicSymbols/AnonymousTypeOrDelegatePublicSymbol.vb index d1ca73b701b01..ec1e6b5d0c4b9 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/AnonymousTypes/PublicSymbols/AnonymousTypeOrDelegatePublicSymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/AnonymousTypes/PublicSymbols/AnonymousTypeOrDelegatePublicSymbol.vb @@ -89,7 +89,13 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols End Get End Property - Friend Overrides ReadOnly Property HasEmbeddedAttribute As Boolean + Friend Overrides ReadOnly Property HasCodeAnalysisEmbeddedAttribute As Boolean + Get + Return False + End Get + End Property + + Friend Overrides ReadOnly Property HasVisualBasicEmbeddedAttribute As Boolean Get Return False End Get diff --git a/src/Compilers/VisualBasic/Portable/Symbols/AnonymousTypes/SynthesizedSymbols/AnonymousTypeOrDelegateTemplateSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/AnonymousTypes/SynthesizedSymbols/AnonymousTypeOrDelegateTemplateSymbol.vb index d6d5e5857f8f1..e153394f1f655 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/AnonymousTypes/SynthesizedSymbols/AnonymousTypeOrDelegateTemplateSymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/AnonymousTypes/SynthesizedSymbols/AnonymousTypeOrDelegateTemplateSymbol.vb @@ -143,7 +143,13 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols End Get End Property - Friend Overrides ReadOnly Property HasEmbeddedAttribute As Boolean + Friend Overrides ReadOnly Property HasCodeAnalysisEmbeddedAttribute As Boolean + Get + Return False + End Get + End Property + + Friend Overrides ReadOnly Property HasVisualBasicEmbeddedAttribute As Boolean Get Return False End Get diff --git a/src/Compilers/VisualBasic/Portable/Symbols/AssemblySymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/AssemblySymbol.vb index 17b972d567f21..1835e7e46726a 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/AssemblySymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/AssemblySymbol.vb @@ -519,7 +519,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols candidate = Nothing End If - If IsAcceptableMatchForGetTypeByNameAndArity(candidate) AndAlso Not candidate.IsHiddenByEmbeddedAttribute() AndAlso candidate <> result Then + If IsAcceptableMatchForGetTypeByNameAndArity(candidate) AndAlso + Not candidate.IsHiddenByVisualBasicEmbeddedAttribute() AndAlso + Not candidate.IsHiddenByCodeAnalysisEmbeddedAttribute() AndAlso + candidate <> result Then If (result IsNot Nothing) Then ' Ambiguity If ignoreCorLibraryDuplicatedTypes Then diff --git a/src/Compilers/VisualBasic/Portable/Symbols/Attributes/WellKnownAttributeData/TypeEarlyWellKnownAttributeData.vb b/src/Compilers/VisualBasic/Portable/Symbols/Attributes/WellKnownAttributeData/TypeEarlyWellKnownAttributeData.vb index efcd9672e4e84..bedab4b65d647 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/Attributes/WellKnownAttributeData/TypeEarlyWellKnownAttributeData.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/Attributes/WellKnownAttributeData/TypeEarlyWellKnownAttributeData.vb @@ -10,15 +10,15 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols Friend Class TypeEarlyWellKnownAttributeData Inherits CommonTypeEarlyWellKnownAttributeData - Private _hasEmbeddedAttribute As Boolean = False - Friend Property HasEmbeddedAttribute As Boolean + Private _hasVisualBasicEmbeddedAttribute As Boolean = False + Friend Property HasVisualBasicEmbeddedAttribute As Boolean Get VerifySealed(expected:=True) - Return Me._hasEmbeddedAttribute + Return Me._hasVisualBasicEmbeddedAttribute End Get Set(value As Boolean) VerifySealed(expected:=False) - Me._hasEmbeddedAttribute = value + Me._hasVisualBasicEmbeddedAttribute = value SetDataStored() End Set End Property diff --git a/src/Compilers/VisualBasic/Portable/Symbols/ErrorTypeSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/ErrorTypeSymbol.vb index ec10f56291888..adead0e1ac987 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/ErrorTypeSymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/ErrorTypeSymbol.vb @@ -237,7 +237,13 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols End Get End Property - Friend Overrides ReadOnly Property HasEmbeddedAttribute As Boolean + Friend Overrides ReadOnly Property HasCodeAnalysisEmbeddedAttribute As Boolean + Get + Return False + End Get + End Property + + Friend Overrides ReadOnly Property HasVisualBasicEmbeddedAttribute As Boolean Get Return False End Get diff --git a/src/Compilers/VisualBasic/Portable/Symbols/Metadata/PE/PENamedTypeSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/Metadata/PE/PENamedTypeSymbol.vb index dde8e9070e09a..8c5d47982221f 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/Metadata/PE/PENamedTypeSymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/Metadata/PE/PENamedTypeSymbol.vb @@ -80,7 +80,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols.Metadata.PE Private _lazyMightContainExtensionMethods As Byte = ThreeState.Unknown - Private _lazyHasEmbeddedAttribute As Integer = ThreeState.Unknown + Private _lazyHasCodeAnalysisEmbeddedAttribute As Integer = ThreeState.Unknown + + Private _lazyHasVisualBasicEmbeddedAttribute As Integer = ThreeState.Unknown Private _lazyObsoleteAttributeData As ObsoleteAttributeData = ObsoleteAttributeData.Uninitialized @@ -933,15 +935,27 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols.Metadata.PE End Get End Property - Friend Overrides ReadOnly Property HasEmbeddedAttribute As Boolean + Friend Overrides ReadOnly Property HasCodeAnalysisEmbeddedAttribute As Boolean + Get + If Me._lazyHasCodeAnalysisEmbeddedAttribute = ThreeState.Unknown Then + Interlocked.CompareExchange( + Me._lazyHasCodeAnalysisEmbeddedAttribute, + Me.ContainingPEModule.Module.HasCodeAnalysisEmbeddedAttribute(Me._handle).ToThreeState(), + ThreeState.Unknown) + End If + Return Me._lazyHasCodeAnalysisEmbeddedAttribute = ThreeState.True + End Get + End Property + + Friend Overrides ReadOnly Property HasVisualBasicEmbeddedAttribute As Boolean Get - If Me._lazyHasEmbeddedAttribute = ThreeState.Unknown Then - Interlocked.CompareExchange(Me._lazyHasEmbeddedAttribute, - If(Me.ContainingPEModule.Module.HasVisualBasicEmbeddedAttribute(Me._handle), - ThreeState.True, ThreeState.False), - ThreeState.Unknown) + If Me._lazyHasVisualBasicEmbeddedAttribute = ThreeState.Unknown Then + Interlocked.CompareExchange( + Me._lazyHasVisualBasicEmbeddedAttribute, + Me.ContainingPEModule.Module.HasVisualBasicEmbeddedAttribute(Me._handle).ToThreeState(), + ThreeState.Unknown) End If - Return Me._lazyHasEmbeddedAttribute = ThreeState.True + Return Me._lazyHasVisualBasicEmbeddedAttribute = ThreeState.True End Get End Property diff --git a/src/Compilers/VisualBasic/Portable/Symbols/NamedTypeSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/NamedTypeSymbol.vb index 08d5542567ccb..9ef24e403869b 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/NamedTypeSymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/NamedTypeSymbol.vb @@ -270,10 +270,15 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols ''' Public MustOverride ReadOnly Property MightContainExtensionMethods As Boolean Implements INamedTypeSymbol.MightContainExtensionMethods + ''' + ''' Returns True if the type is marked by 'Microsoft.CodeAnalysis.Embedded' attribute. + ''' + Friend MustOverride ReadOnly Property HasCodeAnalysisEmbeddedAttribute As Boolean + ''' ''' Returns True if the type is marked by 'Microsoft.VisualBasic.Embedded' attribute. ''' - Friend MustOverride ReadOnly Property HasEmbeddedAttribute As Boolean + Friend MustOverride ReadOnly Property HasVisualBasicEmbeddedAttribute As Boolean ''' ''' A Named type is an extensible interface if both the following are true: diff --git a/src/Compilers/VisualBasic/Portable/Symbols/Retargeting/RetargetingNamedTypeSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/Retargeting/RetargetingNamedTypeSymbol.vb index b43ccd6ded779..31a0898e05cd8 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/Retargeting/RetargetingNamedTypeSymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/Retargeting/RetargetingNamedTypeSymbol.vb @@ -114,9 +114,15 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols.Retargeting End Get End Property - Friend Overrides ReadOnly Property HasEmbeddedAttribute As Boolean + Friend Overrides ReadOnly Property HasCodeAnalysisEmbeddedAttribute As Boolean Get - Return _underlyingType.HasEmbeddedAttribute + Return _underlyingType.HasCodeAnalysisEmbeddedAttribute + End Get + End Property + + Friend Overrides ReadOnly Property HasVisualBasicEmbeddedAttribute As Boolean + Get + Return _underlyingType.HasVisualBasicEmbeddedAttribute End Get End Property diff --git a/src/Compilers/VisualBasic/Portable/Symbols/Source/ImplicitNamedTypeSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/Source/ImplicitNamedTypeSymbol.vb index 5e3a1f02683a5..553e9048ffbe7 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/Source/ImplicitNamedTypeSymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/Source/ImplicitNamedTypeSymbol.vb @@ -135,7 +135,13 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols End Get End Property - Friend Overrides ReadOnly Property HasEmbeddedAttribute As Boolean + Friend Overrides ReadOnly Property HasCodeAnalysisEmbeddedAttribute As Boolean + Get + Return False + End Get + End Property + + Friend Overrides ReadOnly Property HasVisualBasicEmbeddedAttribute As Boolean Get Return False End Get diff --git a/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceNamedTypeSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceNamedTypeSymbol.vb index 0d1aa050c3df9..3d284f6bcbd09 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceNamedTypeSymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceNamedTypeSymbol.vb @@ -1832,10 +1832,17 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols Return DirectCast(attributesBag.DecodedWellKnownAttributeData, CommonTypeWellKnownAttributeData) End Function - Friend Overrides ReadOnly Property HasEmbeddedAttribute As Boolean + Friend Overrides ReadOnly Property HasCodeAnalysisEmbeddedAttribute As Boolean Get Dim data As TypeEarlyWellKnownAttributeData = GetEarlyDecodedWellKnownAttributeData() - Return data IsNot Nothing AndAlso data.HasEmbeddedAttribute + Return data IsNot Nothing AndAlso data.HasCodeAnalysisEmbeddedAttribute + End Get + End Property + + Friend Overrides ReadOnly Property HasVisualBasicEmbeddedAttribute As Boolean + Get + Dim data As TypeEarlyWellKnownAttributeData = GetEarlyDecodedWellKnownAttributeData() + Return data IsNot Nothing AndAlso data.HasVisualBasicEmbeddedAttribute End Get End Property @@ -1974,12 +1981,20 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols ' Handle Microsoft.VisualBasic.Embedded attribute Dim attrdata = arguments.Binder.GetAttribute(arguments.AttributeSyntax, arguments.AttributeType, hasAnyDiagnostics) If Not attrdata.HasErrors Then - arguments.GetOrCreateData(Of TypeEarlyWellKnownAttributeData)().HasEmbeddedAttribute = True + arguments.GetOrCreateData(Of TypeEarlyWellKnownAttributeData)().HasVisualBasicEmbeddedAttribute = True + Return If(Not hasAnyDiagnostics, attrdata, Nothing) + Else + Return Nothing + End If + ElseIf VisualBasicAttributeData.IsTargetEarlyAttribute(arguments.AttributeType, arguments.AttributeSyntax, AttributeDescription.CodeAnalysisEmbeddedAttribute) Then + ' Handle Microsoft.CodeAnalysis.Embedded attribute + Dim attrdata = arguments.Binder.GetAttribute(arguments.AttributeSyntax, arguments.AttributeType, hasAnyDiagnostics) + If Not attrdata.HasErrors Then + arguments.GetOrCreateData(Of TypeEarlyWellKnownAttributeData)().HasCodeAnalysisEmbeddedAttribute = True Return If(Not hasAnyDiagnostics, attrdata, Nothing) Else Return Nothing End If - ElseIf VisualBasicAttributeData.IsTargetEarlyAttribute(arguments.AttributeType, arguments.AttributeSyntax, AttributeDescription.ComImportAttribute) Then ' Handle ComImportAttribute Dim attrdata = arguments.Binder.GetAttribute(arguments.AttributeSyntax, arguments.AttributeType, hasAnyDiagnostics) diff --git a/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceNamedTypeSymbol_ComClass.vb b/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceNamedTypeSymbol_ComClass.vb index 51ee863494fa8..de414acc5594b 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceNamedTypeSymbol_ComClass.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceNamedTypeSymbol_ComClass.vb @@ -783,7 +783,13 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols Return SpecializedCollections.EmptyEnumerable(Of FieldSymbol)() End Function - Friend Overrides ReadOnly Property HasEmbeddedAttribute As Boolean + Friend Overrides ReadOnly Property HasCodeAnalysisEmbeddedAttribute As Boolean + Get + Throw ExceptionUtilities.Unreachable + End Get + End Property + + Friend Overrides ReadOnly Property HasVisualBasicEmbeddedAttribute As Boolean Get Throw ExceptionUtilities.Unreachable End Get diff --git a/src/Compilers/VisualBasic/Portable/Symbols/SubstitutedNamedType.vb b/src/Compilers/VisualBasic/Portable/Symbols/SubstitutedNamedType.vb index 3ca7839a12853..c1e4b14ac4c7c 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/SubstitutedNamedType.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/SubstitutedNamedType.vb @@ -138,9 +138,15 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols End Get End Property - Friend NotOverridable Overrides ReadOnly Property HasEmbeddedAttribute As Boolean + Friend NotOverridable Overrides ReadOnly Property HasCodeAnalysisEmbeddedAttribute As Boolean Get - Return OriginalDefinition.HasEmbeddedAttribute + Return OriginalDefinition.HasCodeAnalysisEmbeddedAttribute + End Get + End Property + + Friend NotOverridable Overrides ReadOnly Property HasVisualBasicEmbeddedAttribute As Boolean + Get + Return OriginalDefinition.HasVisualBasicEmbeddedAttribute End Get End Property diff --git a/src/Compilers/VisualBasic/Portable/Symbols/SymbolExtensions.vb b/src/Compilers/VisualBasic/Portable/Symbols/SymbolExtensions.vb index 80c2df6c3d3ba..c88c7dca10768 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/SymbolExtensions.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/SymbolExtensions.vb @@ -359,22 +359,41 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols Return symbol.Kind = SymbolKind.Method AndAlso DirectCast(symbol, MethodSymbol).IsUserDefinedOperator() End Function + ''' + ''' Does symbol or its containing type have Microsoft.CodeAnalysis.Embedded() attribute + ''' + + Friend Function IsHiddenByCodeAnalysisEmbeddedAttribute(symbol As Symbol) As Boolean + ' Only upper-level types should be checked + Dim upperLevelType = GetUpperLevelNamedTypeSymbol(symbol) + Return upperLevelType IsNot Nothing AndAlso upperLevelType.HasCodeAnalysisEmbeddedAttribute + End Function + ''' ''' Does symbol or its containing type have Microsoft.VisualBasic.Embedded() attribute ''' - Friend Function IsHiddenByEmbeddedAttribute(symbol As Symbol) As Boolean + Friend Function IsHiddenByVisualBasicEmbeddedAttribute(symbol As Symbol) As Boolean ' Only upper-level types should be checked + Dim upperLevelType = GetUpperLevelNamedTypeSymbol(symbol) + Return upperLevelType IsNot Nothing AndAlso upperLevelType.HasVisualBasicEmbeddedAttribute + End Function + + ''' + ''' Gets the upper-level named type symbol, or returns Nothing if it does not exist. + ''' + + Friend Function GetUpperLevelNamedTypeSymbol(symbol As Symbol) As NamedTypeSymbol Dim upperLevelType = If(symbol.Kind = SymbolKind.NamedType, DirectCast(symbol, NamedTypeSymbol), symbol.ContainingType) If upperLevelType Is Nothing Then - Return False + Return Nothing End If While upperLevelType.ContainingType IsNot Nothing upperLevelType = upperLevelType.ContainingType End While - Return upperLevelType.HasEmbeddedAttribute + Return upperLevelType End Function diff --git a/src/Compilers/VisualBasic/Portable/Symbols/SynthesizedSymbols/SynthesizedEventDelegateSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/SynthesizedSymbols/SynthesizedEventDelegateSymbol.vb index 965f61c46e1fa..db1f96ff3aff9 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/SynthesizedSymbols/SynthesizedEventDelegateSymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/SynthesizedSymbols/SynthesizedEventDelegateSymbol.vb @@ -259,7 +259,13 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols End Get End Property - Friend Overrides ReadOnly Property HasEmbeddedAttribute As Boolean + Friend Overrides ReadOnly Property HasCodeAnalysisEmbeddedAttribute As Boolean + Get + Return False + End Get + End Property + + Friend Overrides ReadOnly Property HasVisualBasicEmbeddedAttribute As Boolean Get Return False End Get diff --git a/src/Compilers/VisualBasic/Portable/Symbols/UnboundGenericType.vb b/src/Compilers/VisualBasic/Portable/Symbols/UnboundGenericType.vb index 7eb074b7256af..4cba3a4e98d89 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/UnboundGenericType.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/UnboundGenericType.vb @@ -131,9 +131,15 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols End Get End Property - Friend Overrides ReadOnly Property HasEmbeddedAttribute As Boolean + Friend Overrides ReadOnly Property HasCodeAnalysisEmbeddedAttribute As Boolean Get - Return OriginalDefinition.HasEmbeddedAttribute + Return OriginalDefinition.HasCodeAnalysisEmbeddedAttribute + End Get + End Property + + Friend Overrides ReadOnly Property HasVisualBasicEmbeddedAttribute As Boolean + Get + Return OriginalDefinition.HasVisualBasicEmbeddedAttribute End Get End Property diff --git a/src/Compilers/VisualBasic/Portable/Symbols/Wrapped/WrappedNamedTypeSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/Wrapped/WrappedNamedTypeSymbol.vb index 4f1bfb66d53ba..4b436a84988a8 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/Wrapped/WrappedNamedTypeSymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/Wrapped/WrappedNamedTypeSymbol.vb @@ -133,9 +133,15 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols End Get End Property - Friend Overrides ReadOnly Property HasEmbeddedAttribute As Boolean + Friend Overrides ReadOnly Property HasCodeAnalysisEmbeddedAttribute As Boolean Get - Return Me._underlyingType.HasEmbeddedAttribute + Return Me._underlyingType.HasCodeAnalysisEmbeddedAttribute + End Get + End Property + + Friend Overrides ReadOnly Property HasVisualBasicEmbeddedAttribute As Boolean + Get + Return Me._underlyingType.HasVisualBasicEmbeddedAttribute End Get End Property diff --git a/src/Compilers/VisualBasic/Test/Emit/Attributes/AttributeTests.vb b/src/Compilers/VisualBasic/Test/Emit/Attributes/AttributeTests.vb index f392c0c3a65d1..02a5cf9c8052f 100644 --- a/src/Compilers/VisualBasic/Test/Emit/Attributes/AttributeTests.vb +++ b/src/Compilers/VisualBasic/Test/Emit/Attributes/AttributeTests.vb @@ -4337,5 +4337,237 @@ BC30002: Type 'xyz' is not defined. ]]>) End Sub + + Public Sub ReferencingEmbeddedAttributesFromADifferentAssemblyFails_Internal() + + Dim reference = + + +Namespace Microsoft.CodeAnalysis + Friend Class EmbeddedAttribute + Inherits System.Attribute + End Class +End Namespace +Namespace TestReference + + Friend Class TestType1 + End Class + + Friend Class TestType2 + End Class + Friend Class TestType3 + End Class +End Namespace +]]> + + + + Dim referenceCompilation = CreateCompilationWithMscorlib(reference).ToMetadataReference() + + Dim code = " +Public Class Program + Public Shared Sub Main() + Dim obj1 = New TestReference.TestType1() + Dim obj2 = New TestReference.TestType2() + Dim obj3 = New TestReference.TestType3() ' This should be fine + End Sub +End Class" + + Dim compilation = CreateCompilationWithMscorlib(code, references:={referenceCompilation}, assemblyName:="Source") + + AssertTheseDiagnostics(compilation, ) + End Sub + + + Public Sub ReferencingEmbeddedAttributesFromADifferentAssemblyFails_Public() + + Dim reference = + + + Public Class TestType1 + End Class + + Public Class TestType2 + End Class + Public Class TestType3 + End Class +End Namespace +]]> + + + + Dim referenceCompilation = CreateCompilationWithMscorlib(reference).ToMetadataReference() + + Dim code = " +Public Class Program + Public Shared Sub Main() + Dim obj1 = New TestReference.TestType1() + Dim obj2 = New TestReference.TestType2() + Dim obj3 = New TestReference.TestType3() ' This should be fine + End Sub +End Class" + + Dim compilation = CreateCompilationWithMscorlib(code, references:={referenceCompilation}) + + AssertTheseDiagnostics(compilation, ) + End Sub + + + Public Sub ReferencingEmbeddedAttributesFromADifferentAssemblyFails_Module() + + Dim moduleCode = CreateCompilationWithMscorlib(options:=TestOptions.ReleaseModule, source:=" +Namespace Microsoft.CodeAnalysis + Friend Class EmbeddedAttribute + Inherits System.Attribute + End Class +End Namespace +Namespace TestReference + + Public Class TestType1 + End Class + + Public Class TestType2 + End Class + Public Class TestType3 + End Class +End Namespace") + + Dim reference = ModuleMetadata.CreateFromImage(moduleCode.EmitToArray()).GetReference() + + Dim code = " +Public Class Program + Public Shared Sub Main() + Dim obj1 = New TestReference.TestType1() + Dim obj2 = New TestReference.TestType2() + Dim obj3 = New TestReference.TestType3() ' This should be fine + End Sub +End Class" + + Dim compilation = CreateCompilationWithMscorlib(code, references:={reference}) + + AssertTheseDiagnostics(compilation, ) + End Sub + + + Public Sub ReferencingEmbeddedAttributesFromTheSameAssemblySucceeds() + + Dim compilation = CreateCompilationWithMscorlib(source:=" +Namespace Microsoft.CodeAnalysis + Friend Class EmbeddedAttribute + Inherits System.Attribute + End Class +End Namespace +Namespace TestReference + + Public Class TestType1 + End Class + + Public Class TestType2 + End Class + Public Class TestType3 + End Class +End Namespace +Public Class Program + Public Shared Sub Main() + Dim obj1 = New TestReference.TestType1() + Dim obj2 = New TestReference.TestType2() + Dim obj3 = New TestReference.TestType3() + End Sub +End Class") + + AssertTheseEmitDiagnostics(compilation) + + End Sub + + + Public Sub EmbeddedAttributeInSourceIsAllowedIfCompilerDoesNotNeedToGenerateOne() + + Dim compilation = CreateCompilationWithMscorlib(options:=TestOptions.ReleaseExe, sources:= + + + Public Class TestReference + Public Shared Function GetValue() As Integer + Return 3 + End Function + End Class +End Namespace +Public Class Program + Public Shared Sub Main() + ' This should be fine, as the compiler doesn't need to use an embedded attribute for this compilation + System.Console.Write(OtherNamespace.TestReference.GetValue()) + End Sub +End Class +]]> + +) + + CompileAndVerify(compilation, expectedOutput:="3") + End Sub + + + Public Sub EmbeddedTypesInAnAssemblyAreNotExposedExternally() + + Dim compilation1 = CreateCompilationWithMscorlib(options:=TestOptions.ReleaseDll, sources:= + + +Public Class TestReference1 +End Class +Public Class TestReference2 +End Class +]]> + +) + + Assert.NotNull(compilation1.GetTypeByMetadataName("TestReference1")) + Assert.NotNull(compilation1.GetTypeByMetadataName("TestReference2")) + + Dim compilation2 = CreateCompilationWithMscorlib("", references:={compilation1.EmitToImageReference()}) + + Assert.Null(compilation2.GetTypeByMetadataName("TestReference1")) + Assert.NotNull(compilation2.GetTypeByMetadataName("TestReference2")) + End Sub + End Class End Namespace diff --git a/src/Compilers/VisualBasic/Test/Emit/ErrorHandling.vb b/src/Compilers/VisualBasic/Test/Emit/ErrorHandling.vb index ab10e84c6069b..c43278617d98f 100644 --- a/src/Compilers/VisualBasic/Test/Emit/ErrorHandling.vb +++ b/src/Compilers/VisualBasic/Test/Emit/ErrorHandling.vb @@ -1037,6 +1037,90 @@ End]]>) ]]>) End Sub + + Public Sub SynthesizingDefaultConstructorsWithMsCorLibMissing_Nothing() + Dim comp = CompilationUtils.CreateCompilation(" +Class Test +End Class +", options:=TestOptions.ReleaseDll.WithModuleName("testModule")) + + CompilationUtils.AssertTheseDiagnostics(comp, +BC30002: Type 'System.Void' is not defined. +Class Test +~~~~~~~~~~~ +BC31091: Import of type 'Object' from assembly or module 'testModule' failed. +Class Test + ~~~~ + ) + End Sub + + + Public Sub SynthesizingDefaultConstructorsWithMsCorLibMissing_NoSystemVoid() + Dim comp = CompilationUtils.CreateCompilation(" +Namespace System + Public Class [Object] + End Class +End Namespace +Class Test +End Class +", options:=TestOptions.ReleaseDll.WithModuleName("testModule")) + + CompilationUtils.AssertTheseDiagnostics(comp, +BC30002: Type 'System.Void' is not defined. + Public Class [Object] + ~~~~~~~~~~~~~~~~~~~~~~ +BC30002: Type 'System.Void' is not defined. +Class Test +~~~~~~~~~~~ + ) + End Sub + + + Public Sub SynthesizingDefaultConstructorsWithMsCorLibMissing_NoSystemObject() + Dim comp = CompilationUtils.CreateCompilation(" +Namespace System + Public Class Void + End Class +End Namespace +Class Test +End Class +", options:=TestOptions.ReleaseDll.WithModuleName("testModule")) + + CompilationUtils.AssertTheseDiagnostics(comp, +BC31091: Import of type 'Object' from assembly or module 'testModule' failed. + Public Class Void + ~~~~ +BC31091: Import of type 'Object' from assembly or module 'testModule' failed. +Class Test + ~~~~ +) + End Sub + + + Public Sub SynthesizingDefaultConstructorsWithMsCorLibMissing_NoSystemObjectDefaultConstructor() + Dim comp = CompilationUtils.CreateCompilation(" +Namespace System + Public Class [Object] + Public Sub New(other as Object) + End Sub + End Class + Public Class Void + Public Sub New() + MyBase.New(Nothing) + End Sub + End Class +End Namespace +Class Test +End Class +", options:=TestOptions.ReleaseDll.WithModuleName("testModule")) + + CompilationUtils.AssertTheseDiagnostics(comp, +BC30387: Class 'Test' must declare a 'Sub New' because its base class 'Object' does not have an accessible 'Sub New' that can be called with no arguments. +Class Test + ~~~~ + ) + End Sub + End Class End Namespace diff --git a/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/WellKnownTypeValidationTests.vb b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/WellKnownTypeValidationTests.vb index 057b915517062..3f4d2138aa1ae 100644 --- a/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/WellKnownTypeValidationTests.vb +++ b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/WellKnownTypeValidationTests.vb @@ -508,8 +508,8 @@ End Namespace ' Not a real type Continue For Case WellKnownType.Microsoft_CodeAnalysis_Runtime_Instrumentation, - WellKnownType.System_Runtime_CompilerServices_ReadOnlyAttribute, - WellKnownType.System_Runtime_CompilerServices_IsByRefLikeAttribute + WellKnownType.System_Runtime_CompilerServices_IsReadOnlyAttribute, + WellKnownType.System_Runtime_CompilerServices_IsByRefLikeAttribute ' Not always available. Continue For End Select @@ -545,8 +545,8 @@ End Namespace ' Not a real type Continue For Case WellKnownType.Microsoft_CodeAnalysis_Runtime_Instrumentation, - WellKnownType.System_Runtime_CompilerServices_ReadOnlyAttribute, - WellKnownType.System_Runtime_CompilerServices_IsByRefLikeAttribute + WellKnownType.System_Runtime_CompilerServices_IsReadOnlyAttribute, + WellKnownType.System_Runtime_CompilerServices_IsByRefLikeAttribute ' Not always available. Continue For End Select @@ -585,7 +585,7 @@ End Namespace ' Not available yet, but will be in upcoming release. Continue For Case WellKnownMember.Microsoft_CodeAnalysis_Runtime_Instrumentation__CreatePayload, - WellKnownMember.System_Runtime_CompilerServices_ReadOnlyAttribute__ctor, + WellKnownMember.System_Runtime_CompilerServices_IsReadOnlyAttribute__ctor, WellKnownMember.System_Runtime_CompilerServices_IsByRefLikeAttribute__ctor ' Not always available. Continue For @@ -667,8 +667,8 @@ End Namespace ' Not available yet, but will be in upcoming release. Continue For Case WellKnownMember.Microsoft_CodeAnalysis_Runtime_Instrumentation__CreatePayload, - WellKnownMember.System_Runtime_CompilerServices_ReadOnlyAttribute__ctor, - WellKnownMember.System_Runtime_CompilerServices_IsByRefLikeAttribute__ctor + WellKnownMember.System_Runtime_CompilerServices_IsReadOnlyAttribute__ctor, + WellKnownMember.System_Runtime_CompilerServices_IsByRefLikeAttribute__ctor ' Not always available. Continue For End Select diff --git a/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Symbols/EEMethodSymbol.cs b/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Symbols/EEMethodSymbol.cs index c54d367c413dc..4a0765f98acc5 100644 --- a/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Symbols/EEMethodSymbol.cs +++ b/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Symbols/EEMethodSymbol.cs @@ -7,6 +7,7 @@ using System.Linq; using Microsoft.CodeAnalysis.CodeGen; using Microsoft.CodeAnalysis.Collections; +using Microsoft.CodeAnalysis.CSharp.Emit; using Microsoft.CodeAnalysis.CSharp.Symbols; using Microsoft.CodeAnalysis.ExpressionEvaluator; using Roslyn.Utilities; @@ -692,9 +693,9 @@ private static TypeSymbol CalculateReturnType(CSharpCompilation compilation, Bou } } - internal override void AddSynthesizedReturnTypeAttributes(ref ArrayBuilder attributes) + internal override void AddSynthesizedReturnTypeAttributes(PEModuleBuilder moduleBuilder, ref ArrayBuilder attributes) { - base.AddSynthesizedReturnTypeAttributes(ref attributes); + base.AddSynthesizedReturnTypeAttributes(moduleBuilder, ref attributes); var compilation = this.DeclaringCompilation; var returnType = this.ReturnType; diff --git a/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Symbols/EENamedTypeSymbol.cs b/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Symbols/EENamedTypeSymbol.cs index e75c7ec9cc4b2..14f3dda54bc99 100644 --- a/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Symbols/EENamedTypeSymbol.cs +++ b/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Symbols/EENamedTypeSymbol.cs @@ -333,6 +333,8 @@ internal override bool IsInterface get { return false; } } + internal override bool HasCodeAnalysisEmbeddedAttribute => false; + [Conditional("DEBUG")] internal static void VerifyTypeParameters(Symbol container, ImmutableArray typeParameters) { diff --git a/src/ExpressionEvaluator/CSharp/Test/ExpressionCompiler/ExpressionCompilerTestBase.cs b/src/ExpressionEvaluator/CSharp/Test/ExpressionCompiler/ExpressionCompilerTestBase.cs index 639b05897bf0f..7bea5f0886f94 100644 --- a/src/ExpressionEvaluator/CSharp/Test/ExpressionCompiler/ExpressionCompilerTestBase.cs +++ b/src/ExpressionEvaluator/CSharp/Test/ExpressionCompiler/ExpressionCompilerTestBase.cs @@ -375,7 +375,7 @@ internal static SynthesizedAttributeData GetTupleElementNamesAttributeIfAny(IMet internal static SynthesizedAttributeData GetAttributeIfAny(IMethodSymbol method, string typeName) { - return method.GetSynthesizedAttributes(forReturnType: true). + return ((MethodSymbol)method).GetSynthesizedAttributes(forReturnType: true). Where(a => a.AttributeClass.ToTestDisplayString() == typeName). SingleOrDefault(); } diff --git a/src/ExpressionEvaluator/VisualBasic/Source/ExpressionCompiler/Symbols/EENamedTypeSymbol.vb b/src/ExpressionEvaluator/VisualBasic/Source/ExpressionCompiler/Symbols/EENamedTypeSymbol.vb index cec525f3955d3..f4364a0a17537 100644 --- a/src/ExpressionEvaluator/VisualBasic/Source/ExpressionCompiler/Symbols/EENamedTypeSymbol.vb +++ b/src/ExpressionEvaluator/VisualBasic/Source/ExpressionCompiler/Symbols/EENamedTypeSymbol.vb @@ -321,7 +321,13 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator End Get End Property - Friend Overrides ReadOnly Property HasEmbeddedAttribute As Boolean + Friend Overrides ReadOnly Property HasCodeAnalysisEmbeddedAttribute As Boolean + Get + Return False + End Get + End Property + + Friend Overrides ReadOnly Property HasVisualBasicEmbeddedAttribute As Boolean Get Return False End Get diff --git a/src/ExpressionEvaluator/VisualBasic/Test/ExpressionCompiler/ExpressionCompilerTestBase.vb b/src/ExpressionEvaluator/VisualBasic/Test/ExpressionCompiler/ExpressionCompilerTestBase.vb index 3f7d862f5bf86..b2ff9416d783d 100644 --- a/src/ExpressionEvaluator/VisualBasic/Test/ExpressionCompiler/ExpressionCompilerTestBase.vb +++ b/src/ExpressionEvaluator/VisualBasic/Test/ExpressionCompiler/ExpressionCompilerTestBase.vb @@ -361,7 +361,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator.UnitTests End Function Friend Shared Function GetAttributeIfAny(method As IMethodSymbol, typeName As String) As SynthesizedAttributeData - Return method.GetSynthesizedAttributes(forReturnType:=True). + Return DirectCast(method, MethodSymbol).GetSynthesizedAttributes(forReturnType:=True). Where(Function(a) a.AttributeClass.ToTestDisplayString() = typeName). SingleOrDefault() End Function