Skip to content

Commit 019d778

Browse files
Fix CustomAttributeData in the presence of generic attributes (#56879)
* Fix CustomAttributeData in the presence of generic attributes - Generic attributes need to force the actual exact method to be loaded not just the canonical scenario - GenericAttribute testing had been disabled due to dotnet/msbuild#6734 - Move GenericAttribute test project to Pri0 as its the only generic custom attribute runtime testing that will occur before .NET 6.0 ships - Test disabled on Mono as Mono currently doesn't support this feature. Fixes #56492
1 parent df05666 commit 019d778

File tree

6 files changed

+46
-4
lines changed

6 files changed

+46
-4
lines changed

src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeCustomAttributeData.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,13 @@ private RuntimeCustomAttributeData(RuntimeModule scope, MetadataToken caCtorToke
273273
m_scope = scope;
274274
m_ctor = (RuntimeConstructorInfo)RuntimeType.GetMethodBase(scope, caCtorToken)!;
275275

276+
if (m_ctor!.DeclaringType!.IsGenericType)
277+
{
278+
MetadataImport metadataScope = scope.MetadataImport;
279+
var attributeType = scope.ResolveType(metadataScope.GetParentToken(caCtorToken), null, null)!;
280+
m_ctor = (RuntimeConstructorInfo)scope.ResolveMethod(caCtorToken, attributeType.GenericTypeArguments, null)!.MethodHandle.GetMethodInfo();
281+
}
282+
276283
ParameterInfo[] parameters = m_ctor.GetParametersNoCopy();
277284
m_ctorParams = new CustomAttributeCtorParameter[parameters.Length];
278285
for (int i = 0; i < parameters.Length; i++)

src/tests/Common/dirs.proj

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
<DisabledProjects Include="$(TestRoot)Loader\classloader\generics\GenericMethods\VSW491668.csproj" /> <!-- issue 5501 -->
1717
<DisabledProjects Include="$(TestRoot)Loader\classloader\StaticVirtualMethods\**\generatetest.csproj" /> <!-- test generators -->
1818
<DisabledProjects Include="$(TestRoot)Performance\Scenario\JitBench\unofficial_dotnet\JitBench.csproj" /> <!-- no official build support for SDK-style netcoreapp2.0 projects -->
19-
<DisabledProjects Include="$(TestRoot)reflection\GenericAttribute\GenericAttributeTests.csproj" />
2019
<DisabledProjects Include="$(TestRoot)TestWrappers*\**\*.csproj" />
2120
</ItemGroup>
2221

src/tests/issues.targets

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -981,6 +981,9 @@
981981

982982
<!-- Known failures for mono runtime on *all* architectures/operating systems in *all* runtime modes -->
983983
<ItemGroup Condition="'$(RuntimeFlavor)' == 'mono'" >
984+
<ExcludeList Include = "$(XunitTestBinBase)/reflection/GenericAttribute/**">
985+
<Issue>https://github.com/dotnet/runtime/issues/56887</Issue>
986+
</ExcludeList>
984987
<ExcludeList Include = "$(XunitTestBinBase)/JIT/HardwareIntrinsics/X86/Sse2.X64/StoreNonTemporal_r/**">
985988
<Issue>https://github.com/dotnet/runtime/issues/54176</Issue>
986989
</ExcludeList>

src/tests/reflection/GenericAttribute/GenericAttributeMetadata.il

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,14 @@
1313

1414
// --- The following custom attribute is added automatically, do not uncomment -------
1515
// .custom instance void [mscorlib]System.Diagnostics.DebuggableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggableAttribute/DebuggingModes) = ( 01 00 07 01 00 00 00 00 )
16-
16+
/* Re-enable once the fix to https://github.com/dotnet/msbuild/issues/6734 propagates to this repo.
1717
.custom instance void class SingleAttribute`1<int32>::.ctor() = ( 01 00 00 00 )
1818
.custom instance void class SingleAttribute`1<bool>::.ctor() = ( 01 00 00 00 )
1919
.custom instance void class MultiAttribute`1<int32>::.ctor() = ( 01 00 00 00 )
2020
.custom instance void class MultiAttribute`1<int32>::.ctor(!0) = ( 01 00 01 00 00 00 00 00 )
2121
.custom instance void class MultiAttribute`1<int32>::.ctor() = ( 01 00 01 00 54 08 05 56 61 6C 75 65 02 00 00 00 ) // ....T..Value....
2222
.custom instance void class MultiAttribute`1<bool>::.ctor() = ( 01 00 00 00 )
23-
.custom instance void class MultiAttribute`1<bool>::.ctor(!0) = ( 01 00 01 00 00 )
23+
.custom instance void class MultiAttribute`1<bool>::.ctor(!0) = ( 01 00 01 00 00 ) */
2424
.hash algorithm 0x00008004
2525
.ver 0:0:0:0
2626
}

src/tests/reflection/GenericAttribute/GenericAttributeTests.cs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ class Program
88
{
99
static int Main(string[] args)
1010
{
11+
/* Re-enable once the fix to https://github.com/dotnet/msbuild/issues/6734 propagates to this repo.
1112
Assembly assembly = typeof(Class).GetTypeInfo().Assembly;
1213
Assert(CustomAttributeExtensions.GetCustomAttribute<SingleAttribute<int>>(assembly) != null);
1314
Assert(((ICustomAttributeProvider)assembly).GetCustomAttributes(typeof(SingleAttribute<int>), true) != null);
@@ -18,6 +19,8 @@ static int Main(string[] args)
1819
Assert(CustomAttributeExtensions.IsDefined(assembly, typeof(SingleAttribute<bool>)));
1920
Assert(((ICustomAttributeProvider)assembly).IsDefined(typeof(SingleAttribute<bool>), true));
2021
22+
*/
23+
2124
TypeInfo programTypeInfo = typeof(Class).GetTypeInfo();
2225
Assert(CustomAttributeExtensions.GetCustomAttribute<SingleAttribute<int>>(programTypeInfo) != null);
2326
Assert(((ICustomAttributeProvider)programTypeInfo).GetCustomAttributes(typeof(SingleAttribute<int>), true) != null);
@@ -153,6 +156,24 @@ static int Main(string[] args)
153156
Assert(CustomAttributeExtensions.GetCustomAttributes(programTypeInfo, typeof(MultiAttribute<>), true) == null);
154157
Assert(!((ICustomAttributeProvider)programTypeInfo).GetCustomAttributes(typeof(MultiAttribute<>), true).GetEnumerator().MoveNext());
155158

159+
// Test coverage for CustomAttributeData api surface
160+
var a1_data = CustomAttributeData.GetCustomAttributes(programTypeInfo);
161+
AssertAny(a1_data, a => a.AttributeType == typeof(SingleAttribute<int>));
162+
AssertAny(a1_data, a => a.AttributeType == typeof(SingleAttribute<bool>));
163+
164+
AssertAny(a1_data, a => a.AttributeType == typeof(MultiAttribute<int>) && a.ConstructorArguments.Count == 0 && a.NamedArguments.Count == 0);
165+
AssertAny(a1_data, a => a.AttributeType == typeof(MultiAttribute<int>) && a.ConstructorArguments.Count == 1 && a.NamedArguments.Count == 0 && a.ConstructorArguments[0].ArgumentType == typeof(int) && ((int)a.ConstructorArguments[0].Value) == 1);
166+
AssertAny(a1_data, a => a.AttributeType == typeof(MultiAttribute<int>) && a.ConstructorArguments.Count == 0 && a.NamedArguments.Count == 1 && a.NamedArguments[0].TypedValue.ArgumentType == typeof(int) && ((int)a.NamedArguments[0].TypedValue.Value) == 2);
167+
168+
AssertAny(a1_data, a => a.AttributeType == typeof(MultiAttribute<bool>) && a.ConstructorArguments.Count == 0 && a.NamedArguments.Count == 0);
169+
AssertAny(a1_data, a => a.AttributeType == typeof(MultiAttribute<bool>) && a.ConstructorArguments.Count == 1 && a.NamedArguments.Count == 0 && a.ConstructorArguments[0].ArgumentType == typeof(bool) && ((bool)a.ConstructorArguments[0].Value) == true);
170+
AssertAny(a1_data, a => a.AttributeType == typeof(MultiAttribute<bool>) && a.ConstructorArguments.Count == 0 && a.NamedArguments.Count == 1 && a.NamedArguments[0].TypedValue.ArgumentType == typeof(bool) && ((bool)a.NamedArguments[0].TypedValue.Value) == true);
171+
172+
AssertAny(a1_data, a => a.AttributeType == typeof(MultiAttribute<bool?>) && a.ConstructorArguments.Count == 0 && a.NamedArguments.Count == 0);
173+
174+
AssertAny(a1_data, a => a.AttributeType == typeof(MultiAttribute<Type>) && a.ConstructorArguments.Count == 1 && a.NamedArguments.Count == 0 && a.ConstructorArguments[0].ArgumentType == typeof(Type) && ((Type)a.ConstructorArguments[0].Value) == typeof(Class));
175+
AssertAny(a1_data, a => a.AttributeType == typeof(MultiAttribute<Type>) && a.ConstructorArguments.Count == 0 && a.NamedArguments.Count == 1 && a.NamedArguments[0].TypedValue.ArgumentType == typeof(Type) && ((Type)a.NamedArguments[0].TypedValue.Value) == typeof(Class.Derive));
176+
156177
return 100;
157178
}
158179

@@ -176,4 +197,17 @@ static void AssertAny(IEnumerable<object> source, Func<Attribute, bool> conditio
176197
}
177198
throw new Exception($"Error in line: {line}");
178199
}
200+
201+
static void AssertAny(IEnumerable<CustomAttributeData> source, Func<CustomAttributeData, bool> condition, int count = 1, [CallerLineNumberAttribute]int line = 0)
202+
{
203+
var enumerator = source.GetEnumerator();
204+
while (enumerator.MoveNext())
205+
{
206+
if(condition(enumerator.Current) && --count == 0)
207+
{
208+
return;
209+
}
210+
}
211+
throw new Exception($"Error in line: {line}");
212+
}
179213
}

src/tests/reflection/GenericAttribute/GenericAttributeTests.csproj

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
44
<OutputType>Exe</OutputType>
55
<CLRTestKind>BuildAndRun</CLRTestKind>
6-
<CLRTestPriority>1</CLRTestPriority>
76
</PropertyGroup>
87
<ItemGroup>
98
<Compile Include="GenericAttributeTests.cs" />

0 commit comments

Comments
 (0)