From b81e291060a518d01f3f33ca03ab3769f81a2673 Mon Sep 17 00:00:00 2001 From: Fredric Silberberg Date: Tue, 3 May 2022 14:39:52 -0700 Subject: [PATCH] Add support for CompilerFeatureRequiredAttribute Adds support for decoding and reporting errors when `CompilerFeatureRequiredAttribute` is encountered on metadata type symbols. We also block applying the attribute by hand in both C# and VB. Test plan: https://github.com/dotnet/roslyn/issues/57046 --- .../CSharp/Portable/CSharpResources.resx | 3 + .../CSharp/Portable/Errors/ErrorCode.cs | 1 + .../Symbols/Metadata/PE/PEEventSymbol.cs | 2 + .../Symbols/Metadata/PE/PEFieldSymbol.cs | 2 + .../Symbols/Metadata/PE/PEMethodSymbol.cs | 23 +- .../Symbols/Metadata/PE/PENamedTypeSymbol.cs | 82 ++- .../Symbols/Metadata/PE/PEParameterSymbol.cs | 18 + .../Symbols/Metadata/PE/PEPropertySymbol.cs | 2 + .../Metadata/PE/PETypeParameterSymbol.cs | 17 + .../Source/SourceTypeParameterSymbol.cs | 6 +- .../CSharp/Portable/Symbols/Symbol.cs | 24 +- .../Portable/xlf/CSharpResources.cs.xlf | 5 + .../Portable/xlf/CSharpResources.de.xlf | 5 + .../Portable/xlf/CSharpResources.es.xlf | 5 + .../Portable/xlf/CSharpResources.fr.xlf | 5 + .../Portable/xlf/CSharpResources.it.xlf | 5 + .../Portable/xlf/CSharpResources.ja.xlf | 5 + .../Portable/xlf/CSharpResources.ko.xlf | 5 + .../Portable/xlf/CSharpResources.pl.xlf | 5 + .../Portable/xlf/CSharpResources.pt-BR.xlf | 5 + .../Portable/xlf/CSharpResources.ru.xlf | 5 + .../Portable/xlf/CSharpResources.tr.xlf | 5 + .../Portable/xlf/CSharpResources.zh-Hans.xlf | 5 + .../Portable/xlf/CSharpResources.zh-Hant.xlf | 5 + .../CSharpCompilerFeatureRequiredTests.cs | 404 +++++++++++ .../Core/Portable/MetadataReader/PEModule.cs | 135 +++- .../Attributes/AttributeDescription.cs | 1 + .../Symbols/CompilerFeatureRequiredHelpers.cs | 77 +++ .../Core/BaseCompilerFeatureRequiredTests.cs | 654 ++++++++++++++++++ .../Test/Utilities/CSharp/CSharpTestBase.cs | 16 + .../VisualBasic/Portable/Errors/Errors.vb | 5 +- .../Symbols/Metadata/PE/PEEventSymbol.vb | 4 +- .../Symbols/Metadata/PE/PEFieldSymbol.vb | 2 + .../Symbols/Metadata/PE/PEMethodSymbol.vb | 32 +- .../Symbols/Metadata/PE/PENamedTypeSymbol.vb | 5 + .../Symbols/Metadata/PE/PEParameterSymbol.vb | 14 + .../Symbols/Metadata/PE/PEPropertySymbol.vb | 4 +- .../Metadata/PE/PETypeParameterSymbol.vb | 17 + .../VisualBasic/Portable/Symbols/Symbol.vb | 13 + .../Portable/Symbols/Symbol_Attributes.vb | 2 + .../VisualBasic/Portable/VBResources.resx | 8 +- .../Portable/xlf/VBResources.cs.xlf | 10 + .../Portable/xlf/VBResources.de.xlf | 10 + .../Portable/xlf/VBResources.es.xlf | 10 + .../Portable/xlf/VBResources.fr.xlf | 10 + .../Portable/xlf/VBResources.it.xlf | 10 + .../Portable/xlf/VBResources.ja.xlf | 10 + .../Portable/xlf/VBResources.ko.xlf | 10 + .../Portable/xlf/VBResources.pl.xlf | 10 + .../Portable/xlf/VBResources.pt-BR.xlf | 10 + .../Portable/xlf/VBResources.ru.xlf | 10 + .../Portable/xlf/VBResources.tr.xlf | 10 + .../Portable/xlf/VBResources.zh-Hans.xlf | 10 + .../Portable/xlf/VBResources.zh-Hant.xlf | 10 + ...VisualBasicCompilerFeatureRequiredTests.vb | 459 ++++++++++++ 55 files changed, 2175 insertions(+), 52 deletions(-) create mode 100644 src/Compilers/CSharp/Test/Symbol/Symbols/CSharpCompilerFeatureRequiredTests.cs create mode 100644 src/Compilers/Core/Portable/Symbols/CompilerFeatureRequiredHelpers.cs create mode 100644 src/Compilers/Test/Core/BaseCompilerFeatureRequiredTests.cs create mode 100644 src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/Metadata/PE/VisualBasicCompilerFeatureRequiredTests.vb diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index 5150812adf15b..0a034fc44db93 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.resx +++ b/src/Compilers/CSharp/Portable/CSharpResources.resx @@ -7130,4 +7130,7 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ unsigned right shift + + '{0}' requires compiler feature '{1}', which is not supported by this version of the C# compiler. + diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs index a14a1a8c37f62..baaabffbeec5e 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs @@ -2087,5 +2087,6 @@ internal enum ErrorCode ERR_RequiredMembersBaseTypeInvalid = 9509, ERR_ChainingToSetsRequiredMembersRequiresSetsRequiredMembers = 9510, ERR_NewConstraintCannotHaveRequiredMembers = 9511, + ERR_UnsupportedCompilerFeature = 9512, } } diff --git a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEEventSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEEventSymbol.cs index af90a53935133..7c40227359d3f 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEEventSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEEventSymbol.cs @@ -5,6 +5,7 @@ using Microsoft.CodeAnalysis.CSharp.DocumentationComments; using Microsoft.CodeAnalysis.CSharp.Emit; using Microsoft.CodeAnalysis.PooledObjects; +using Microsoft.CodeAnalysis.Symbols; using Roslyn.Utilities; using System; using System.Collections.Generic; @@ -468,6 +469,7 @@ internal override UseSiteInfo GetUseSiteInfo() { UseSiteInfo result = new UseSiteInfo(primaryDependency); CalculateUseSiteDiagnostic(ref result); + DeriveUseSiteInfoFromCompilerFeatureRequiredAttributes(ref result, Handle, allowedFeatures: CompilerFeatureRequiredFeatures.None); _lazyCachedUseSiteInfo.Initialize(primaryDependency, result); } diff --git a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEFieldSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEFieldSymbol.cs index db882cdfa270e..6959ad84f7674 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEFieldSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEFieldSymbol.cs @@ -17,6 +17,7 @@ using System.Threading; using Microsoft.CodeAnalysis.CSharp.DocumentationComments; using Microsoft.CodeAnalysis.CSharp.Emit; +using Microsoft.CodeAnalysis.Symbols; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.CSharp.Symbols.Metadata.PE @@ -590,6 +591,7 @@ internal override UseSiteInfo GetUseSiteInfo() { UseSiteInfo result = new UseSiteInfo(primaryDependency); CalculateUseSiteDiagnostic(ref result); + DeriveUseSiteInfoFromCompilerFeatureRequiredAttributes(ref result, Handle, allowedFeatures: CompilerFeatureRequiredFeatures.None); _lazyCachedUseSiteInfo.Initialize(primaryDependency, result); } diff --git a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEMethodSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEMethodSymbol.cs index 6055a69d842ba..8ab10f89cdb81 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEMethodSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEMethodSymbol.cs @@ -16,6 +16,7 @@ using Microsoft.CodeAnalysis.CSharp.DocumentationComments; using Microsoft.CodeAnalysis.CSharp.Emit; using Microsoft.CodeAnalysis.PooledObjects; +using Microsoft.CodeAnalysis.Symbols; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.CSharp.Symbols.Metadata.PE @@ -886,9 +887,17 @@ private ImmutableArray LoadTypeParameters(ref DiagnosticInf else { var ownedParams = ImmutableArray.CreateBuilder(gpHandles.Count); + UseSiteInfo typeParamUseSiteInfo = default; for (int i = 0; i < gpHandles.Count; i++) { - ownedParams.Add(new PETypeParameterSymbol(moduleSymbol, this, (ushort)i, gpHandles[i])); + var typeParam = new PETypeParameterSymbol(moduleSymbol, this, (ushort)i, gpHandles[i]); + ownedParams.Add(typeParam); + MergeUseSiteInfo(ref typeParamUseSiteInfo, typeParam.GetUseSiteInfo()); + } + + if (typeParamUseSiteInfo.DiagnosticInfo != null) + { + diagnosticInfo = typeParamUseSiteInfo.DiagnosticInfo; } return ownedParams.ToImmutable(); @@ -1356,6 +1365,18 @@ internal override UseSiteInfo GetUseSiteInfo() { UseSiteInfo result = new UseSiteInfo(PrimaryDependency); CalculateUseSiteDiagnostic(ref result); + DeriveUseSiteInfoFromCompilerFeatureRequiredAttributes(ref result, Handle, allowedFeatures: MethodKind == MethodKind.Constructor ? CompilerFeatureRequiredFeatures.RequiredMembers : CompilerFeatureRequiredFeatures.None); + + if (result.DiagnosticInfo == null || !IsHighestPriorityUseSiteError(result.DiagnosticInfo)) + { + foreach (var param in Parameters) + { + if (MergeUseSiteInfo(ref result, param.GetUseSiteInfo())) + { + break; + } + } + } var diagnosticInfo = result.DiagnosticInfo; EnsureTypeParametersAreLoaded(ref diagnosticInfo); diff --git a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PENamedTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PENamedTypeSymbol.cs index 31e2a49a854b4..550c4ecbae7af 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PENamedTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PENamedTypeSymbol.cs @@ -19,6 +19,7 @@ using Microsoft.CodeAnalysis.PooledObjects; using Roslyn.Utilities; using System.Reflection.Metadata.Ecma335; +using Microsoft.CodeAnalysis.Symbols; namespace Microsoft.CodeAnalysis.CSharp.Symbols.Metadata.PE { @@ -2016,48 +2017,54 @@ internal override UseSiteInfo GetUseSiteInfo() if (!_lazyCachedUseSiteInfo.IsInitialized) { AssemblySymbol primaryDependency = PrimaryDependency; - _lazyCachedUseSiteInfo.Initialize(primaryDependency, new UseSiteInfo(primaryDependency).AdjustDiagnosticInfo(GetUseSiteDiagnosticImpl())); + var result = new UseSiteInfo(primaryDependency); + GetUseSiteDiagnosticImpl(ref result); + _lazyCachedUseSiteInfo.Initialize(primaryDependency, result); } return _lazyCachedUseSiteInfo.ToUseSiteInfo(PrimaryDependency); } - protected virtual DiagnosticInfo GetUseSiteDiagnosticImpl() + protected virtual void GetUseSiteDiagnosticImpl(ref UseSiteInfo result) { - DiagnosticInfo diagnostic = null; + if (MergeUseSiteInfo(ref result, new UseSiteInfo(CalculateUseSiteDiagnostic()))) + { + return; + } - if (!MergeUseSiteDiagnostics(ref diagnostic, CalculateUseSiteDiagnostic())) + // Check if this type is marked by RequiredAttribute attribute. + // If so mark the type as bad, because it relies upon semantics that are not understood by the C# compiler. + if (this.ContainingPEModule.Module.HasRequiredAttributeAttribute(_handle)) { - // Check if this type is marked by RequiredAttribute attribute. - // If so mark the type as bad, because it relies upon semantics that are not understood by the C# compiler. - if (this.ContainingPEModule.Module.HasRequiredAttributeAttribute(_handle)) - { - diagnostic = new CSDiagnosticInfo(ErrorCode.ERR_BogusType, this); - } - else if (TypeKind == TypeKind.Class && SpecialType != SpecialType.System_Enum) + result = result.AdjustDiagnosticInfo(new CSDiagnosticInfo(ErrorCode.ERR_BogusType, this)); + return; + } + else if (TypeKind == TypeKind.Class && SpecialType != SpecialType.System_Enum) + { + TypeSymbol @base = GetDeclaredBaseType(null); + if (@base?.SpecialType == SpecialType.None && @base.ContainingAssembly?.IsMissing == true) { - TypeSymbol @base = GetDeclaredBaseType(null); - if (@base?.SpecialType == SpecialType.None && @base.ContainingAssembly?.IsMissing == true) + var missingType = @base as MissingMetadataTypeSymbol.TopLevel; + if ((object)missingType != null && missingType.Arity == 0) { - var missingType = @base as MissingMetadataTypeSymbol.TopLevel; - if ((object)missingType != null && missingType.Arity == 0) + string emittedName = MetadataHelpers.BuildQualifiedName(missingType.NamespaceName, missingType.MetadataName); + switch (SpecialTypes.GetTypeFromMetadataName(emittedName)) { - string emittedName = MetadataHelpers.BuildQualifiedName(missingType.NamespaceName, missingType.MetadataName); - switch (SpecialTypes.GetTypeFromMetadataName(emittedName)) - { - case SpecialType.System_Enum: - case SpecialType.System_MulticastDelegate: - case SpecialType.System_ValueType: - // This might be a structure, an enum, or a delegate - diagnostic = missingType.GetUseSiteInfo().DiagnosticInfo; - break; - } + case SpecialType.System_Enum: + case SpecialType.System_MulticastDelegate: + case SpecialType.System_ValueType: + // This might be a structure, an enum, or a delegate + if (MergeUseSiteInfo(ref result, missingType.GetUseSiteInfo())) + { + return; + } + break; } } } } - return diagnostic; + DeriveUseSiteInfoFromCompilerFeatureRequiredAttributes(ref result, Handle, allowedFeatures: IsRefLikeType ? CompilerFeatureRequiredFeatures.RefStructs : CompilerFeatureRequiredFeatures.None); } internal string DefaultMemberName @@ -2515,21 +2522,28 @@ private void EnsureTypeParametersAreLoaded() } } - protected override DiagnosticInfo GetUseSiteDiagnosticImpl() + protected override void GetUseSiteDiagnosticImpl(ref UseSiteInfo result) { - DiagnosticInfo diagnostic = null; + base.GetUseSiteDiagnosticImpl(ref result); + if (result.DiagnosticInfo != null && IsHighestPriorityUseSiteError(result.DiagnosticInfo)) + { + return; + } - if (!MergeUseSiteDiagnostics(ref diagnostic, base.GetUseSiteDiagnosticImpl())) + foreach (var typeParameter in this.TypeParameters) { - // Verify type parameters for containing types - // match those on the containing types. - if (!MatchesContainingTypeParameters()) + if (MergeUseSiteInfo(ref result, typeParameter.GetUseSiteInfo())) { - diagnostic = new CSDiagnosticInfo(ErrorCode.ERR_BogusType, this); + return; } } - return diagnostic; + // Verify type parameters for containing types + // match those on the containing types. + if (!MatchesContainingTypeParameters()) + { + result = result.AdjustDiagnosticInfo(new CSDiagnosticInfo(ErrorCode.ERR_BogusType, this)); + } } /// diff --git a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEParameterSymbol.cs index 1a0280d0473e5..83510c8df8340 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEParameterSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEParameterSymbol.cs @@ -14,6 +14,7 @@ using System.Threading; using Microsoft.CodeAnalysis.CSharp.Emit; using Microsoft.CodeAnalysis.PooledObjects; +using Microsoft.CodeAnalysis.Symbols; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.CSharp.Symbols.Metadata.PE @@ -160,6 +161,8 @@ public bool TryGetFlowAnalysisAnnotations(out FlowAnalysisAnnotations value) private PackedFlags _packedFlags; + private CachedUseSiteInfo _lazyCachedUseSiteInfo = CachedUseSiteInfo.Uninitialized; + internal static PEParameterSymbol Create( PEModuleSymbol moduleSymbol, PEMethodSymbol containingSymbol, @@ -1068,5 +1071,20 @@ public sealed override bool Equals(Symbol other, TypeCompareKind compareKind) nps.Equals(this, compareKind) : base.Equals(other, compareKind); } + +#nullable enable + internal override UseSiteInfo GetUseSiteInfo() + { + AssemblySymbol primaryDependency = PrimaryDependency; + + if (!_lazyCachedUseSiteInfo.IsInitialized) + { + UseSiteInfo result = new UseSiteInfo(primaryDependency); + DeriveUseSiteInfoFromCompilerFeatureRequiredAttributes(ref result, Handle, allowedFeatures: CompilerFeatureRequiredFeatures.None); + _lazyCachedUseSiteInfo.Initialize(primaryDependency, result); + } + + return _lazyCachedUseSiteInfo.ToUseSiteInfo(primaryDependency); + } } } diff --git a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEPropertySymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEPropertySymbol.cs index 26238a22178f2..70fa138a9afe1 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEPropertySymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEPropertySymbol.cs @@ -17,6 +17,7 @@ using Microsoft.CodeAnalysis.CSharp.DocumentationComments; using Microsoft.CodeAnalysis.CSharp.Emit; using Microsoft.CodeAnalysis.PooledObjects; +using Microsoft.CodeAnalysis.Symbols; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.CSharp.Symbols.Metadata.PE @@ -784,6 +785,7 @@ internal override UseSiteInfo GetUseSiteInfo() { var result = new UseSiteInfo(primaryDependency); CalculateUseSiteDiagnostic(ref result); + DeriveUseSiteInfoFromCompilerFeatureRequiredAttributes(ref result, Handle, allowedFeatures: CompilerFeatureRequiredFeatures.None); _lazyCachedUseSiteInfo.Initialize(primaryDependency, result); } diff --git a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PETypeParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PETypeParameterSymbol.cs index 9c1cd3c683066..7515a74c0be9a 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PETypeParameterSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PETypeParameterSymbol.cs @@ -13,6 +13,7 @@ using System.Reflection.Metadata.Ecma335; using System.Threading; using Microsoft.CodeAnalysis.PooledObjects; +using Microsoft.CodeAnalysis.Symbols; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.CSharp.Symbols.Metadata.PE @@ -42,6 +43,7 @@ internal sealed class PETypeParameterSymbol private TypeParameterBounds _lazyBounds = TypeParameterBounds.Unset; private ImmutableArray _lazyDeclaredConstraintTypes; private ImmutableArray _lazyCustomAttributes; + private CachedUseSiteInfo _lazyCachedUseSiteInfo = CachedUseSiteInfo.Uninitialized; internal PETypeParameterSymbol( PEModuleSymbol moduleSymbol, @@ -705,5 +707,20 @@ private NamedTypeSymbol GetDefaultBaseType() { get { return null; } } + +#nullable enable + internal override UseSiteInfo GetUseSiteInfo() + { + AssemblySymbol primaryDependency = PrimaryDependency; + + if (!_lazyCachedUseSiteInfo.IsInitialized) + { + UseSiteInfo result = new UseSiteInfo(primaryDependency); + DeriveUseSiteInfoFromCompilerFeatureRequiredAttributes(ref result, Handle, allowedFeatures: CompilerFeatureRequiredFeatures.None); + _lazyCachedUseSiteInfo.Initialize(primaryDependency, result); + } + + return _lazyCachedUseSiteInfo.ToUseSiteInfo(primaryDependency); + } } } diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceTypeParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceTypeParameterSymbol.cs index 7ae3bfd1e8c50..481baeb9b71bd 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceTypeParameterSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceTypeParameterSymbol.cs @@ -424,11 +424,7 @@ internal sealed override void DecodeWellKnownAttribute(ref DecodeWellKnownAttrib Debug.Assert(!attribute.HasErrors); Debug.Assert(arguments.SymbolPart == AttributeLocation.None); - if (attribute.IsTargetAttribute(this, AttributeDescription.NullableAttribute)) - { - // NullableAttribute should not be set explicitly. - ((BindingDiagnosticBag)arguments.Diagnostics).Add(ErrorCode.ERR_ExplicitNullableAttribute, arguments.AttributeSyntaxOpt.Location); - } + ReportExplicitUseOfReservedAttributes(in arguments, ReservedAttributes.NullableAttribute); base.DecodeWellKnownAttribute(ref arguments); } diff --git a/src/Compilers/CSharp/Portable/Symbols/Symbol.cs b/src/Compilers/CSharp/Portable/Symbols/Symbol.cs index 5ba4063944be3..262a9f67c1b19 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Symbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Symbol.cs @@ -987,7 +987,7 @@ internal bool MergeUseSiteDiagnostics(ref DiagnosticInfo result, DiagnosticInfo return false; } - if (info.Severity == DiagnosticSeverity.Error && (info.Code == HighestPriorityUseSiteError || HighestPriorityUseSiteError == Int32.MaxValue)) + if (IsHighestPriorityUseSiteError(info)) { // this error is final, no other error can override it: result = info; @@ -1005,6 +1005,10 @@ internal bool MergeUseSiteDiagnostics(ref DiagnosticInfo result, DiagnosticInfo return false; } + protected bool IsHighestPriorityUseSiteError(DiagnosticInfo info) + => info.Severity == DiagnosticSeverity.Error + && (info.Code == HighestPriorityUseSiteError || HighestPriorityUseSiteError == int.MaxValue); + /// /// Merges given diagnostic and dependencies to the existing result. /// @@ -1122,7 +1126,6 @@ internal bool DeriveUseSiteInfoFromParameters(ref UseSiteInfo re return false; } - [Flags] internal enum AllowedRequiredModifierType { @@ -1196,6 +1199,18 @@ internal bool DeriveUseSiteInfoFromCustomModifiers(ref UseSiteInfo result, System.Reflection.Metadata.EntityHandle handle, CompilerFeatureRequiredFeatures allowedFeatures) + { + string? disallowedFeature = CompilerFeatureRequiredHelpers.GetUnsupportedCompilerFeature(handle, ((PEModuleSymbol)this.ContainingModule).Module, allowedFeatures); + if (disallowedFeature != null) + { + // '{0}' requires compiler feature '{1}', which is not supported by this version of the C# compiler. + result = result.AdjustDiagnosticInfo(new CSDiagnosticInfo(ErrorCode.ERR_UnsupportedCompilerFeature, this, disallowedFeature)); + } + } +#nullable disable + internal static bool GetUnificationUseSiteDiagnosticRecursive(ref DiagnosticInfo result, ImmutableArray types, Symbol owner, ref HashSet checkedTypes) where T : TypeSymbol { foreach (var t in types) @@ -1445,6 +1460,11 @@ internal bool ReportExplicitUseOfReservedAttributes(in DecodeWellKnownAttributeA // Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. diagnostics.Add(ErrorCode.ERR_ExplicitRequiredMember, arguments.AttributeSyntaxOpt.Location); } + else if (attribute.IsTargetAttribute(this, AttributeDescription.CompilerFeatureRequiredAttribute)) + { + // This is always disallowed, so we don't bother with a flag. + reportExplicitUseOfReservedAttribute(attribute, arguments, AttributeDescription.CompilerFeatureRequiredAttribute); + } else { return false; diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf index 75671ed63c549..b9272c012f189 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf @@ -1452,6 +1452,11 @@ {0} má atribut UnmanagedCallersOnly a nedá se převést na typ delegáta. Pro tuto metodu získejte ukazatel na funkci. UnmanagedCallersOnly is not localizable. + + '{0}' requires compiler feature '{1}', which is not supported by this version of the C# compiler. + '{0}' requires compiler feature '{1}', which is not supported by this version of the C# compiler. + + List patterns may not be used for a value of type '{0}'. Vzory seznamů se nedají používat pro hodnotu typu {0}. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf index 342cd973aed8b..6e6bf84b02a0a 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf @@ -1452,6 +1452,11 @@ "{0}" ist mit dem Attribut "UnmanagedCallersOnly" versehen und kann nicht in einen Delegattyp konvertiert werden. Rufen Sie einen Funktionszeiger auf diese Methode ab. UnmanagedCallersOnly is not localizable. + + '{0}' requires compiler feature '{1}', which is not supported by this version of the C# compiler. + '{0}' requires compiler feature '{1}', which is not supported by this version of the C# compiler. + + List patterns may not be used for a value of type '{0}'. Listenmuster dürfen nicht für einen Wert vom Typ „{0}“ verwendet werden. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf index 10b171ae10672..ec3f6699f869b 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf @@ -1452,6 +1452,11 @@ ' {0} ' tiene un atributo ' UnmanagedCallersOnly ' y no se puede convertir en un tipo de delegado. Obtenga un puntero de función a este método. UnmanagedCallersOnly is not localizable. + + '{0}' requires compiler feature '{1}', which is not supported by this version of the C# compiler. + '{0}' requires compiler feature '{1}', which is not supported by this version of the C# compiler. + + List patterns may not be used for a value of type '{0}'. No se pueden utilizar patrones de lista para un valor de tipo "{0}". diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf index 5fde23300df40..32398d2d6b308 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf @@ -1452,6 +1452,11 @@ '{0}' est attribué avec 'UnmanagedCallersOnly' et ne peut pas être converti en type délégué. Obtenez un pointeur de fonction vers cette méthode. UnmanagedCallersOnly is not localizable. + + '{0}' requires compiler feature '{1}', which is not supported by this version of the C# compiler. + '{0}' requires compiler feature '{1}', which is not supported by this version of the C# compiler. + + List patterns may not be used for a value of type '{0}'. Les modèles de liste ne peuvent pas être utilisés pour une valeur de type '{0}'. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf index 863af695b52db..c60638e6729b2 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf @@ -1452,6 +1452,11 @@ '{0}', a cui è assegnato l'attributo 'UnmanagedCallersOnly', non può essere convertito in un tipo delegato. Ottenere un puntatore a funzione per questo metodo. UnmanagedCallersOnly is not localizable. + + '{0}' requires compiler feature '{1}', which is not supported by this version of the C# compiler. + '{0}' requires compiler feature '{1}', which is not supported by this version of the C# compiler. + + List patterns may not be used for a value of type '{0}'. Non è possibile usare i modelli di elenco per un valore di tipo '{0}'. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf index 3f65bd09d8af1..1dd8859b4655f 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf @@ -1452,6 +1452,11 @@ '{0}' は 'UnmanagedCallersOnly' 属性が設定されているため、デリゲート型に変換できません。このメソッドへの関数ポインターを取得してください。 UnmanagedCallersOnly is not localizable. + + '{0}' requires compiler feature '{1}', which is not supported by this version of the C# compiler. + '{0}' requires compiler feature '{1}', which is not supported by this version of the C# compiler. + + List patterns may not be used for a value of type '{0}'. リスト パターンは、'{0}' 型の値に使用されない可能性があります。 diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf index 09ab26188d046..6801ed9bffcac 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf @@ -1452,6 +1452,11 @@ '{0}'에는 'UnmanagedCallersOnly' 특성이 지정되어 있으며 이 항목은 대리자 형식으로 변환할 수 없습니다. 이 메서드에 대한 함수 포인터를 가져오세요. UnmanagedCallersOnly is not localizable. + + '{0}' requires compiler feature '{1}', which is not supported by this version of the C# compiler. + '{0}' requires compiler feature '{1}', which is not supported by this version of the C# compiler. + + List patterns may not be used for a value of type '{0}'. 목록 패턴은 '{0}' 형식 값에 사용할 수 없습니다. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf index 54701481b7493..67e5320bf3c32 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf @@ -1452,6 +1452,11 @@ Element „{0}” ma atrybut „UnmanagedCallersOnly” i nie można go przekonwertować na typ delegowany. Uzyskaj wskaźnik funkcji do tej metody. UnmanagedCallersOnly is not localizable. + + '{0}' requires compiler feature '{1}', which is not supported by this version of the C# compiler. + '{0}' requires compiler feature '{1}', which is not supported by this version of the C# compiler. + + List patterns may not be used for a value of type '{0}'. Wzorców list nie można używać na potrzeby wartości typu „{0}”. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf index e03a31ea48f9b..668fd62e320ad 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf @@ -1452,6 +1452,11 @@ '{0}' foi atribuído com 'UnmanagedCallersOnly' e não pode ser convertido em um tipo delegado. Obtenha um ponteiro de função para esse método. UnmanagedCallersOnly is not localizable. + + '{0}' requires compiler feature '{1}', which is not supported by this version of the C# compiler. + '{0}' requires compiler feature '{1}', which is not supported by this version of the C# compiler. + + List patterns may not be used for a value of type '{0}'. Os padrões de lista não podem ser usados para um valor do tipo '{0}'. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf index d421725d76999..419592cf6ec6b 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf @@ -1452,6 +1452,11 @@ "{0}" имеет атрибут "UnmanagedCallersOnly" и не может быть преобразован в тип делегата. Получите указатель на функцию для этого метода. UnmanagedCallersOnly is not localizable. + + '{0}' requires compiler feature '{1}', which is not supported by this version of the C# compiler. + '{0}' requires compiler feature '{1}', which is not supported by this version of the C# compiler. + + List patterns may not be used for a value of type '{0}'. Шаблоны списка не могут использоваться для значений типа "{0}". diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf index bc7160209c1d8..68a96ab9a4bc1 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf @@ -1452,6 +1452,11 @@ '{0}', 'UnmanagedCallersOnly' özniteliğine sahip ve temsilci türüne dönüştürülemez. Bu yöntem için bir işlev işaretçisi edinin. UnmanagedCallersOnly is not localizable. + + '{0}' requires compiler feature '{1}', which is not supported by this version of the C# compiler. + '{0}' requires compiler feature '{1}', which is not supported by this version of the C# compiler. + + List patterns may not be used for a value of type '{0}'. Liste desenleri, '{0}' türünde bir değer için kullanılamaz. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf index a024159a37137..cd629ba992b15 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf @@ -1452,6 +1452,11 @@ “{0}”使用 "UnmanagedCallersOnly" 进行特性化,无法转换为委托类型。请获取指向此方法的函数指针。 UnmanagedCallersOnly is not localizable. + + '{0}' requires compiler feature '{1}', which is not supported by this version of the C# compiler. + '{0}' requires compiler feature '{1}', which is not supported by this version of the C# compiler. + + List patterns may not be used for a value of type '{0}'. 列表模式不能用于类型为“{0}”的值。 diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf index f9fb37b9f8b87..65685a7afa471 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf @@ -1452,6 +1452,11 @@ '{0}' 使用 'UnmanagedCallersOnly' 屬性化,因此無法轉換為委派類型。取得此方法的函式指標。 UnmanagedCallersOnly is not localizable. + + '{0}' requires compiler feature '{1}', which is not supported by this version of the C# compiler. + '{0}' requires compiler feature '{1}', which is not supported by this version of the C# compiler. + + List patterns may not be used for a value of type '{0}'. 類型 '{0}' 的值不可使用清單模式。 diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/CSharpCompilerFeatureRequiredTests.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/CSharpCompilerFeatureRequiredTests.cs new file mode 100644 index 0000000000000..21dd0aa65a21c --- /dev/null +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/CSharpCompilerFeatureRequiredTests.cs @@ -0,0 +1,404 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using Microsoft.CodeAnalysis.CodeGen; +using Microsoft.CodeAnalysis.CSharp.Test.Utilities; +using Microsoft.CodeAnalysis.Test.Utilities; +using Xunit; + +namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Symbols; + +public class CSharpCompilerFeatureRequiredTests : BaseCompilerFeatureRequiredTests +{ + private class CompilerFeatureRequiredTests_CSharp : CSharpTestBase { } + + private readonly CompilerFeatureRequiredTests_CSharp _csharpTest = new CompilerFeatureRequiredTests_CSharp(); + + protected override CSharpTestSource GetUsage() => """ + #pragma warning disable 168 // Unused local + OnType onType; + OnMethod.M(); + OnMethodReturn.M(); + OnParameter.M(1); + _ = OnField.Field; + OnProperty.Property = 1; + _ = OnProperty.Property; + OnPropertySetter.Property = 1; + _ = OnPropertySetter.Property; + OnPropertyGetter.Property = 1; + _ = OnPropertyGetter.Property; + OnEvent.Event += () => {}; + OnEvent.Event -= () => {}; + OnEventAdder.Event += () => {}; + OnEventAdder.Event -= () => {}; + OnEventRemover.Event += () => {}; + OnEventRemover.Event -= () => {}; + OnEnum onEnum; + _ = OnEnumMember.A; + OnClassTypeParameter onClassTypeParameter; + OnMethodTypeParameter.M(); + OnDelegateType onDelegateType; + OnIndexedPropertyParameter.set_Property(1, 1); + _ = OnIndexedPropertyParameter.get_Property(1); + """; + + internal override string VisualizeRealIL(IModuleSymbol peModule, CompilationTestData.MethodData methodData, IReadOnlyDictionary markers, bool areLocalsZeroed) + { + return _csharpTest.VisualizeRealIL(peModule, methodData, markers, areLocalsZeroed); + } + + protected override CSharpCompilation CreateCompilationWithIL(CSharpTestSource source, string ilSource) + { + return CSharpTestBase.CreateCompilationWithIL(source, ilSource); + } + + protected override CSharpCompilation CreateCompilation(CSharpTestSource source, MetadataReference[] references) + { + return CSharpTestBase.CreateCompilation(source, references); + } + + protected override CompilationVerifier CompileAndVerify(CSharpCompilation compilation) + { + return _csharpTest.CompileAndVerify(compilation); + } + + protected override void AssertNormalErrors(CSharpCompilation comp) + { + comp.VerifyDiagnostics( + // (2,1): error CS9512: 'OnType' requires compiler feature 'test', which is not supported by this version of the C# compiler. + // OnType onType; + Diagnostic(ErrorCode.ERR_UnsupportedCompilerFeature, "OnType").WithArguments("OnType", "test").WithLocation(2, 1), + // (3,1): error CS9512: 'OnMethod.M()' requires compiler feature 'test', which is not supported by this version of the C# compiler. + // OnMethod.M(); + Diagnostic(ErrorCode.ERR_UnsupportedCompilerFeature, "OnMethod.M").WithArguments("OnMethod.M()", "test").WithLocation(3, 1), + // (5,1): error CS9512: 'int' requires compiler feature 'test', which is not supported by this version of the C# compiler. + // OnParameter.M(1); + Diagnostic(ErrorCode.ERR_UnsupportedCompilerFeature, "OnParameter.M").WithArguments("int", "test").WithLocation(5, 1), + // (6,13): error CS9512: 'OnField.Field' requires compiler feature 'test', which is not supported by this version of the C# compiler. + // _ = OnField.Field; + Diagnostic(ErrorCode.ERR_UnsupportedCompilerFeature, "Field").WithArguments("OnField.Field", "test").WithLocation(6, 13), + // (7,12): error CS9512: 'OnProperty.Property' requires compiler feature 'test', which is not supported by this version of the C# compiler. + // OnProperty.Property = 1; + Diagnostic(ErrorCode.ERR_UnsupportedCompilerFeature, "Property").WithArguments("OnProperty.Property", "test").WithLocation(7, 12), + // (8,16): error CS9512: 'OnProperty.Property' requires compiler feature 'test', which is not supported by this version of the C# compiler. + // _ = OnProperty.Property; + Diagnostic(ErrorCode.ERR_UnsupportedCompilerFeature, "Property").WithArguments("OnProperty.Property", "test").WithLocation(8, 16), + // (9,18): error CS9512: 'OnPropertySetter.Property.set' requires compiler feature 'test', which is not supported by this version of the C# compiler. + // OnPropertySetter.Property = 1; + Diagnostic(ErrorCode.ERR_UnsupportedCompilerFeature, "Property").WithArguments("OnPropertySetter.Property.set", "test").WithLocation(9, 18), + // (12,22): error CS9512: 'OnPropertyGetter.Property.get' requires compiler feature 'test', which is not supported by this version of the C# compiler. + // _ = OnPropertyGetter.Property; + Diagnostic(ErrorCode.ERR_UnsupportedCompilerFeature, "Property").WithArguments("OnPropertyGetter.Property.get", "test").WithLocation(12, 22), + // (13,9): error CS9512: 'OnEvent.Event' requires compiler feature 'test', which is not supported by this version of the C# compiler. + // OnEvent.Event += () => {}; + Diagnostic(ErrorCode.ERR_UnsupportedCompilerFeature, "Event").WithArguments("OnEvent.Event", "test").WithLocation(13, 9), + // (14,9): error CS9512: 'OnEvent.Event' requires compiler feature 'test', which is not supported by this version of the C# compiler. + // OnEvent.Event -= () => {}; + Diagnostic(ErrorCode.ERR_UnsupportedCompilerFeature, "Event").WithArguments("OnEvent.Event", "test").WithLocation(14, 9), + // (19,1): error CS9512: 'OnEnum' requires compiler feature 'test', which is not supported by this version of the C# compiler. + // OnEnum onEnum; + Diagnostic(ErrorCode.ERR_UnsupportedCompilerFeature, "OnEnum").WithArguments("OnEnum", "test").WithLocation(19, 1), + // (20,18): error CS9512: 'OnEnumMember.A' requires compiler feature 'test', which is not supported by this version of the C# compiler. + // _ = OnEnumMember.A; + Diagnostic(ErrorCode.ERR_UnsupportedCompilerFeature, "A").WithArguments("OnEnumMember.A", "test").WithLocation(20, 18), + // (21,1): error CS9512: 'T' requires compiler feature 'test', which is not supported by this version of the C# compiler. + // OnClassTypeParameter onClassTypeParameter; + Diagnostic(ErrorCode.ERR_UnsupportedCompilerFeature, "OnClassTypeParameter").WithArguments("T", "test").WithLocation(21, 1), + // (22,1): error CS9512: 'T' requires compiler feature 'test', which is not supported by this version of the C# compiler. + // OnMethodTypeParameter.M(); + Diagnostic(ErrorCode.ERR_UnsupportedCompilerFeature, "OnMethodTypeParameter.M").WithArguments("T", "test").WithLocation(22, 1), + // (23,1): error CS9512: 'OnDelegateType' requires compiler feature 'test', which is not supported by this version of the C# compiler. + // OnDelegateType onDelegateType; + Diagnostic(ErrorCode.ERR_UnsupportedCompilerFeature, "OnDelegateType").WithArguments("OnDelegateType", "test").WithLocation(23, 1), + // (24,1): error CS9512: 'int' requires compiler feature 'test', which is not supported by this version of the C# compiler. + // OnIndexedPropertyParameter.set_Property(1, 1); + Diagnostic(ErrorCode.ERR_UnsupportedCompilerFeature, "OnIndexedPropertyParameter.set_Property").WithArguments("int", "test").WithLocation(24, 1), + // (25,5): error CS9512: 'int' requires compiler feature 'test', which is not supported by this version of the C# compiler. + // _ = OnIndexedPropertyParameter.get_Property(1); + Diagnostic(ErrorCode.ERR_UnsupportedCompilerFeature, "OnIndexedPropertyParameter.get_Property").WithArguments("int", "test").WithLocation(25, 5) + ); + } + + protected override void AssertModuleAndAssemblyErrors(CSharpCompilation comp) + { + comp.VerifyDiagnostics( + // (2,1): error CS9512: 'OnType' requires compiler feature 'test', which is not supported by this version of the C# compiler. + // OnType onType; + Diagnostic(ErrorCode.ERR_UnsupportedCompilerFeature, "OnType").WithArguments("OnType", "test").WithLocation(2, 1), + // (3,1): error CS9512: 'OnMethod' requires compiler feature 'test', which is not supported by this version of the C# compiler. + // OnMethod.M(); + Diagnostic(ErrorCode.ERR_UnsupportedCompilerFeature, "OnMethod").WithArguments("OnMethod", "test").WithLocation(3, 1), + // (3,1): error CS9512: 'OnMethod.M()' requires compiler feature 'test', which is not supported by this version of the C# compiler. + // OnMethod.M(); + Diagnostic(ErrorCode.ERR_UnsupportedCompilerFeature, "OnMethod.M").WithArguments("OnMethod.M()", "test").WithLocation(3, 1), + // (4,1): error CS9512: 'OnMethodReturn' requires compiler feature 'test', which is not supported by this version of the C# compiler. + // OnMethodReturn.M(); + Diagnostic(ErrorCode.ERR_UnsupportedCompilerFeature, "OnMethodReturn").WithArguments("OnMethodReturn", "test").WithLocation(4, 1), + // (4,1): error CS9512: 'OnMethodReturn.M()' requires compiler feature 'test', which is not supported by this version of the C# compiler. + // OnMethodReturn.M(); + Diagnostic(ErrorCode.ERR_UnsupportedCompilerFeature, "OnMethodReturn.M").WithArguments("OnMethodReturn.M()", "test").WithLocation(4, 1), + // (5,1): error CS9512: 'OnParameter' requires compiler feature 'test', which is not supported by this version of the C# compiler. + // OnParameter.M(1); + Diagnostic(ErrorCode.ERR_UnsupportedCompilerFeature, "OnParameter").WithArguments("OnParameter", "test").WithLocation(5, 1), + // (5,1): error CS9512: 'OnParameter.M(int)' requires compiler feature 'test', which is not supported by this version of the C# compiler. + // OnParameter.M(1); + Diagnostic(ErrorCode.ERR_UnsupportedCompilerFeature, "OnParameter.M").WithArguments("OnParameter.M(int)", "test").WithLocation(5, 1), + // (6,5): error CS9512: 'OnField' requires compiler feature 'test', which is not supported by this version of the C# compiler. + // _ = OnField.Field; + Diagnostic(ErrorCode.ERR_UnsupportedCompilerFeature, "OnField").WithArguments("OnField", "test").WithLocation(6, 5), + // (6,13): error CS9512: 'OnField.Field' requires compiler feature 'test', which is not supported by this version of the C# compiler. + // _ = OnField.Field; + Diagnostic(ErrorCode.ERR_UnsupportedCompilerFeature, "Field").WithArguments("OnField.Field", "test").WithLocation(6, 13), + // (7,1): error CS9512: 'OnProperty' requires compiler feature 'test', which is not supported by this version of the C# compiler. + // OnProperty.Property = 1; + Diagnostic(ErrorCode.ERR_UnsupportedCompilerFeature, "OnProperty").WithArguments("OnProperty", "test").WithLocation(7, 1), + // (7,12): error CS9512: 'OnProperty.Property' requires compiler feature 'test', which is not supported by this version of the C# compiler. + // OnProperty.Property = 1; + Diagnostic(ErrorCode.ERR_UnsupportedCompilerFeature, "Property").WithArguments("OnProperty.Property", "test").WithLocation(7, 12), + // (8,5): error CS9512: 'OnProperty' requires compiler feature 'test', which is not supported by this version of the C# compiler. + // _ = OnProperty.Property; + Diagnostic(ErrorCode.ERR_UnsupportedCompilerFeature, "OnProperty").WithArguments("OnProperty", "test").WithLocation(8, 5), + // (8,16): error CS9512: 'OnProperty.Property' requires compiler feature 'test', which is not supported by this version of the C# compiler. + // _ = OnProperty.Property; + Diagnostic(ErrorCode.ERR_UnsupportedCompilerFeature, "Property").WithArguments("OnProperty.Property", "test").WithLocation(8, 16), + // (9,1): error CS9512: 'OnPropertySetter' requires compiler feature 'test', which is not supported by this version of the C# compiler. + // OnPropertySetter.Property = 1; + Diagnostic(ErrorCode.ERR_UnsupportedCompilerFeature, "OnPropertySetter").WithArguments("OnPropertySetter", "test").WithLocation(9, 1), + // (9,18): error CS9512: 'OnPropertySetter.Property' requires compiler feature 'test', which is not supported by this version of the C# compiler. + // OnPropertySetter.Property = 1; + Diagnostic(ErrorCode.ERR_UnsupportedCompilerFeature, "Property").WithArguments("OnPropertySetter.Property", "test").WithLocation(9, 18), + // (10,5): error CS9512: 'OnPropertySetter' requires compiler feature 'test', which is not supported by this version of the C# compiler. + // _ = OnPropertySetter.Property; + Diagnostic(ErrorCode.ERR_UnsupportedCompilerFeature, "OnPropertySetter").WithArguments("OnPropertySetter", "test").WithLocation(10, 5), + // (10,22): error CS9512: 'OnPropertySetter.Property' requires compiler feature 'test', which is not supported by this version of the C# compiler. + // _ = OnPropertySetter.Property; + Diagnostic(ErrorCode.ERR_UnsupportedCompilerFeature, "Property").WithArguments("OnPropertySetter.Property", "test").WithLocation(10, 22), + // (11,1): error CS9512: 'OnPropertyGetter' requires compiler feature 'test', which is not supported by this version of the C# compiler. + // OnPropertyGetter.Property = 1; + Diagnostic(ErrorCode.ERR_UnsupportedCompilerFeature, "OnPropertyGetter").WithArguments("OnPropertyGetter", "test").WithLocation(11, 1), + // (11,18): error CS9512: 'OnPropertyGetter.Property' requires compiler feature 'test', which is not supported by this version of the C# compiler. + // OnPropertyGetter.Property = 1; + Diagnostic(ErrorCode.ERR_UnsupportedCompilerFeature, "Property").WithArguments("OnPropertyGetter.Property", "test").WithLocation(11, 18), + // (12,5): error CS9512: 'OnPropertyGetter' requires compiler feature 'test', which is not supported by this version of the C# compiler. + // _ = OnPropertyGetter.Property; + Diagnostic(ErrorCode.ERR_UnsupportedCompilerFeature, "OnPropertyGetter").WithArguments("OnPropertyGetter", "test").WithLocation(12, 5), + // (12,22): error CS9512: 'OnPropertyGetter.Property' requires compiler feature 'test', which is not supported by this version of the C# compiler. + // _ = OnPropertyGetter.Property; + Diagnostic(ErrorCode.ERR_UnsupportedCompilerFeature, "Property").WithArguments("OnPropertyGetter.Property", "test").WithLocation(12, 22), + // (13,1): error CS9512: 'OnEvent' requires compiler feature 'test', which is not supported by this version of the C# compiler. + // OnEvent.Event += () => {}; + Diagnostic(ErrorCode.ERR_UnsupportedCompilerFeature, "OnEvent").WithArguments("OnEvent", "test").WithLocation(13, 1), + // (13,9): error CS9512: 'OnEvent.Event' requires compiler feature 'test', which is not supported by this version of the C# compiler. + // OnEvent.Event += () => {}; + Diagnostic(ErrorCode.ERR_UnsupportedCompilerFeature, "Event").WithArguments("OnEvent.Event", "test").WithLocation(13, 9), + // (14,1): error CS9512: 'OnEvent' requires compiler feature 'test', which is not supported by this version of the C# compiler. + // OnEvent.Event -= () => {}; + Diagnostic(ErrorCode.ERR_UnsupportedCompilerFeature, "OnEvent").WithArguments("OnEvent", "test").WithLocation(14, 1), + // (14,9): error CS9512: 'OnEvent.Event' requires compiler feature 'test', which is not supported by this version of the C# compiler. + // OnEvent.Event -= () => {}; + Diagnostic(ErrorCode.ERR_UnsupportedCompilerFeature, "Event").WithArguments("OnEvent.Event", "test").WithLocation(14, 9), + // (15,1): error CS9512: 'OnEventAdder' requires compiler feature 'test', which is not supported by this version of the C# compiler. + // OnEventAdder.Event += () => {}; + Diagnostic(ErrorCode.ERR_UnsupportedCompilerFeature, "OnEventAdder").WithArguments("OnEventAdder", "test").WithLocation(15, 1), + // (15,14): error CS9512: 'OnEventAdder.Event' requires compiler feature 'test', which is not supported by this version of the C# compiler. + // OnEventAdder.Event += () => {}; + Diagnostic(ErrorCode.ERR_UnsupportedCompilerFeature, "Event").WithArguments("OnEventAdder.Event", "test").WithLocation(15, 14), + // (16,1): error CS9512: 'OnEventAdder' requires compiler feature 'test', which is not supported by this version of the C# compiler. + // OnEventAdder.Event -= () => {}; + Diagnostic(ErrorCode.ERR_UnsupportedCompilerFeature, "OnEventAdder").WithArguments("OnEventAdder", "test").WithLocation(16, 1), + // (16,14): error CS9512: 'OnEventAdder.Event' requires compiler feature 'test', which is not supported by this version of the C# compiler. + // OnEventAdder.Event -= () => {}; + Diagnostic(ErrorCode.ERR_UnsupportedCompilerFeature, "Event").WithArguments("OnEventAdder.Event", "test").WithLocation(16, 14), + // (17,1): error CS9512: 'OnEventRemover' requires compiler feature 'test', which is not supported by this version of the C# compiler. + // OnEventRemover.Event += () => {}; + Diagnostic(ErrorCode.ERR_UnsupportedCompilerFeature, "OnEventRemover").WithArguments("OnEventRemover", "test").WithLocation(17, 1), + // (17,16): error CS9512: 'OnEventRemover.Event' requires compiler feature 'test', which is not supported by this version of the C# compiler. + // OnEventRemover.Event += () => {}; + Diagnostic(ErrorCode.ERR_UnsupportedCompilerFeature, "Event").WithArguments("OnEventRemover.Event", "test").WithLocation(17, 16), + // (18,1): error CS9512: 'OnEventRemover' requires compiler feature 'test', which is not supported by this version of the C# compiler. + // OnEventRemover.Event -= () => {}; + Diagnostic(ErrorCode.ERR_UnsupportedCompilerFeature, "OnEventRemover").WithArguments("OnEventRemover", "test").WithLocation(18, 1), + // (18,16): error CS9512: 'OnEventRemover.Event' requires compiler feature 'test', which is not supported by this version of the C# compiler. + // OnEventRemover.Event -= () => {}; + Diagnostic(ErrorCode.ERR_UnsupportedCompilerFeature, "Event").WithArguments("OnEventRemover.Event", "test").WithLocation(18, 16), + // (19,1): error CS9512: 'OnEnum' requires compiler feature 'test', which is not supported by this version of the C# compiler. + // OnEnum onEnum; + Diagnostic(ErrorCode.ERR_UnsupportedCompilerFeature, "OnEnum").WithArguments("OnEnum", "test").WithLocation(19, 1), + // (20,5): error CS9512: 'OnEnumMember' requires compiler feature 'test', which is not supported by this version of the C# compiler. + // _ = OnEnumMember.A; + Diagnostic(ErrorCode.ERR_UnsupportedCompilerFeature, "OnEnumMember").WithArguments("OnEnumMember", "test").WithLocation(20, 5), + // (20,18): error CS9512: 'OnEnumMember.A' requires compiler feature 'test', which is not supported by this version of the C# compiler. + // _ = OnEnumMember.A; + Diagnostic(ErrorCode.ERR_UnsupportedCompilerFeature, "A").WithArguments("OnEnumMember.A", "test").WithLocation(20, 18), + // (21,1): error CS9512: 'OnClassTypeParameter' requires compiler feature 'test', which is not supported by this version of the C# compiler. + // OnClassTypeParameter onClassTypeParameter; + Diagnostic(ErrorCode.ERR_UnsupportedCompilerFeature, "OnClassTypeParameter").WithArguments("OnClassTypeParameter", "test").WithLocation(21, 1), + // (22,1): error CS9512: 'OnMethodTypeParameter' requires compiler feature 'test', which is not supported by this version of the C# compiler. + // OnMethodTypeParameter.M(); + Diagnostic(ErrorCode.ERR_UnsupportedCompilerFeature, "OnMethodTypeParameter").WithArguments("OnMethodTypeParameter", "test").WithLocation(22, 1), + // (22,1): error CS9512: 'T' requires compiler feature 'test', which is not supported by this version of the C# compiler. + // OnMethodTypeParameter.M(); + Diagnostic(ErrorCode.ERR_UnsupportedCompilerFeature, "OnMethodTypeParameter.M").WithArguments("T", "test").WithLocation(22, 1), + // (23,1): error CS9512: 'OnDelegateType' requires compiler feature 'test', which is not supported by this version of the C# compiler. + // OnDelegateType onDelegateType; + Diagnostic(ErrorCode.ERR_UnsupportedCompilerFeature, "OnDelegateType").WithArguments("OnDelegateType", "test").WithLocation(23, 1), + // (24,1): error CS9512: 'OnIndexedPropertyParameter' requires compiler feature 'test', which is not supported by this version of the C# compiler. + // OnIndexedPropertyParameter.set_Property(1, 1); + Diagnostic(ErrorCode.ERR_UnsupportedCompilerFeature, "OnIndexedPropertyParameter").WithArguments("OnIndexedPropertyParameter", "test").WithLocation(24, 1), + // (24,1): error CS9512: 'OnIndexedPropertyParameter.set_Property(int, int)' requires compiler feature 'test', which is not supported by this version of the C# compiler. + // OnIndexedPropertyParameter.set_Property(1, 1); + Diagnostic(ErrorCode.ERR_UnsupportedCompilerFeature, "OnIndexedPropertyParameter.set_Property").WithArguments("OnIndexedPropertyParameter.set_Property(int, int)", "test").WithLocation(24, 1), + // (25,5): error CS9512: 'OnIndexedPropertyParameter' requires compiler feature 'test', which is not supported by this version of the C# compiler. + // _ = OnIndexedPropertyParameter.get_Property(1); + Diagnostic(ErrorCode.ERR_UnsupportedCompilerFeature, "OnIndexedPropertyParameter").WithArguments("OnIndexedPropertyParameter", "test").WithLocation(25, 5), + // (25,5): error CS9512: 'OnIndexedPropertyParameter.get_Property(int)' requires compiler feature 'test', which is not supported by this version of the C# compiler. + // _ = OnIndexedPropertyParameter.get_Property(1); + Diagnostic(ErrorCode.ERR_UnsupportedCompilerFeature, "OnIndexedPropertyParameter.get_Property").WithArguments("OnIndexedPropertyParameter.get_Property(int)", "test").WithLocation(25, 5) + ); + } + + [Fact] + public void Application() + { + var comp = CSharpTestBase.CreateCompilation(new[] { """ + using System; + using System.Runtime.CompilerServices; + + [CompilerFeatureRequired("OnType")] + public class OnType + { + } + + public class OnMethod + { + [CompilerFeatureRequired("OnMethod")] + public static void M() {} + } + + public class OnMethodReturn + { + [return: CompilerFeatureRequired("OnMethodReturn")] + public static void M() {} + } + + public class OnParameter + { + public static void M([CompilerFeatureRequired("OnParameter")] int param) {} + } + + public class OnField + { + [CompilerFeatureRequired("OnField")] + public static int Field; + } + + public class OnProperty + { + [CompilerFeatureRequired("OnProperty")] + public static int Property { get => 0; set {} } + } + + public class OnPropertySetter + { + public static int Property { get => 0; [CompilerFeatureRequired("OnPropertySetter")] set {} } + } + + public class OnPropertyGetter + { + public static int Property { [CompilerFeatureRequired("OnPropertyGetter")] get => 0; set {} } + } + + public class OnEvent + { + [CompilerFeatureRequired("OnEvent")] + public static event Action Event { add {} remove {} } + } + + public class OnEventAdder + { + public static event Action Event { [CompilerFeatureRequired("OnEventAdder")] add {} remove {} } + } + + public class OnEventRemover + { + public static event Action Event { [CompilerFeatureRequired("OnEventRemover")] add {} remove {} } + } + + [CompilerFeatureRequired("OnEnum")] + public enum OnEnum + { + A + } + + public enum OnEnumMember + { + [CompilerFeatureRequired("OnEnumMember")] A + } + + public class OnClassTypeParameter<[CompilerFeatureRequired("OnClassTypeParameter")] T> + { + } + + public class OnMethodTypeParameter + { + public static void M<[CompilerFeatureRequired("OnMethodTypeParameter")] T>() {} + } + + [CompilerFeatureRequired("OnDelegateType")] + public delegate void OnDelegateType(); + """, CSharpTestBase.CompilerFeatureRequiredAttribute }); + + comp.VerifyDiagnostics( + // (4,2): error CS8335: Do not use 'System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute'. This is reserved for compiler usage. + // [CompilerFeatureRequired("OnType")] + Diagnostic(ErrorCode.ERR_ExplicitReservedAttr, @"CompilerFeatureRequired(""OnType"")").WithArguments("System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute").WithLocation(4, 2), + // (11,6): error CS8335: Do not use 'System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute'. This is reserved for compiler usage. + // [CompilerFeatureRequired("OnMethod")] + Diagnostic(ErrorCode.ERR_ExplicitReservedAttr, @"CompilerFeatureRequired(""OnMethod"")").WithArguments("System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute").WithLocation(11, 6), + // (17,14): error CS8335: Do not use 'System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute'. This is reserved for compiler usage. + // [return: CompilerFeatureRequired("OnMethodReturn")] + Diagnostic(ErrorCode.ERR_ExplicitReservedAttr, @"CompilerFeatureRequired(""OnMethodReturn"")").WithArguments("System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute").WithLocation(17, 14), + // (23,27): error CS8335: Do not use 'System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute'. This is reserved for compiler usage. + // public static void M([CompilerFeatureRequired("OnParameter")] int param) {} + Diagnostic(ErrorCode.ERR_ExplicitReservedAttr, @"CompilerFeatureRequired(""OnParameter"")").WithArguments("System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute").WithLocation(23, 27), + // (28,6): error CS8335: Do not use 'System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute'. This is reserved for compiler usage. + // [CompilerFeatureRequired("OnField")] + Diagnostic(ErrorCode.ERR_ExplicitReservedAttr, @"CompilerFeatureRequired(""OnField"")").WithArguments("System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute").WithLocation(28, 6), + // (34,6): error CS8335: Do not use 'System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute'. This is reserved for compiler usage. + // [CompilerFeatureRequired("OnProperty")] + Diagnostic(ErrorCode.ERR_ExplicitReservedAttr, @"CompilerFeatureRequired(""OnProperty"")").WithArguments("System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute").WithLocation(34, 6), + // (40,45): error CS8335: Do not use 'System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute'. This is reserved for compiler usage. + // public static int Property { get => 0; [CompilerFeatureRequired("OnPropertySetter")] set {} } + Diagnostic(ErrorCode.ERR_ExplicitReservedAttr, @"CompilerFeatureRequired(""OnPropertySetter"")").WithArguments("System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute").WithLocation(40, 45), + // (45,35): error CS8335: Do not use 'System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute'. This is reserved for compiler usage. + // public static int Property { [CompilerFeatureRequired("OnPropertyGetter")] get => 0; set {} } + Diagnostic(ErrorCode.ERR_ExplicitReservedAttr, @"CompilerFeatureRequired(""OnPropertyGetter"")").WithArguments("System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute").WithLocation(45, 35), + // (50,6): error CS8335: Do not use 'System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute'. This is reserved for compiler usage. + // [CompilerFeatureRequired("OnEvent")] + Diagnostic(ErrorCode.ERR_ExplicitReservedAttr, @"CompilerFeatureRequired(""OnEvent"")").WithArguments("System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute").WithLocation(50, 6), + // (56,41): error CS8335: Do not use 'System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute'. This is reserved for compiler usage. + // public static event Action Event { [CompilerFeatureRequired("OnEventAdder")] add {} remove {} } + Diagnostic(ErrorCode.ERR_ExplicitReservedAttr, @"CompilerFeatureRequired(""OnEventAdder"")").WithArguments("System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute").WithLocation(56, 41), + // (61,41): error CS8335: Do not use 'System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute'. This is reserved for compiler usage. + // public static event Action Event { [CompilerFeatureRequired("OnEventRemover")] add {} remove {} } + Diagnostic(ErrorCode.ERR_ExplicitReservedAttr, @"CompilerFeatureRequired(""OnEventRemover"")").WithArguments("System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute").WithLocation(61, 41), + // (64,2): error CS8335: Do not use 'System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute'. This is reserved for compiler usage. + // [CompilerFeatureRequired("OnEnum")] + Diagnostic(ErrorCode.ERR_ExplicitReservedAttr, @"CompilerFeatureRequired(""OnEnum"")").WithArguments("System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute").WithLocation(64, 2), + // (72,6): error CS8335: Do not use 'System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute'. This is reserved for compiler usage. + // [CompilerFeatureRequired("OnEnumMember")] A + Diagnostic(ErrorCode.ERR_ExplicitReservedAttr, @"CompilerFeatureRequired(""OnEnumMember"")").WithArguments("System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute").WithLocation(72, 6), + // (75,36): error CS8335: Do not use 'System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute'. This is reserved for compiler usage. + // public class OnClassTypeParameter<[CompilerFeatureRequired("OnClassTypeParameter")] T> + Diagnostic(ErrorCode.ERR_ExplicitReservedAttr, @"CompilerFeatureRequired(""OnClassTypeParameter"")").WithArguments("System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute").WithLocation(75, 36), + // (81,27): error CS8335: Do not use 'System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute'. This is reserved for compiler usage. + // public static void M<[CompilerFeatureRequired("OnMethodTypeParameter")] T>() {} + Diagnostic(ErrorCode.ERR_ExplicitReservedAttr, @"CompilerFeatureRequired(""OnMethodTypeParameter"")").WithArguments("System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute").WithLocation(81, 27), + // (84,2): error CS8335: Do not use 'System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute'. This is reserved for compiler usage. + // [CompilerFeatureRequired("OnDelegateType")] + Diagnostic(ErrorCode.ERR_ExplicitReservedAttr, @"CompilerFeatureRequired(""OnDelegateType"")").WithArguments("System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute").WithLocation(84, 2) + ); + } +} diff --git a/src/Compilers/Core/Portable/MetadataReader/PEModule.cs b/src/Compilers/Core/Portable/MetadataReader/PEModule.cs index cd0972fa881c7..37b63e4b68d00 100644 --- a/src/Compilers/Core/Portable/MetadataReader/PEModule.cs +++ b/src/Compilers/Core/Portable/MetadataReader/PEModule.cs @@ -101,6 +101,7 @@ internal sealed class PEModule : IDisposable private static readonly AttributeValueExtractor s_attributeDeprecatedDataExtractor = CrackDeprecatedAttributeData; private static readonly AttributeValueExtractor s_attributeBoolAndStringArrayValueExtractor = CrackBoolAndStringArrayInAttributeValue; private static readonly AttributeValueExtractor s_attributeBoolAndStringValueExtractor = CrackBoolAndStringInAttributeValue; + private static readonly AttributeValueExtractor s_attributeStringAndNamedArgBoolValueExtractor = CrackStringAndNamedArgBoolBoolInAttributeValue; internal struct BoolAndStringArrayData { @@ -125,6 +126,22 @@ public BoolAndStringData(bool sense, string? @string) public readonly bool Sense; public readonly string? String; } + + internal struct StringAndNamedArgBool + { + public StringAndNamedArgBool(string? @string, bool @bool, string? namedArg, bool namedArgIsField) + { + StringValue = @string; + BoolValue = @bool; + NamedArgName = namedArg; + NamedArgIsField = namedArgIsField; + } + + public readonly string? StringValue; + public readonly bool BoolValue; + public readonly string? NamedArgName; + public readonly bool NamedArgIsField; + } #nullable disable // 'ignoreAssemblyRefs' is used by the EE only, when debugging @@ -1149,6 +1166,47 @@ internal ObsoleteAttributeData TryGetDeprecatedOrExperimentalOrObsoleteAttribute } #nullable enable + internal ImmutableArray GetCompilerFeatureRequiredFeatures(EntityHandle token) + { + List? infos = FindTargetAttributes(token, AttributeDescription.CompilerFeatureRequiredAttribute); + + if (infos == null) + { + return ImmutableArray.Empty; + } + + ArrayBuilder builder = ArrayBuilder.GetInstance(); + + foreach (var info in infos) + { + if (TryExtractStringAndNamedArgBoolFromAttribute(info.Handle, out string? featureName, out bool isOptional, out string? namedArg, out bool isField)) + { + if (namedArg != "IsOptional" || isField) + { + isOptional = false; + } + } + else if (TryExtractStringValueFromAttribute(info.Handle, out featureName)) + { + isOptional = false; + } + else + { + // Bad metadata. + continue; + } + + if (featureName is null || isOptional) + { + continue; + } + + builder.Add(featureName); + } + + return builder.ToImmutableAndFree(); + } + internal UnmanagedCallersOnlyAttributeData? TryGetUnmanagedCallersOnlyAttribute( EntityHandle token, IAttributeNamedArgumentDecoder attributeArgumentDecoder, @@ -1694,6 +1752,16 @@ private bool TryExtractStringArrayValueFromAttribute(CustomAttributeHandle handl return TryExtractValueFromAttribute(handle, out value, s_attributeStringArrayValueExtractor); } + private bool TryExtractStringAndNamedArgBoolFromAttribute(CustomAttributeHandle handle, out string? stringValue, out bool boolValue, out string? namedArgName, out bool isField) + { + var result = TryExtractValueFromAttribute(handle, out var data, s_attributeStringAndNamedArgBoolValueExtractor); + stringValue = data.StringValue; + boolValue = data.BoolValue; + namedArgName = data.NamedArgName; + isField = data.NamedArgIsField; + return result; + } + private bool TryExtractValueFromAttribute(CustomAttributeHandle handle, out T? value, AttributeValueExtractor valueExtractor) { Debug.Assert(!handle.IsNil); @@ -2113,6 +2181,67 @@ internal static bool CrackByteArrayInAttributeValue(out ImmutableArray val value = default(ImmutableArray); return false; } + + internal static bool CrackStringAndNamedArgBoolBoolInAttributeValue(out StringAndNamedArgBool value, ref BlobReader sig) + { + // Refer to ECMA-335 II.23.3 for more information about the custom attribute format. + + // String positional argument. + if (!CrackStringInAttributeValue(out string? @string, ref sig)) + { + value = default; + return false; + } + + // Number of named arguments. There are at least 4 bytes remaining: a 2 byte count, followed by the + // property or field specifier (1 byte), followed by the type code (1 byte) + if (sig.RemainingBytes < 4 || sig.ReadUInt16() != 1) + { + value = default; + return false; + } + + // A single byte saying what type of named argument this is (Field or Property) + bool isField; + switch ((CustomAttributeNamedArgumentKind)sig.ReadByte()) + { + case CustomAttributeNamedArgumentKind.Field: + isField = true; + break; + + case CustomAttributeNamedArgumentKind.Property: + isField = false; + break; + + default: + value = default; + return false; + } + + // Single byte named argument type code + if (sig.ReadByte() != (byte)SerializationTypeCode.Boolean) + { + value = default; + return false; + } + + // Attribute name + if (!CrackStringInAttributeValue(out string? namedArg, ref sig)) + { + value = default; + return false; + } + + // Attribute value + if (!CrackBooleanInAttributeValue(out bool namedArgValue, ref sig)) + { + value = default; + return false; + } + + value = new StringAndNamedArgBool(@string, namedArgValue, namedArg, isField); + return true; + } #nullable disable internal struct AttributeInfo @@ -2133,9 +2262,10 @@ public bool HasValue } } - internal List FindTargetAttributes(EntityHandle hasAttribute, AttributeDescription description) +#nullable enable + internal List? FindTargetAttributes(EntityHandle hasAttribute, AttributeDescription description) { - List result = null; + List? result = null; try { @@ -2159,6 +2289,7 @@ internal List FindTargetAttributes(EntityHandle hasAttribute, Att return result; } +#nullable disable internal AttributeInfo FindTargetAttribute(EntityHandle hasAttribute, AttributeDescription description) { diff --git a/src/Compilers/Core/Portable/Symbols/Attributes/AttributeDescription.cs b/src/Compilers/Core/Portable/Symbols/Attributes/AttributeDescription.cs index c472cfd8df66f..492943114c624 100644 --- a/src/Compilers/Core/Portable/Symbols/Attributes/AttributeDescription.cs +++ b/src/Compilers/Core/Portable/Symbols/Attributes/AttributeDescription.cs @@ -480,5 +480,6 @@ static AttributeDescription() internal static readonly AttributeDescription InterpolatedStringHandlerArgumentAttribute = new AttributeDescription("System.Runtime.CompilerServices", "InterpolatedStringHandlerArgumentAttribute", s_signaturesOfInterpolatedStringArgumentAttribute); internal static readonly AttributeDescription RequiredMemberAttribute = new AttributeDescription("System.Runtime.CompilerServices", "RequiredMemberAttribute", s_signatures_HasThis_Void_Only); internal static readonly AttributeDescription SetsRequiredMembersAttribute = new AttributeDescription("System.Diagnostics.CodeAnalysis", "SetsRequiredMembersAttribute", s_signatures_HasThis_Void_Only); + internal static readonly AttributeDescription CompilerFeatureRequiredAttribute = new AttributeDescription("System.Runtime.CompilerServices", "CompilerFeatureRequiredAttribute", s_signatures_HasThis_Void_String_Only); } } diff --git a/src/Compilers/Core/Portable/Symbols/CompilerFeatureRequiredHelpers.cs b/src/Compilers/Core/Portable/Symbols/CompilerFeatureRequiredHelpers.cs new file mode 100644 index 0000000000000..13a9a74770974 --- /dev/null +++ b/src/Compilers/Core/Portable/Symbols/CompilerFeatureRequiredHelpers.cs @@ -0,0 +1,77 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Immutable; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Reflection.Metadata; + +namespace Microsoft.CodeAnalysis.Symbols; + +[Flags] +internal enum CompilerFeatureRequiredFeatures +{ + None = 0, + RefStructs = 1 << 0, + RequiredMembers = 1 << 1, + + Unknown = 1 << 31 +} + +internal static class CompilerFeatureRequiredHelpers +{ + internal static string? GetUnsupportedCompilerFeature(EntityHandle token, PEModule containingModule, CompilerFeatureRequiredFeatures allowedFeatures) + { + Debug.Assert(!token.IsNil); + Debug.Assert((allowedFeatures & CompilerFeatureRequiredFeatures.Unknown) == 0); + + var compilerRequiredFeatures = containingModule.GetCompilerFeatureRequiredFeatures(token); + + if (tryGetFirstUnsupportedFeature(compilerRequiredFeatures, out var unsupportedFeature)) + { + return unsupportedFeature; + } + + // Check the containing module and assembly as well, if the symbol itself was fine + compilerRequiredFeatures = containingModule.GetCompilerFeatureRequiredFeatures(EntityHandle.ModuleDefinition); + if (tryGetFirstUnsupportedFeature(compilerRequiredFeatures, out unsupportedFeature)) + { + return unsupportedFeature; + } + + compilerRequiredFeatures = containingModule.GetCompilerFeatureRequiredFeatures(EntityHandle.AssemblyDefinition); + if (tryGetFirstUnsupportedFeature(compilerRequiredFeatures, out unsupportedFeature)) + { + return unsupportedFeature; + } + + // No unsupported features found + return null; + + bool tryGetFirstUnsupportedFeature(ImmutableArray features, [NotNullWhen(true)] out string? unsupportedFeature) + { + foreach (var feature in features) + { + if ((allowedFeatures & getFeatureKind(feature)) == 0) + { + unsupportedFeature = feature; + return true; + } + } + + unsupportedFeature = null; + return false; + } + + + static CompilerFeatureRequiredFeatures getFeatureKind(string feature) + => feature switch + { + nameof(CompilerFeatureRequiredFeatures.RefStructs) => CompilerFeatureRequiredFeatures.RefStructs, + nameof(CompilerFeatureRequiredFeatures.RequiredMembers) => CompilerFeatureRequiredFeatures.RequiredMembers, + _ => CompilerFeatureRequiredFeatures.Unknown, + }; + } +} diff --git a/src/Compilers/Test/Core/BaseCompilerFeatureRequiredTests.cs b/src/Compilers/Test/Core/BaseCompilerFeatureRequiredTests.cs new file mode 100644 index 0000000000000..48f9e1000e1ea --- /dev/null +++ b/src/Compilers/Test/Core/BaseCompilerFeatureRequiredTests.cs @@ -0,0 +1,654 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Linq; +using System.Reflection.Metadata; +using Microsoft.CodeAnalysis.Test.Utilities; +using Xunit; + +namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Symbols; + +public abstract class BaseCompilerFeatureRequiredTests : CommonTestBase where TCompilation : Compilation +{ + private static string CompilerFeatureRequiredApplication( + bool? isOptional) + { + var builder = new BlobBuilder(); + builder.WriteSerializedString("test"); + var featureLengthAndName = string.Join(" ", builder.ToImmutableArray().Select(b => $"{b:x2}")); + + var isOptionalText = isOptional switch + { + true => "01 00 54 02 0a 49 73 4f 70 74 69 6f 6e 61 6c 01", // One optional parameter, "IsOptional", true + false => "01 00 54 02 0a 49 73 4f 70 74 69 6f 6e 61 6c 00", // One optional parameter, "IsOptional", false + null => "00 00" // No optional parameters + }; + + return $""" + .custom instance void System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute::.ctor(string) = ( + 01 00 {featureLengthAndName} {isOptionalText} + ) + """; + } + + private const string CompilerFeatureRequiredIl = + """ + .class public auto ansi sealed beforefieldinit System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute + extends [mscorlib]System.Attribute + { + .custom instance void [mscorlib]System.AttributeUsageAttribute::.ctor(valuetype [mscorlib]System.AttributeTargets) = ( + 01 00 ff 7f 00 00 02 00 54 02 0d 41 6c 6c 6f 77 + 4d 75 6c 74 69 70 6c 65 01 54 02 09 49 6e 68 65 + 72 69 74 65 64 00 + ) + // Fields + .field private initonly string 'k__BackingField' + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( + 01 00 00 00 + ) + .field private initonly bool 'k__BackingField' + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( + 01 00 00 00 + ) + + .field public static literal string RefStructs = "RefStructs" + .field public static literal string RequiredMembers = "RequiredMembers" + + // Methods + .method public hidebysig specialname rtspecialname + instance void .ctor ( + string featureName + ) cil managed + { + ldarg.0 + call instance void [mscorlib]System.Attribute::.ctor() + ldarg.0 + ldarg.1 + stfld string System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute::'k__BackingField' + ret + } // end of method CompilerFeatureRequiredAttribute::.ctor + + .method public hidebysig specialname + instance string get_FeatureName () cil managed + { + ldarg.0 + ldfld string System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute::'k__BackingField' + ret + } // end of method CompilerFeatureRequiredAttribute::get_FeatureName + + .method public hidebysig specialname + instance bool get_IsOptional () cil managed + { + ldarg.0 + ldfld bool System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute::'k__BackingField' + ret + } // end of method CompilerFeatureRequiredAttribute::get_IsOptional + + .method public hidebysig specialname + instance void modreq([mscorlib]System.Runtime.CompilerServices.IsExternalInit) set_IsOptional ( + bool 'value' + ) cil managed + { + ldarg.0 + ldarg.1 + stfld bool System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute::'k__BackingField' + ret + } // end of method CompilerFeatureRequiredAttribute::set_IsOptional + + // Properties + .property instance string FeatureName() + { + .get instance string System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute::get_FeatureName() + } + .property instance bool IsOptional() + { + .get instance bool System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute::get_IsOptional() + .set instance void modreq([mscorlib]System.Runtime.CompilerServices.IsExternalInit) System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute::set_IsOptional(bool) + } + + } // end of class System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute + """; + + // This IL is equivalent to the following definition, which format holes for the required attribute under test: + // [CompilerFeatureRequired("test")] + // public class OnType + // { + // } + // + // public class OnMethod + // { + // [CompilerFeatureRequired("test")] + // public static void M() {} + // } + // + // public class OnMethodReturn + // { + // [return: CompilerFeatureRequired("test")] + // public static void M() {} + // } + // + // public class OnParameter + // { + // public static void M([CompilerFeatureRequired("test")] int param) {} + // } + // + // public class OnField + // { + // [CompilerFeatureRequired("test")] + // public static int Field; + // } + // + // public class OnProperty + // { + // [CompilerFeatureRequired("test")] + // public static int Property { get => 0; set {} } + // } + // + // public class OnPropertySetter + // { + // public static int Property { get => 0; [CompilerFeatureRequired("test")] set {} } + // } + // + // public class OnPropertyGetter + // { + // public static int Property { [CompilerFeatureRequired("test")] get => 0; set {} } + // } + // + // public class OnEvent + // { + // [CompilerFeatureRequired("test")] + // public static event Action Event { add {} remove {} } + // } + // + // public class OnEventAdder + // { + // public static event Action Event { [CompilerFeatureRequired("test")] add {} remove {} } + // } + // + // public class OnEventRemover + // { + // public static event Action Event { [CompilerFeatureRequired("test")] add {} remove {} } + // } + // + // [CompilerFeatureRequired("test")] + // public enum OnEnum + // { + // A + // } + // + // public enum OnEnumMember + // { + // [CompilerFeatureRequired("test")] A + // } + // + // public class OnClassTypeParameter<[CompilerFeatureRequired("test")] T> + // { + // } + // + // public class OnMethodTypeParameter + // { + // public static void M<[CompilerFeatureRequired("test")] T>() {} + // } + // + // [CompilerFeatureRequired("test")] + // public delegate void OnDelegateType(); + // + // VB: + // Public Class OnIndexedPropertyParameter + // Public Property [Property]( param As Integer) As Integer + // Get + // Return 1 + // End Get + // Set + // End Set + // End Property + // End Class + private string GetTestIl(string attributeApplication) + { + return $$""" + .class public auto ansi beforefieldinit OnType + extends [mscorlib]System.Object + { + {{attributeApplication}} + } // end of class OnType + + .class public auto ansi beforefieldinit OnMethod + extends [mscorlib]System.Object + { + // Methods + .method public hidebysig static + void M () cil managed + { + {{attributeApplication}} + ret + } // end of method OnMethod::M + } // end of class OnMethod + + .class public auto ansi beforefieldinit OnMethodReturn + extends [mscorlib]System.Object + { + // Methods + .method public hidebysig static + void M () cil managed + { + .param [0] + {{attributeApplication}} + ret + } // end of method OnMethodReturn::M + } // end of class OnMethodReturn + + .class public auto ansi beforefieldinit OnParameter + extends [mscorlib]System.Object + { + // Methods + .method public hidebysig static + void M ( + int32 param + ) cil managed + { + .param [1] + {{attributeApplication}} + ret + } // end of method OnParameter::M + } // end of class OnParameter + + .class public auto ansi beforefieldinit OnField + extends [mscorlib]System.Object + { + // Fields + .field public static int32 Field + {{attributeApplication}} + } // end of class OnField + + .class public auto ansi beforefieldinit OnProperty + extends [mscorlib]System.Object + { + // Methods + .method public hidebysig specialname static + int32 get_Property () cil managed + { + ldc.i4.0 + ret + } // end of method OnProperty::get_Property + + .method public hidebysig specialname static + void set_Property ( + int32 'value' + ) cil managed + { + ret + } // end of method OnProperty::set_Property + + // Properties + .property int32 Property() + { + {{attributeApplication}} + .get int32 OnProperty::get_Property() + .set void OnProperty::set_Property(int32) + } + + } // end of class OnProperty + + .class public auto ansi beforefieldinit OnPropertySetter + extends [mscorlib]System.Object + { + // Methods + .method public hidebysig specialname static + int32 get_Property () cil managed + { + ldc.i4.0 + ret + } // end of method OnPropertySetter::get_Property + + .method public hidebysig specialname static + void set_Property ( + int32 'value' + ) cil managed + { + {{attributeApplication}} + ret + } // end of method OnPropertySetter::set_Property + + // Properties + .property int32 Property() + { + .get int32 OnPropertySetter::get_Property() + .set void OnPropertySetter::set_Property(int32) + } + } // end of class OnPropertySetter + + .class public auto ansi beforefieldinit OnPropertyGetter + extends [mscorlib]System.Object + { + // Methods + .method public hidebysig specialname static + int32 get_Property () cil managed + { + {{attributeApplication}} + ldc.i4.0 + ret + } // end of method OnPropertyGetter::get_Property + + .method public hidebysig specialname static + void set_Property ( + int32 'value' + ) cil managed + { + ret + } // end of method OnPropertyGetter::set_Property + + // Properties + .property int32 Property() + { + .get int32 OnPropertyGetter::get_Property() + .set void OnPropertyGetter::set_Property(int32) + } + + } // end of class OnPropertyGetter + + .class public auto ansi beforefieldinit OnEvent + extends [mscorlib]System.Object + { + // Methods + .method public hidebysig specialname static + void add_Event ( + class [mscorlib]System.Action 'value' + ) cil managed + { + ret + } // end of method OnEvent::add_Event + + .method public hidebysig specialname static + void remove_Event ( + class [mscorlib]System.Action 'value' + ) cil managed + { + ret + } // end of method OnEvent::remove_Event + + // Events + .event [mscorlib]System.Action Event + { + {{attributeApplication}} + .addon void OnEvent::add_Event(class [mscorlib]System.Action) + .removeon void OnEvent::remove_Event(class [mscorlib]System.Action) + } + + + } // end of class OnEvent + + .class public auto ansi beforefieldinit OnEventAdder + extends [mscorlib]System.Object + { + // Methods + .method public hidebysig specialname static + void add_Event ( + class [mscorlib]System.Action 'value' + ) cil managed + { + {{attributeApplication}} + ret + } // end of method OnEventAdder::add_Event + + .method public hidebysig specialname static + void remove_Event ( + class [mscorlib]System.Action 'value' + ) cil managed + { + ret + } // end of method OnEventAdder::remove_Event + + // Events + .event [mscorlib]System.Action Event + { + .addon void OnEventAdder::add_Event(class [mscorlib]System.Action) + .removeon void OnEventAdder::remove_Event(class [mscorlib]System.Action) + } + + + } // end of class OnEventAdder + + .class public auto ansi beforefieldinit OnEventRemover + extends [mscorlib]System.Object + { + // Methods + .method public hidebysig specialname static + void add_Event ( + class [mscorlib]System.Action 'value' + ) cil managed + { + ret + } // end of method OnEventRemover::add_Event + + .method public hidebysig specialname static + void remove_Event ( + class [mscorlib]System.Action 'value' + ) cil managed + { + {{attributeApplication}} + ret + } // end of method OnEventRemover::remove_Event + + // Events + .event [mscorlib]System.Action Event + { + .addon void OnEventRemover::add_Event(class [mscorlib]System.Action) + .removeon void OnEventRemover::remove_Event(class [mscorlib]System.Action) + } + + + } // end of class OnEventRemover + + .class public auto ansi sealed OnEnum + extends [mscorlib]System.Enum + { + {{attributeApplication}} + // Fields + .field public specialname rtspecialname int32 value__ + .field public static literal valuetype OnEnum A = int32(0) + + } // end of class OnEnum + + .class public auto ansi sealed OnEnumMember + extends [mscorlib]System.Enum + { + // Fields + .field public specialname rtspecialname int32 value__ + .field public static literal valuetype OnEnumMember A = int32(0) + {{attributeApplication}} + + } // end of class OnEnumMember + + .class public auto ansi beforefieldinit OnClassTypeParameter`1 + extends [mscorlib]System.Object + { + .param type T + {{attributeApplication}} + } // end of class OnClassTypeParameter`1 + + .class public auto ansi beforefieldinit OnMethodTypeParameter + extends [mscorlib]System.Object + { + // Methods + .method public hidebysig static + void M () cil managed + { + .param type T + {{attributeApplication}} + ret + } // end of method OnMethodTypeParameter::M + } // end of class OnMethodTypeParameter + + .class public auto ansi sealed OnDelegateType + extends [mscorlib]System.MulticastDelegate + { + {{attributeApplication}} + // Methods + .method public hidebysig specialname rtspecialname + instance void .ctor ( + object 'object', + native int 'method' + ) runtime managed + { + } // end of method OnDelegateType::.ctor + + .method public hidebysig newslot virtual + instance void Invoke () runtime managed + { + } // end of method OnDelegateType::Invoke + + .method public hidebysig newslot virtual + instance class [mscorlib]System.IAsyncResult BeginInvoke ( + class [mscorlib]System.AsyncCallback callback, + object 'object' + ) runtime managed + { + } // end of method OnDelegateType::BeginInvoke + + .method public hidebysig newslot virtual + instance void EndInvoke ( + class [mscorlib]System.IAsyncResult result + ) runtime managed + { + } // end of method OnDelegateType::EndInvoke + + } // end of class OnDelegateType + + .class public auto ansi OnIndexedPropertyParameter + extends [mscorlib]System.Object + { + // Methods + .method public specialname static + int32 get_Property ( + int32 param + ) cil managed + { + .param [1] + {{attributeApplication}} + + ldc.i4.1 + stloc.0 + ldloc.0 + ret + } // end of method OnIndexedPropertyParameter::get_Property + + .method public specialname static + void set_Property ( + int32 param, + int32 Value + ) cil managed + { + .param [1] + {{attributeApplication}} + + ret + } // end of method OnIndexedPropertyParameter::set_Property + + // Properties + .property int32 Property( + int32 param + ) + { + .get int32 OnIndexedPropertyParameter::get_Property(int32) + .set void OnIndexedPropertyParameter::set_Property(int32, int32) + } + + } // end of class OnIndexedPropertyParameter + """; + } + + protected abstract TSource GetUsage(); + protected abstract TCompilation CreateCompilationWithIL(TSource source, string ilSource); + protected abstract TCompilation CreateCompilation(TSource source, MetadataReference[] references); + protected abstract CompilationVerifier CompileAndVerify(TCompilation compilation); + + [Theory] + [InlineData(true)] + [InlineData(false)] + [InlineData(null)] + public void OnNormalSymbols(bool? isOptional) + { + var testIl = $""" + {CompilerFeatureRequiredIl} + {GetTestIl(CompilerFeatureRequiredApplication(isOptional: isOptional))} + """; + var comp = CreateCompilationWithIL(source: GetUsage(), ilSource: testIl); + + if (isOptional == true) + { + CompileAndVerify(comp).VerifyDiagnostics(); + } + else + { + AssertNormalErrors(comp); + } + } + + protected abstract void AssertNormalErrors(TCompilation compilation); + + [Theory] + [InlineData(true)] + [InlineData(false)] + [InlineData(null)] + public void OnAssembly(bool? isOptional) + { + var il = $$""" + .assembly 'AssemblyTest' + { + {{CompilerFeatureRequiredApplication(isOptional: isOptional)}} + } + + .assembly extern mscorlib + { + .publickeytoken = (B7 7A 5C 56 19 34 E0 89) + .ver 4:0:0:0 + } + + {{CompilerFeatureRequiredIl}} + {{GetTestIl(attributeApplication: "")}} + """; + + var compiledIl = CompileIL(il, prependDefaultHeader: false); + + var comp = CreateCompilation(source: GetUsage(), references: new[] { compiledIl }); + + if (isOptional == true) + { + CompileAndVerify(comp).VerifyDiagnostics(); + } + else + { + AssertModuleAndAssemblyErrors(comp); + } + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + [InlineData(null)] + public void OnModule(bool? isOptional) + { + var il = $$""" + .module OnModule + {{CompilerFeatureRequiredApplication(isOptional: isOptional)}} + + {{CompilerFeatureRequiredIl}} + {{GetTestIl(attributeApplication: "")}} + """; + + + var comp = CreateCompilationWithIL(source: GetUsage(), ilSource: il); + + if (isOptional == true) + { + CompileAndVerify(comp).VerifyDiagnostics(); + } + else + { + AssertModuleAndAssemblyErrors(comp); + } + } + + protected abstract void AssertModuleAndAssemblyErrors(TCompilation compilation); +} diff --git a/src/Compilers/Test/Utilities/CSharp/CSharpTestBase.cs b/src/Compilers/Test/Utilities/CSharp/CSharpTestBase.cs index 9b9c1c9200af6..21a72e50b5527 100644 --- a/src/Compilers/Test/Utilities/CSharp/CSharpTestBase.cs +++ b/src/Compilers/Test/Utilities/CSharp/CSharpTestBase.cs @@ -651,6 +651,22 @@ public SetsRequiredMembersAttribute() } "; + internal const string CompilerFeatureRequiredAttribute = """ + namespace System.Runtime.CompilerServices + { + [AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = false)] + public sealed class CompilerFeatureRequiredAttribute : Attribute + { + public CompilerFeatureRequiredAttribute(string featureName) + { + FeatureName = featureName; + } + public string FeatureName { get; } + public bool IsOptional { get; set; } + } + } + """; + protected static CSharpCompilationOptions WithNullableEnable(CSharpCompilationOptions options = null) { return WithNullable(options, NullableContextOptions.Enable); diff --git a/src/Compilers/VisualBasic/Portable/Errors/Errors.vb b/src/Compilers/VisualBasic/Portable/Errors/Errors.vb index 9cd4e9a6c63c4..dc5213173ded5 100644 --- a/src/Compilers/VisualBasic/Portable/Errors/Errors.vb +++ b/src/Compilers/VisualBasic/Portable/Errors/Errors.vb @@ -1764,7 +1764,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ERR_MultipleAnalyzerConfigsInSameDir = 37317 ERR_StdInOptionProvidedButConsoleInputIsNotRedirected = 37318 - ERR_NextAvailable = 37319 + ERR_UnsupportedCompilerFeature = 37319 + ERR_DoNotUseCompilerFeatureRequired = 37320 + + ERR_NextAvailable = 37321 '// WARNINGS BEGIN HERE WRN_UseOfObsoleteSymbol2 = 40000 diff --git a/src/Compilers/VisualBasic/Portable/Symbols/Metadata/PE/PEEventSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/Metadata/PE/PEEventSymbol.vb index 8b97e585a9c4d..b47418943d15e 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/Metadata/PE/PEEventSymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/Metadata/PE/PEEventSymbol.vb @@ -293,7 +293,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols.Metadata.PE Dim primaryDependency As AssemblySymbol = Me.PrimaryDependency If Not _lazyCachedUseSiteInfo.IsInitialized Then - _lazyCachedUseSiteInfo.Initialize(primaryDependency, CalculateUseSiteInfo()) + Dim useSiteInfo As UseSiteInfo(Of AssemblySymbol) = CalculateUseSiteInfo() + DeriveUseSiteInfoFromCompilerFeatureRequiredAttributes(useSiteInfo, Handle, CodeAnalysis.Symbols.CompilerFeatureRequiredFeatures.None) + _lazyCachedUseSiteInfo.Initialize(primaryDependency, useSiteInfo) End If Return _lazyCachedUseSiteInfo.ToUseSiteInfo(primaryDependency) diff --git a/src/Compilers/VisualBasic/Portable/Symbols/Metadata/PE/PEFieldSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/Metadata/PE/PEFieldSymbol.vb index bb09dc34f1427..b98ab0e1a44a9 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/Metadata/PE/PEFieldSymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/Metadata/PE/PEFieldSymbol.vb @@ -383,6 +383,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols.Metadata.PE If Not _lazyCachedUseSiteInfo.IsInitialized Then Dim fieldUseSiteInfo = CalculateUseSiteInfo() + DeriveUseSiteInfoFromCompilerFeatureRequiredAttributes(fieldUseSiteInfo, Handle, CodeAnalysis.Symbols.CompilerFeatureRequiredFeatures.None) + ' if there was no previous use site error for this symbol, check the constant value If fieldUseSiteInfo.DiagnosticInfo Is Nothing Then diff --git a/src/Compilers/VisualBasic/Portable/Symbols/Metadata/PE/PEMethodSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/Metadata/PE/PEMethodSymbol.vb index 0258db8c72de9..53599f60a0c2d 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/Metadata/PE/PEMethodSymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/Metadata/PE/PEMethodSymbol.vb @@ -15,6 +15,7 @@ Imports Microsoft.CodeAnalysis.VisualBasic.Symbols Imports Microsoft.CodeAnalysis.VisualBasic.Syntax Imports System.Runtime.InteropServices Imports System.Reflection.Metadata.Ecma335 +Imports System.Diagnostics.CodeAnalysis Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols.Metadata.PE @@ -388,7 +389,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols.Metadata.PE End If End If - If Not IsShared AndAlso String.Equals(name, WellKnownMemberNames.DelegateInvokeName, StringComparison.Ordinal) AndAlso _containingType.TypeKind = TYPEKIND.Delegate Then + If Not IsShared AndAlso String.Equals(name, WellKnownMemberNames.DelegateInvokeName, StringComparison.Ordinal) AndAlso _containingType.TypeKind = TypeKind.Delegate Then Return MethodKind.DelegateInvoke End If @@ -949,7 +950,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols.Metadata.PE ''' false if the method is already associated with a property or event. ''' Friend Function SetAssociatedProperty(propertySymbol As PEPropertySymbol, methodKind As MethodKind) As Boolean - Debug.Assert((methodKind = methodKind.PropertyGet) OrElse (methodKind = methodKind.PropertySet)) + Debug.Assert((methodKind = MethodKind.PropertyGet) OrElse (methodKind = MethodKind.PropertySet)) Return Me.SetAssociatedPropertyOrEvent(propertySymbol, methodKind) End Function @@ -958,7 +959,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols.Metadata.PE ''' false if the method is already associated with a property or event. ''' Friend Function SetAssociatedEvent(eventSymbol As PEEventSymbol, methodKind As MethodKind) As Boolean - Debug.Assert((methodKind = methodKind.EventAdd) OrElse (methodKind = methodKind.EventRemove) OrElse (methodKind = methodKind.EventRaise)) + Debug.Assert((methodKind = MethodKind.EventAdd) OrElse (methodKind = MethodKind.EventRemove) OrElse (methodKind = MethodKind.EventRaise)) Return Me.SetAssociatedPropertyOrEvent(eventSymbol, methodKind) End Function @@ -1063,10 +1064,17 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols.Metadata.PE Return ImmutableArray(Of TypeParameterSymbol).Empty Else Dim ownedParams = ImmutableArray.CreateBuilder(Of TypeParameterSymbol)(gpHandles.Count) + Dim useSiteInfo As UseSiteInfo(Of AssemblySymbol) = Nothing For i = 0 To gpHandles.Count - 1 - ownedParams.Add(New PETypeParameterSymbol(moduleSymbol, Me, CUShort(i), gpHandles(i))) + Dim typeParam As New PETypeParameterSymbol(moduleSymbol, Me, CUShort(i), gpHandles(i)) + useSiteInfo = MergeUseSiteInfo(useSiteInfo, typeParam.GetUseSiteInfo()) + ownedParams.Add(typeParam) Next + If useSiteInfo.DiagnosticInfo IsNot Nothing Then + errorInfo = useSiteInfo.DiagnosticInfo + End If + Return ownedParams.ToImmutable() End If Catch mrEx As BadImageFormatException @@ -1142,9 +1150,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols.Metadata.PE Friend Overrides Function GetUseSiteInfo() As UseSiteInfo(Of AssemblySymbol) If Not _packedFlags.IsUseSiteDiagnosticPopulated Then Dim useSiteInfo As UseSiteInfo(Of AssemblySymbol) = CalculateUseSiteInfo() + DeriveUseSiteInfoFromCompilerFeatureRequiredAttributes(useSiteInfo, Handle, CodeAnalysis.Symbols.CompilerFeatureRequiredFeatures.None) Dim errorInfo As DiagnosticInfo = useSiteInfo.DiagnosticInfo EnsureTypeParametersAreLoaded(errorInfo) CheckUnmanagedCallersOnly(errorInfo) + CheckParameterUseSiteInfo(errorInfo) Return InitializeUseSiteInfo(useSiteInfo.AdjustDiagnosticInfo(errorInfo)) End If @@ -1166,6 +1176,20 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols.Metadata.PE End If End Sub + Private Sub CheckParameterUseSiteInfo(ByRef errorInfo As DiagnosticInfo) + If errorInfo IsNot Nothing Then + Return + End If + + Dim info As UseSiteInfo(Of AssemblySymbol) = Nothing + + For Each parameter In Parameters + info = MergeUseSiteInfo(info, parameter.GetUseSiteInfo()) + Next + + errorInfo = info.DiagnosticInfo + End Sub + Private Function InitializeUseSiteInfo(useSiteInfo As UseSiteInfo(Of AssemblySymbol)) As UseSiteInfo(Of AssemblySymbol) If _packedFlags.IsUseSiteDiagnosticPopulated Then Return GetCachedUseSiteInfo() diff --git a/src/Compilers/VisualBasic/Portable/Symbols/Metadata/PE/PENamedTypeSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/Metadata/PE/PENamedTypeSymbol.vb index 26f53df3b08ee..cf657a7c4b670 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/Metadata/PE/PENamedTypeSymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/Metadata/PE/PENamedTypeSymbol.vb @@ -1275,9 +1275,14 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols.Metadata.PE Private Function CalculateUseSiteInfoImpl() As UseSiteInfo(Of AssemblySymbol) Dim useSiteInfo = CalculateUseSiteInfo() + DeriveUseSiteInfoFromCompilerFeatureRequiredAttributes(useSiteInfo, Handle, CodeAnalysis.Symbols.CompilerFeatureRequiredFeatures.None) If useSiteInfo.DiagnosticInfo Is Nothing Then + For Each typeParameter In Me.TypeParameters + useSiteInfo = MergeUseSiteInfo(useSiteInfo, typeParameter.GetUseSiteInfo()) + Next + ' Check if this type Is marked by RequiredAttribute attribute. ' If so mark the type as bad, because it relies upon semantics that are not understood by the VB compiler. If Me.ContainingPEModule.Module.HasRequiredAttributeAttribute(Me.Handle) Then diff --git a/src/Compilers/VisualBasic/Portable/Symbols/Metadata/PE/PEParameterSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/Metadata/PE/PEParameterSymbol.vb index 21b1018a09ebd..c51a28648f659 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/Metadata/PE/PEParameterSymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/Metadata/PE/PEParameterSymbol.vb @@ -63,6 +63,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols.Metadata.PE ''' Private _lazyHiddenAttributes As ImmutableArray(Of VisualBasicAttributeData) + Private _lazyCachedUseSiteInfo As CachedUseSiteInfo(Of AssemblySymbol) = CachedUseSiteInfo(Of AssemblySymbol).Uninitialized ' Indicates unknown state. + Friend Shared Function Create( moduleSymbol As PEModuleSymbol, containingSymbol As PEMethodSymbol, @@ -655,5 +657,17 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols.Metadata.PE Return DirectCast(_containingSymbol.ContainingModule, PEModuleSymbol).Module End Get End Property + + Friend Overrides Function GetUseSiteInfo() As UseSiteInfo(Of AssemblySymbol) + Dim primaryDependency As AssemblySymbol = Me.PrimaryDependency + + If Not _lazyCachedUseSiteInfo.IsInitialized Then + Dim useSiteInfo As New UseSiteInfo(Of AssemblySymbol)(primaryDependency) + DeriveUseSiteInfoFromCompilerFeatureRequiredAttributes(useSiteInfo, Handle, CodeAnalysis.Symbols.CompilerFeatureRequiredFeatures.None) + _lazyCachedUseSiteInfo.Initialize(primaryDependency, useSiteInfo) + End If + + Return _lazyCachedUseSiteInfo.ToUseSiteInfo(primaryDependency) + End Function End Class End Namespace diff --git a/src/Compilers/VisualBasic/Portable/Symbols/Metadata/PE/PEPropertySymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/Metadata/PE/PEPropertySymbol.vb index 7756a63151118..aa8942b508fc3 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/Metadata/PE/PEPropertySymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/Metadata/PE/PEPropertySymbol.vb @@ -545,7 +545,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols.Metadata.PE Dim primaryDependency As AssemblySymbol = Me.PrimaryDependency If Not _lazyCachedUseSiteInfo.IsInitialized Then - _lazyCachedUseSiteInfo.Initialize(primaryDependency, CalculateUseSiteInfo()) + Dim useSiteInfo As UseSiteInfo(Of AssemblySymbol) = CalculateUseSiteInfo() + DeriveUseSiteInfoFromCompilerFeatureRequiredAttributes(useSiteInfo, Handle, CodeAnalysis.Symbols.CompilerFeatureRequiredFeatures.None) + _lazyCachedUseSiteInfo.Initialize(primaryDependency, useSiteInfo) End If Return _lazyCachedUseSiteInfo.ToUseSiteInfo(primaryDependency) diff --git a/src/Compilers/VisualBasic/Portable/Symbols/Metadata/PE/PETypeParameterSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/Metadata/PE/PETypeParameterSymbol.vb index 175d97bab669a..a807de943887a 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/Metadata/PE/PETypeParameterSymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/Metadata/PE/PETypeParameterSymbol.vb @@ -39,6 +39,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols.Metadata.PE ''' Private _lazyCachedBoundsUseSiteInfo As CachedUseSiteInfo(Of AssemblySymbol) = CachedUseSiteInfo(Of AssemblySymbol).Uninitialized ' Indicates unknown state. + ''' + ''' First error on the type symbol itself + ''' + Private _lazyCachedUseSiteInfo As CachedUseSiteInfo(Of AssemblySymbol) = CachedUseSiteInfo(Of AssemblySymbol).Uninitialized ' Indicates unknown state. + Friend Sub New( moduleSymbol As PEModuleSymbol, definingNamedType As PENamedTypeSymbol, @@ -305,6 +310,18 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols.Metadata.PE Return _lazyCachedBoundsUseSiteInfo.ToUseSiteInfo(PrimaryDependency) End Function + Friend Overrides Function GetUseSiteInfo() As UseSiteInfo(Of AssemblySymbol) + Dim primaryDependency As AssemblySymbol = Me.PrimaryDependency + + If Not _lazyCachedUseSiteInfo.IsInitialized Then + Dim useSiteInfo As New UseSiteInfo(Of AssemblySymbol)(primaryDependency) + DeriveUseSiteInfoFromCompilerFeatureRequiredAttributes(useSiteInfo, Handle, CodeAnalysis.Symbols.CompilerFeatureRequiredFeatures.None) + _lazyCachedUseSiteInfo.Initialize(primaryDependency, useSiteInfo) + End If + + Return _lazyCachedUseSiteInfo.ToUseSiteInfo(primaryDependency) + End Function + ''' ''' This is for perf, not for correctness. ''' diff --git a/src/Compilers/VisualBasic/Portable/Symbols/Symbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/Symbol.vb index 22fec68b94238..a3730a4b0847a 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/Symbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/Symbol.vb @@ -12,6 +12,7 @@ Imports Microsoft.CodeAnalysis.PooledObjects Imports Microsoft.CodeAnalysis.Symbols Imports Microsoft.CodeAnalysis.Text Imports Microsoft.CodeAnalysis.VisualBasic.Symbols +Imports Microsoft.CodeAnalysis.VisualBasic.Symbols.Metadata.PE Imports Display = Microsoft.CodeAnalysis.VisualBasic.SymbolDisplay Namespace Microsoft.CodeAnalysis.VisualBasic @@ -1109,6 +1110,18 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Return Nothing End Function + Protected Sub DeriveUseSiteInfoFromCompilerFeatureRequiredAttributes(ByRef result As UseSiteInfo(Of AssemblySymbol), handle As System.Reflection.Metadata.EntityHandle, allowedFeatures As CompilerFeatureRequiredFeatures) + If (result.DiagnosticInfo IsNot Nothing) Then + Debug.Assert(result.DiagnosticInfo.Severity = DiagnosticSeverity.Error) + End If + + Dim unsupportedFeature = CompilerFeatureRequiredHelpers.GetUnsupportedCompilerFeature(handle, DirectCast(ContainingModule, PEModuleSymbol).Module, allowedFeatures) + If unsupportedFeature IsNot Nothing Then + ' '{0}' requires compiler feature '{1}', which is not supported by this version of the Visual Basic compiler. + result = result.AdjustDiagnosticInfo(ErrorFactory.ErrorInfo(ERRID.ERR_UnsupportedCompilerFeature, Me, unsupportedFeature)) + End If + End Sub + #End Region #Region "ISymbol" diff --git a/src/Compilers/VisualBasic/Portable/Symbols/Symbol_Attributes.vb b/src/Compilers/VisualBasic/Portable/Symbols/Symbol_Attributes.vb index 860b150e5b5b9..accc2a1242633 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/Symbol_Attributes.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/Symbol_Attributes.vb @@ -197,6 +197,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic If arguments.Attribute.IsTargetAttribute(Me, AttributeDescription.SkipLocalsInitAttribute) Then DirectCast(arguments.Diagnostics, BindingDiagnosticBag).Add(ERRID.WRN_AttributeNotSupportedInVB, arguments.AttributeSyntaxOpt.Location, AttributeDescription.SkipLocalsInitAttribute.FullName) + ElseIf arguments.Attribute.IsTargetAttribute(Me, AttributeDescription.CompilerFeatureRequiredAttribute) Then + DirectCast(arguments.Diagnostics, BindingDiagnosticBag).Add(ERRID.ERR_DoNotUseCompilerFeatureRequired, arguments.AttributeSyntaxOpt.Location) End If End Sub diff --git a/src/Compilers/VisualBasic/Portable/VBResources.resx b/src/Compilers/VisualBasic/Portable/VBResources.resx index 0fc1c93964159..f9c5e8b50f35b 100644 --- a/src/Compilers/VisualBasic/Portable/VBResources.resx +++ b/src/Compilers/VisualBasic/Portable/VBResources.resx @@ -5650,4 +5650,10 @@ {0} '{1}' cannot implement interface '{3}' because it contains shared abstract '{2}'. - + + '{0}' requires compiler feature '{1}', which is not supported by this version of the Visual Basic compiler. + + + 'System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute' is reserved for compiler usage only. + + \ No newline at end of file diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.cs.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.cs.xlf index 74dbe4cd9e5b2..f95673276b56f 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.cs.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.cs.xlf @@ -27,6 +27,11 @@ Typ {0} nemůže být vložený, protože má neabstraktní člen. Zvažte nastavení vlastnosti Vložit typy spolupráce na hodnotu false. + + 'System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute' is reserved for compiler usage only. + 'System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute' is reserved for compiler usage only. + + Multiple analyzer config files cannot be in the same directory ('{0}'). Ve stejném adresáři nemůže být více konfiguračních souborů analyzátoru ({0}). @@ -72,6 +77,11 @@ Atribut UnmanagedCallersOnly se nepodporuje. + + '{0}' requires compiler feature '{1}', which is not supported by this version of the Visual Basic compiler. + '{0}' requires compiler feature '{1}', which is not supported by this version of the Visual Basic compiler. + + caller argument expression výraz argumentu volajícího diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.de.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.de.xlf index a23847ee1b959..e09396cb29548 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.de.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.de.xlf @@ -27,6 +27,11 @@ Der Typ "{0}" kann nicht eingebettet werden, weil er einen nicht abstrakten Member aufweist. Legen Sie die Eigenschaft "Interoptypen einbetten" ggf. auf FALSE fest. + + 'System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute' is reserved for compiler usage only. + 'System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute' is reserved for compiler usage only. + + Multiple analyzer config files cannot be in the same directory ('{0}'). Dasselbe Verzeichnis ({0}) darf nicht mehrere Konfigurationsdateien des Analysetools enthalten. @@ -72,6 +77,11 @@ Das Attribut "UnmanagedCallersOnly" wird nicht unterstützt. + + '{0}' requires compiler feature '{1}', which is not supported by this version of the Visual Basic compiler. + '{0}' requires compiler feature '{1}', which is not supported by this version of the Visual Basic compiler. + + caller argument expression Aufruferargumentausdruck diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.es.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.es.xlf index 5aff11abead9e..0f417c0d3e00e 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.es.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.es.xlf @@ -27,6 +27,11 @@ El tipo "{0}" no se puede incrustar porque tiene un miembro no abstracto. Puede establecer la propiedad "Incrustar tipos de interoperabilidad" en false. + + 'System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute' is reserved for compiler usage only. + 'System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute' is reserved for compiler usage only. + + Multiple analyzer config files cannot be in the same directory ('{0}'). No es posible que un mismo directorio ("{0}") contenga varios archivos de configuración del analizador. @@ -72,6 +77,11 @@ No se admite el atributo "UnmanagedCallersOnly". + + '{0}' requires compiler feature '{1}', which is not supported by this version of the Visual Basic compiler. + '{0}' requires compiler feature '{1}', which is not supported by this version of the Visual Basic compiler. + + caller argument expression expresión de argumento de autor de llamada diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.fr.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.fr.xlf index aa9b5800ad529..2a45359ecc6ad 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.fr.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.fr.xlf @@ -27,6 +27,11 @@ Impossible d'incorporer le type '{0}', car il a un membre non abstrait. Affectez la valeur false à la propriété 'Incorporer les types interop'. + + 'System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute' is reserved for compiler usage only. + 'System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute' is reserved for compiler usage only. + + Multiple analyzer config files cannot be in the same directory ('{0}'). Plusieurs fichiers config d'analyseur ne peuvent pas figurer dans le même répertoire ('{0}'). @@ -72,6 +77,11 @@ L'attribut 'UnmanagedCallersOnly' n'est pas pris en charge. + + '{0}' requires compiler feature '{1}', which is not supported by this version of the Visual Basic compiler. + '{0}' requires compiler feature '{1}', which is not supported by this version of the Visual Basic compiler. + + caller argument expression expression d’argument de l’appelant diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.it.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.it.xlf index 49dced1ee481e..0dff509f7a273 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.it.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.it.xlf @@ -27,6 +27,11 @@ Non è possibile incorporare il tipo '{0}' perché contiene un membro non astratto. Provare a impostare la proprietà 'Incorpora tipi di interoperabilità' su false. + + 'System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute' is reserved for compiler usage only. + 'System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute' is reserved for compiler usage only. + + Multiple analyzer config files cannot be in the same directory ('{0}'). La stessa directory ('{0}') non può contenere più file di configurazione dell'analizzatore. @@ -72,6 +77,11 @@ L'attributo 'UnmanagedCallersOnly' non è supportato. + + '{0}' requires compiler feature '{1}', which is not supported by this version of the Visual Basic compiler. + '{0}' requires compiler feature '{1}', which is not supported by this version of the Visual Basic compiler. + + caller argument expression espressione passata come argomento del chiamante diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.ja.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.ja.xlf index 366b22b30ed17..64442f73c17bf 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.ja.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.ja.xlf @@ -27,6 +27,11 @@ 型 '{0}' には非抽象メンバーがあるため、この型を埋め込むことはできません。'相互運用型の埋め込み' プロパティを false に設定することをご検討ください。 + + 'System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute' is reserved for compiler usage only. + 'System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute' is reserved for compiler usage only. + + Multiple analyzer config files cannot be in the same directory ('{0}'). 複数のアナライザー構成ファイルを同じディレクトリに入れることはできません ('{0}')。 @@ -72,6 +77,11 @@ 'UnmanagedCallersOnly' 属性はサポートされていません。 + + '{0}' requires compiler feature '{1}', which is not supported by this version of the Visual Basic compiler. + '{0}' requires compiler feature '{1}', which is not supported by this version of the Visual Basic compiler. + + caller argument expression 呼び出し元の引数式 diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.ko.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.ko.xlf index 04c427b770613..f323fafb03155 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.ko.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.ko.xlf @@ -27,6 +27,11 @@ '{0}' 형식에는 비추상 멤버가 있으므로 해당 형식을 포함할 수 없습니다. 'Interop 형식 포함' 속성을 false로 설정해보세요. + + 'System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute' is reserved for compiler usage only. + 'System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute' is reserved for compiler usage only. + + Multiple analyzer config files cannot be in the same directory ('{0}'). 분석기 구성 파일 여러 개가 동일한 디렉터리('{0}')에 있을 수 없습니다. @@ -72,6 +77,11 @@ 'UnmanagedCallersOnly' 특성은 지원되지 않습니다. + + '{0}' requires compiler feature '{1}', which is not supported by this version of the Visual Basic compiler. + '{0}' requires compiler feature '{1}', which is not supported by this version of the Visual Basic compiler. + + caller argument expression 호출자 인수 표현식 diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.pl.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.pl.xlf index 5f6b7884f04d0..92a76b8aaa915 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.pl.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.pl.xlf @@ -27,6 +27,11 @@ Nie można osadzić typu „{0}”, ponieważ ma nieabstrakcyjną składową. Rozważ ustawienie wartości false dla właściwości „Osadź typy międzyoperacyjne”. + + 'System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute' is reserved for compiler usage only. + 'System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute' is reserved for compiler usage only. + + Multiple analyzer config files cannot be in the same directory ('{0}'). Wiele plików konfiguracji analizatora nie może znajdować się w tym samym katalogu („{0}”). @@ -72,6 +77,11 @@ Atrybut „UnmanagedCallersOnly” jest nieobsługiwany. + + '{0}' requires compiler feature '{1}', which is not supported by this version of the Visual Basic compiler. + '{0}' requires compiler feature '{1}', which is not supported by this version of the Visual Basic compiler. + + caller argument expression wyrażenie argumentu wywołującego diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.pt-BR.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.pt-BR.xlf index 206d8737e4cb4..c41ff58308bec 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.pt-BR.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.pt-BR.xlf @@ -27,6 +27,11 @@ O tipo '{0}' não pode ser inserido porque tem um membro que não é abstrato. Considere a definição da propriedade 'Inserir Tipos de Interoperabilidade' como false. + + 'System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute' is reserved for compiler usage only. + 'System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute' is reserved for compiler usage only. + + Multiple analyzer config files cannot be in the same directory ('{0}'). Não é possível que haja vários arquivos de configuração do analisador no mesmo diretório ('{0}'). @@ -72,6 +77,11 @@ Não há suporte para o atributo 'UnmanagedCallersOnly'. + + '{0}' requires compiler feature '{1}', which is not supported by this version of the Visual Basic compiler. + '{0}' requires compiler feature '{1}', which is not supported by this version of the Visual Basic compiler. + + caller argument expression expressão do argumento do chamador diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.ru.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.ru.xlf index fb9068dd3eff5..87fda78fe33be 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.ru.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.ru.xlf @@ -27,6 +27,11 @@ Не удается внедрить тип "{0}", так как он имеет неабстрактный член. Попробуйте задать для свойства "Внедрить типы взаимодействия" значение false. + + 'System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute' is reserved for compiler usage only. + 'System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute' is reserved for compiler usage only. + + Multiple analyzer config files cannot be in the same directory ('{0}'). В одном каталоге ("{0}") не может находиться несколько файлов конфигурации анализатора. @@ -72,6 +77,11 @@ Атрибут "UnmanagedCallersOnly" не поддерживается. + + '{0}' requires compiler feature '{1}', which is not supported by this version of the Visual Basic compiler. + '{0}' requires compiler feature '{1}', which is not supported by this version of the Visual Basic compiler. + + caller argument expression выражение аргумента вызывающего diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.tr.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.tr.xlf index e6bbcbc2efa53..a493c72740a9d 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.tr.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.tr.xlf @@ -27,6 +27,11 @@ '{0}' türünün soyut olmayan bir üyesi olduğundan bu tür eklenemiyor. 'Embed Interop Types' özelliğini false olarak ayarlamayı deneyin. + + 'System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute' is reserved for compiler usage only. + 'System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute' is reserved for compiler usage only. + + Multiple analyzer config files cannot be in the same directory ('{0}'). Birden çok çözümleyici yapılandırma dosyası aynı dizinde ('{0}') olamaz. @@ -72,6 +77,11 @@ 'UnmanagedCallersOnly' özniteliği desteklenmez. + + '{0}' requires compiler feature '{1}', which is not supported by this version of the Visual Basic compiler. + '{0}' requires compiler feature '{1}', which is not supported by this version of the Visual Basic compiler. + + caller argument expression çağıran bağımsız değişken ifadesi diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.zh-Hans.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.zh-Hans.xlf index 288055d74cc81..d79b4ca9af8f3 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.zh-Hans.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.zh-Hans.xlf @@ -27,6 +27,11 @@ 无法嵌入类型“{0}”,因为它有非抽象成员。请考虑将“嵌入互操作类型”属性设置为 false。 + + 'System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute' is reserved for compiler usage only. + 'System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute' is reserved for compiler usage only. + + Multiple analyzer config files cannot be in the same directory ('{0}'). 多个分析器配置文件不能位于同一目录({0})中。 @@ -72,6 +77,11 @@ 不支持 "UnmanagedCallersOnly" 属性。 + + '{0}' requires compiler feature '{1}', which is not supported by this version of the Visual Basic compiler. + '{0}' requires compiler feature '{1}', which is not supported by this version of the Visual Basic compiler. + + caller argument expression 调用方参数表达式 diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.zh-Hant.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.zh-Hant.xlf index 3bf828f847415..4293a6bade1dc 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.zh-Hant.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.zh-Hant.xlf @@ -27,6 +27,11 @@ 因為類型 '{0}' 有非抽象成員,所以無法內嵌。請考慮將 [內嵌 Interop 類型] 屬性設為 false。 + + 'System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute' is reserved for compiler usage only. + 'System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute' is reserved for compiler usage only. + + Multiple analyzer config files cannot be in the same directory ('{0}'). 多個分析器組態檔無法處於相同目錄 ('{0}') 中。 @@ -72,6 +77,11 @@ 不支援 'UnmanagedCallersOnly' 屬性。 + + '{0}' requires compiler feature '{1}', which is not supported by this version of the Visual Basic compiler. + '{0}' requires compiler feature '{1}', which is not supported by this version of the Visual Basic compiler. + + caller argument expression 呼叫者引數運算式 diff --git a/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/Metadata/PE/VisualBasicCompilerFeatureRequiredTests.vb b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/Metadata/PE/VisualBasicCompilerFeatureRequiredTests.vb new file mode 100644 index 0000000000000..f09e550d99763 --- /dev/null +++ b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/Metadata/PE/VisualBasicCompilerFeatureRequiredTests.vb @@ -0,0 +1,459 @@ +' Licensed to the .NET Foundation under one or more agreements. +' The .NET Foundation licenses this file to you under the MIT license. +' See the LICENSE file in the project root for more information. + +Imports Microsoft.CodeAnalysis +Imports Microsoft.CodeAnalysis.CodeGen +Imports Microsoft.CodeAnalysis.CSharp.UnitTests.Symbols +Imports Microsoft.CodeAnalysis.Test.Utilities +Imports Microsoft.CodeAnalysis.VisualBasic +Imports Microsoft.CodeAnalysis.VisualBasic.UnitTests + +Namespace Microsoft.CodeAnalysis.VisualBasic.UnitTests + + Public Class VisualBasicCompilerFeatureRequiredTests + Inherits BaseCompilerFeatureRequiredTests(Of VisualBasicCompilation, XElement) + + Private Class CompilerFeatureRequiredTests_VisualBasic + Inherits BasicTestBase + End Class + + Private ReadOnly _testBase As New CompilerFeatureRequiredTests_VisualBasic() + + Friend Overrides Function VisualizeRealIL(peModule As IModuleSymbol, methodData As CompilationTestData.MethodData, markers As IReadOnlyDictionary(Of Integer, String), areLocalsZeroed As Boolean) As String + Return _testBase.VisualizeRealIL(peModule, methodData, markers, areLocalsZeroed) + End Function + + Protected Overrides Function GetUsage() As XElement + Return + + + + End Function + + Protected Overrides Function CreateCompilationWithIL(source As XElement, ilSource As String) As VisualBasicCompilation + Return CreateCompilationWithCustomILSource(source, ilSource) + End Function + + Protected Overrides Function CreateCompilation(source As XElement, references() As MetadataReference) As VisualBasicCompilation + Return CompilationUtils.CreateCompilation(source, references) + End Function + + Protected Overrides Function CompileAndVerify(compilation As VisualBasicCompilation) As CompilationVerifier + Return _testBase.CompileAndVerify(compilation) + End Function + + Protected Overrides Sub AssertNormalErrors(comp As VisualBasicCompilation) + comp.AssertTheseDiagnostics( + + ) + End Sub + + Protected Overrides Sub AssertModuleAndAssemblyErrors(comp As VisualBasicCompilation) + comp.AssertTheseDiagnostics( + + ) + End Sub + + + Public Sub Application() + Dim compilation = CompilationUtils.CreateCompilation( + +Public Class OnType +End Class + +Public Class OnMethod + + Public Sub OnMethod() + End Sub +End Class + +Public Class OnMethodReturn + Public Function OnMethodReturn() As Integer + Return 1 + End Function +End Class + +Public Class OnField + + Public Field As Integer +End Class + +Public Class OnProperty + + Public Property Prop As Integer +End Class + +Public Class OnPropertySetter + Public Property Prop As Integer + Get + Return 1 + End Get + + Set + End Set + End Property +End Class + +Public Class OnPropertyGetter + Public Property Prop As Integer + + Get + Return 1 + End Get + Set + End Set + End Property +End Class + +Public Class OnEvent + + Public Event [Event] As Action +End Class + +Public Class OnEventAdder + Public Custom Event [Event] As Action + + AddHandler(value As Action) + End AddHandler + RemoveHandler(value As Action) + End RemoveHandler + RaiseEvent + End RaiseEvent + End Event +End Class + +Public Class OnEventRemover + Public Custom Event [Event] As Action + AddHandler(value As Action) + End AddHandler + + RemoveHandler(value As Action) + End RemoveHandler + RaiseEvent + End RaiseEvent + End Event +End Class + +Public Class OnEventRaiseEvent + Public Custom Event [Event] As Action + AddHandler(value As Action) + End AddHandler + RemoveHandler(value As Action) + End RemoveHandler + + RaiseEvent + End RaiseEvent + End Event +End Class + + +Public Enum OnEnum + A +End Enum + +Public Enum OnEnumMember + A +End Enum + + +Public Delegate Sub OnDelegate() +]]> + + + + Public Class CompilerFeatureRequiredAttribute + Inherits Attribute + + Public Sub New(featureName As String) + FeatureName = featureName + End Sub + + Public ReadOnly Property FeatureName As String + + Public Property IsOptional As Boolean + End Class +End Namespace +]]> + + + ) + + compilation.AssertTheseDiagnostics( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +BC37320: 'System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute' is reserved for compiler usage only. + + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +BC37320: 'System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute' is reserved for compiler usage only. + Public Function OnMethodReturn() As Integer + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +BC37320: 'System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute' is reserved for compiler usage only. + + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +BC37320: 'System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute' is reserved for compiler usage only. + + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +BC37320: 'System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute' is reserved for compiler usage only. + + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +BC37320: 'System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute' is reserved for compiler usage only. + + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +BC37320: 'System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute' is reserved for compiler usage only. + + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +BC37320: 'System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute' is reserved for compiler usage only. + + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +BC37320: 'System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute' is reserved for compiler usage only. + + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +BC37320: 'System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute' is reserved for compiler usage only. + + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +BC37320: 'System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute' is reserved for compiler usage only. + + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +BC37320: 'System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute' is reserved for compiler usage only. + A + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +BC37320: 'System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute' is reserved for compiler usage only. + + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +]]>) + End Sub + End Class +End Namespace