Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -26,83 +26,6 @@ public static class RuntimeHelpers
}
}";

private const string CompilerFeatureRequiredAttributeIL = @"
.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 '<FeatureName>k__BackingField'
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
01 00 00 00
)
.field private initonly bool '<IsOptional>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::'<FeatureName>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::'<FeatureName>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::'<IsOptional>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::'<IsOptional>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
";

[ConditionalFact(typeof(CoreClrOnly))]
[WorkItem(23358, "https://github.com/dotnet/roslyn/issues/23358")]
public void EmptyOrNullStringConv()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7894,4 +7894,92 @@ public ConditionalAttribute(string condition)
Diagnostic(ErrorCode.ERR_AttributeOnBadSymbolType, "Conditional").WithArguments("Conditional", "class, method").WithLocation(6, 6)
);
}

[Fact]
public void UnknownCompilerFeatureRequired()
{
// Equivalent to
// public class C
// {
// public required int Prop { get; set; }
// [CompilerFeatureRequired("Unknown")]
// public C() {}
// }
var il = """
.class public auto ansi C
extends [mscorlib]System.Object
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.RequiredMemberAttribute::.ctor() = (
01 00 00 0
)
.method public specialname rtspecialname
instance void .ctor () cil managed
{
// CompilerFeatureRequiredAttribute("Unknown")
.custom instance void System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute::.ctor(string) = (
01 00 07 55 6e 6b 6e 6f 77 6e 00 00
)
.custom instance void [mscorlib]System.ObsoleteAttribute::.ctor(string, bool) = (
01 00 5f 43 6f 6e 73 74 72 75 63 74 6f 72 73 20
6f 66 20 74 79 70 65 73 20 77 69 74 68 20 72 65
71 75 69 72 65 64 20 6d 65 6d 62 65 72 73 20 61
72 65 20 6e 6f 74 20 73 75 70 70 6f 72 74 65 64
20 69 6e 20 74 68 69 73 20 76 65 72 73 69 6f 6e
20 6f 66 20 79 6f 75 72 20 63 6f 6d 70 69 6c 65
72 2e 01 00 00
)
.custom instance void System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute::.ctor(string) = (
01 00 0f 52 65 71 75 69 72 65 64 4d 65 6d 62 65
72 73 00 00
)
ldarg.0
call instance void [mscorlib]System.Object::.ctor()
ret
}

.method public hidebysig specialname
instance int32 get_Prop () cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
01 00 00 00
)
ldarg.0
ldfld int32 C::'<Prop>k__BackingField'
ret
} // end of method C::get_Prop

.method public hidebysig specialname
instance void set_Prop (
int32 'value'
) cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
01 00 00 00
)
ldarg.0
ldarg.1
stfld int32 C::'<Prop>k__BackingField'
ret
} // end of method C::set_Prop
.property instance int32 Prop()
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.RequiredMemberAttribute::.ctor() = (
01 00 00 00
)
.get instance int32 C::get_Prop()
.set instance void C::set_Prop(int32)
}
}
""" + CompilerFeatureRequiredAttributeIL;

var comp = CreateCompilationWithIL(source: "", ilSource: il, targetFramework: TargetFramework.Net70);
var c = comp.GetTypeByMetadataName("C");

MethodSymbol constructor = c!.Constructors.Single();
AssertEx.Equal(["System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute(\"Unknown\")",
"System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute(\"RequiredMembers\")"],
constructor.GetAttributes().Select(a => $"{a.AttributeClass.ToTestDisplayString()}({string.Join(", ", a.CommonConstructorArguments.Select(arg => arg.ToCSharpString()))})"));

Assert.True(constructor.ShouldCheckRequiredMembers());
}
}
77 changes: 77 additions & 0 deletions src/Compilers/Test/Utilities/CSharp/CSharpTestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -721,6 +721,83 @@ public CompilerFeatureRequiredAttribute(string featureName)
}
""";

internal const string CompilerFeatureRequiredAttributeIL = @"
.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 '<FeatureName>k__BackingField'
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
01 00 00 00
)
.field private initonly bool '<IsOptional>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::'<FeatureName>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::'<FeatureName>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::'<IsOptional>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::'<IsOptional>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
";

internal static readonly string CollectionBuilderAttributeDefinition = """
namespace System.Runtime.CompilerServices
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -641,7 +641,26 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols.Metadata.PE
If Not _packedFlags.IsCustomAttributesPopulated Then
Dim attributeData As ImmutableArray(Of VisualBasicAttributeData) = Nothing
Dim containingPEModuleSymbol = DirectCast(ContainingModule(), PEModuleSymbol)
containingPEModuleSymbol.LoadCustomAttributes(Me.Handle, attributeData)
Dim checkForRequiredMembers = MethodKind = MethodKind.Constructor AndAlso
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HasSetsRequiredMembers = False AndAlso
(Me.ContainingType.HasAnyDeclaredRequiredMembers OrElse Not Me.ContainingType.AllRequiredMembers.IsEmpty)

If checkForRequiredMembers Then
Dim compilerFeatureRequiredDiagnostic As DiagnosticInfo = Nothing
DeriveCompilerFeatureRequiredUseSiteInfo(compilerFeatureRequiredDiagnostic)

Dim discard1 As CustomAttributeHandle = Nothing
Dim discard2 As CustomAttributeHandle = Nothing
attributeData = containingPEModuleSymbol.GetCustomAttributesForToken(
Me.Handle,
filteredOutAttribute1:=discard1,
filterOut1:=If(compilerFeatureRequiredDiagnostic Is Nothing, AttributeDescription.CompilerFeatureRequiredAttribute, Nothing),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

compilerFeatureRequiredDiagnostic Is Nothing

Do we have a test observing significance of this condition?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, I didn't cook up some invalid IL test here. If you'd prefer that I do so, I can.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume we have a test for C#, it feels like it shouldn't be very hard to port it.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We didn't, but now we do.

filteredOutAttribute2:=discard2,
filterOut2:=If(ObsoleteAttributeData Is Nothing, AttributeDescription.ObsoleteAttribute, Nothing))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If(ObsoleteAttributeData Is Nothing, AttributeDescription.ObsoleteAttribute, Nothing)

Does this filter out explicit [Obsolete] attributes as well (for a constructor on a type with a required member that has been deprecated)?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


Else
containingPEModuleSymbol.LoadCustomAttributes(Me.Handle, attributeData)
End If
Debug.Assert(Not attributeData.IsDefault)
If Not attributeData.IsEmpty Then
attributeData = InterlockedOperations.Initialize(AccessUncommonFields()._lazyCustomAttributes, attributeData)
Expand Down
Loading