Skip to content

Commit

Permalink
Fix custom attribute with enum on generic type (jbevain#827)
Browse files Browse the repository at this point in the history
* Fix custom attribute with enum on generic type

Fixes both the reader and the write to correctly handle values of type enum on a generic type.
Cecil represents generic instantiations as typeref which has etype GenericInst, so the exising check for etype doesn't work. Also since attributes only allow simple values and enums (and types), there's technically no other way to get a GenericInst then the enum case.

Added several test for various combinations of boxed an unboxed enums on generic type.

Added a test case provided by @mrvoorhe with array of such enums.

* Disable the new tests on .NET 4

The CodeDom compiler doesn't support parsing enums on generic types in attributes (uses the "old" csc.exe from framework).
  • Loading branch information
vitek-karas authored and mrvoorhe committed Feb 25, 2022
1 parent 83ed824 commit 55142e2
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 0 deletions.
6 changes: 6 additions & 0 deletions Mono.Cecil/AssemblyReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3595,6 +3595,12 @@ CustomAttributeArgument ReadCustomAttributeElement (TypeReference type)
object ReadCustomAttributeElementValue (TypeReference type)
{
var etype = type.etype;
if (etype == ElementType.GenericInst) {
// The only way to get a generic here is that it's an enum on a generic type
// so for enum we don't need to know the generic arguments (they have no effect)
type = type.GetElementType ();
etype = type.etype;
}

switch (etype) {
case ElementType.String:
Expand Down
12 changes: 12 additions & 0 deletions Mono.Cecil/AssemblyWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2971,6 +2971,10 @@ void WriteCustomAttributeValue (TypeReference type, object value)
else
WriteCustomAttributeEnumValue (type, value);
break;
case ElementType.GenericInst:
// Generic instantiation can only happen for an enum (no other generic like types can appear in attribute value)
WriteCustomAttributeEnumValue (type, value);
break;
default:
WritePrimitiveValue (value);
break;
Expand Down Expand Up @@ -3077,6 +3081,14 @@ void WriteCustomAttributeFieldOrPropType (TypeReference type)
WriteTypeReference (type);
}
return;
case ElementType.GenericInst:
// Generic instantiation can really only happen if it's an enum type since no other
// types are allowed in the attribute value.
// Enums are special in attribute data, they're encoded as ElementType.Enum followed by a typeref
// followed by the value.
WriteElementType (ElementType.Enum);
WriteTypeReference (type);
return;
default:
WriteElementType (etype);
return;
Expand Down

0 comments on commit 55142e2

Please sign in to comment.