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