diff --git a/ICSharpCode.Decompiler.Tests/Helpers/RemoveCompilerAttribute.cs b/ICSharpCode.Decompiler.Tests/Helpers/RemoveCompilerAttribute.cs index 3231e7f96..494c11225 100644 --- a/ICSharpCode.Decompiler.Tests/Helpers/RemoveCompilerAttribute.cs +++ b/ICSharpCode.Decompiler.Tests/Helpers/RemoveCompilerAttribute.cs @@ -33,11 +33,12 @@ namespace ICSharpCode.Decompiler.Tests.Helpers } } - public class RemoveEmbeddedAtttributes : DepthFirstAstVisitor, IAstTransform + public class RemoveEmbeddedAttributes : DepthFirstAstVisitor, IAstTransform { HashSet attributeNames = new HashSet() { "System.Runtime.CompilerServices.IsReadOnlyAttribute", "System.Runtime.CompilerServices.IsByRefLikeAttribute", + "System.Runtime.CompilerServices.IsUnmanagedAttribute", "Microsoft.CodeAnalysis.EmbeddedAttribute", }; diff --git a/ICSharpCode.Decompiler.Tests/Helpers/Tester.cs b/ICSharpCode.Decompiler.Tests/Helpers/Tester.cs index ace9d1ef9..b25101352 100644 --- a/ICSharpCode.Decompiler.Tests/Helpers/Tester.cs +++ b/ICSharpCode.Decompiler.Tests/Helpers/Tester.cs @@ -412,7 +412,7 @@ namespace ICSharpCode.Decompiler.Tests.Helpers resolver.AddSearchDirectory(Path.GetDirectoryName(typeof(Span<>).Assembly.Location)); var typeSystem = new DecompilerTypeSystem(module, resolver, settings); CSharpDecompiler decompiler = new CSharpDecompiler(typeSystem, settings); - decompiler.AstTransforms.Insert(0, new RemoveEmbeddedAtttributes()); + decompiler.AstTransforms.Insert(0, new RemoveEmbeddedAttributes()); decompiler.AstTransforms.Insert(0, new RemoveCompilerAttribute()); decompiler.AstTransforms.Add(new EscapeInvalidIdentifiers()); var syntaxTree = decompiler.DecompileWholeModuleAsSingleFile(); diff --git a/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj b/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj index a2852c603..5ba642215 100644 --- a/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj +++ b/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj @@ -32,7 +32,11 @@ - TRACE;DEBUG;NET46;ROSLYN;CS60;CS70 + TRACE;DEBUG;NET46;ROSLYN;CS60;CS70;CS71;CS72;CS73 + + + + TRACE;NET46;ROSLYN;CS60;CS70;CS71;CS72;CS73 diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Generics.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Generics.cs index f3ad3c213..563860434 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Generics.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Generics.cs @@ -96,5 +96,22 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty { return new T[size1, size2]; } + +#if CS73 + public static object CallDelegate(T input) where T : Delegate + { + return input.DynamicInvoke(); + } + + public static int CountEnumerators() where T : Enum + { + return typeof(T).GetEnumValues().Length; + } + + public unsafe static int UnmanagedConstraint() where T : unmanaged + { + return sizeof(T); + } +#endif } } diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Generics.opt.roslyn.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Generics.opt.roslyn.il index 3112d5a7a..eaa8d1c15 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Generics.opt.roslyn.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Generics.opt.roslyn.il @@ -33,6 +33,40 @@ // =============== CLASS MEMBERS DECLARATION =================== +.class private auto ansi sealed beforefieldinit Microsoft.CodeAnalysis.EmbeddedAttribute + extends [mscorlib]System.Attribute +{ + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void Microsoft.CodeAnalysis.EmbeddedAttribute::.ctor() = ( 01 00 00 00 ) + .method public hidebysig specialname rtspecialname + instance void .ctor() cil managed + { + // Code size 7 (0x7) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Attribute::.ctor() + IL_0006: ret + } // end of method EmbeddedAttribute::.ctor + +} // end of class Microsoft.CodeAnalysis.EmbeddedAttribute + +.class private auto ansi sealed beforefieldinit System.Runtime.CompilerServices.IsUnmanagedAttribute + extends [mscorlib]System.Attribute +{ + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void Microsoft.CodeAnalysis.EmbeddedAttribute::.ctor() = ( 01 00 00 00 ) + .method public hidebysig specialname rtspecialname + instance void .ctor() cil managed + { + // Code size 7 (0x7) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Attribute::.ctor() + IL_0006: ret + } // end of method IsUnmanagedAttribute::.ctor + +} // end of class System.Runtime.CompilerServices.IsUnmanagedAttribute + .class private auto ansi beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.Pretty.Generics extends [mscorlib]System.Object { @@ -222,6 +256,40 @@ IL_0007: ret } // end of method Generics::NewArray + .method public hidebysig static object + CallDelegate<([mscorlib]System.Delegate) T>(!!T input) cil managed + { + // Code size 18 (0x12) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: box !!T + IL_0006: ldc.i4.0 + IL_0007: newarr [mscorlib]System.Object + IL_000c: callvirt instance object [mscorlib]System.Delegate::DynamicInvoke(object[]) + IL_0011: ret + } // end of method Generics::CallDelegate + + .method public hidebysig static int32 CountEnumerators<([mscorlib]System.Enum) T>() cil managed + { + // Code size 21 (0x15) + .maxstack 8 + IL_0000: ldtoken !!T + IL_0005: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle) + IL_000a: callvirt instance class [mscorlib]System.Array [mscorlib]System.Type::GetEnumValues() + IL_000f: callvirt instance int32 [mscorlib]System.Array::get_Length() + IL_0014: ret + } // end of method Generics::CountEnumerators + + .method public hidebysig static int32 UnmanagedConstraint() cil managed + { + .param type T + .custom instance void System.Runtime.CompilerServices.IsUnmanagedAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 7 (0x7) + .maxstack 8 + IL_0000: sizeof !!T + IL_0006: ret + } // end of method Generics::UnmanagedConstraint + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Generics.roslyn.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Generics.roslyn.il index a433f6f70..948034d46 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Generics.roslyn.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Generics.roslyn.il @@ -33,6 +33,42 @@ // =============== CLASS MEMBERS DECLARATION =================== +.class private auto ansi sealed beforefieldinit Microsoft.CodeAnalysis.EmbeddedAttribute + extends [mscorlib]System.Attribute +{ + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void Microsoft.CodeAnalysis.EmbeddedAttribute::.ctor() = ( 01 00 00 00 ) + .method public hidebysig specialname rtspecialname + instance void .ctor() cil managed + { + // Code size 8 (0x8) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Attribute::.ctor() + IL_0006: nop + IL_0007: ret + } // end of method EmbeddedAttribute::.ctor + +} // end of class Microsoft.CodeAnalysis.EmbeddedAttribute + +.class private auto ansi sealed beforefieldinit System.Runtime.CompilerServices.IsUnmanagedAttribute + extends [mscorlib]System.Attribute +{ + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void Microsoft.CodeAnalysis.EmbeddedAttribute::.ctor() = ( 01 00 00 00 ) + .method public hidebysig specialname rtspecialname + instance void .ctor() cil managed + { + // Code size 8 (0x8) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Attribute::.ctor() + IL_0006: nop + IL_0007: ret + } // end of method IsUnmanagedAttribute::.ctor + +} // end of class System.Runtime.CompilerServices.IsUnmanagedAttribute + .class private auto ansi beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.Pretty.Generics extends [mscorlib]System.Object { @@ -298,6 +334,58 @@ IL_000c: ret } // end of method Generics::NewArray + .method public hidebysig static object + CallDelegate<([mscorlib]System.Delegate) T>(!!T input) cil managed + { + // Code size 23 (0x17) + .maxstack 2 + .locals init (object V_0) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: box !!T + IL_0007: ldc.i4.0 + IL_0008: newarr [mscorlib]System.Object + IL_000d: callvirt instance object [mscorlib]System.Delegate::DynamicInvoke(object[]) + IL_0012: stloc.0 + IL_0013: br.s IL_0015 + + IL_0015: ldloc.0 + IL_0016: ret + } // end of method Generics::CallDelegate + + .method public hidebysig static int32 CountEnumerators<([mscorlib]System.Enum) T>() cil managed + { + // Code size 26 (0x1a) + .maxstack 1 + .locals init (int32 V_0) + IL_0000: nop + IL_0001: ldtoken !!T + IL_0006: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle) + IL_000b: callvirt instance class [mscorlib]System.Array [mscorlib]System.Type::GetEnumValues() + IL_0010: callvirt instance int32 [mscorlib]System.Array::get_Length() + IL_0015: stloc.0 + IL_0016: br.s IL_0018 + + IL_0018: ldloc.0 + IL_0019: ret + } // end of method Generics::CountEnumerators + + .method public hidebysig static int32 UnmanagedConstraint() cil managed + { + .param type T + .custom instance void System.Runtime.CompilerServices.IsUnmanagedAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 12 (0xc) + .maxstack 1 + .locals init (int32 V_0) + IL_0000: nop + IL_0001: sizeof !!T + IL_0007: stloc.0 + IL_0008: br.s IL_000a + + IL_000a: ldloc.0 + IL_000b: ret + } // end of method Generics::UnmanagedConstraint + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs b/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs index 2dbb0abc3..566e60079 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs @@ -1730,7 +1730,11 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax c.BaseTypes.Add(new PrimitiveType("class")); } } else if (tp.HasValueTypeConstraint) { - c.BaseTypes.Add(new PrimitiveType("struct")); + if (tp.HasUnmanagedConstraint) { + c.BaseTypes.Add(new PrimitiveType("unmanaged")); + } else { + c.BaseTypes.Add(new PrimitiveType("struct")); + } } foreach (IType t in tp.DirectBaseTypes) { if (!IsObjectOrValueType(t)) diff --git a/ICSharpCode.Decompiler/DecompilerSettings.cs b/ICSharpCode.Decompiler/DecompilerSettings.cs index 516ee6b88..f86ea0743 100644 --- a/ICSharpCode.Decompiler/DecompilerSettings.cs +++ b/ICSharpCode.Decompiler/DecompilerSettings.cs @@ -89,7 +89,7 @@ namespace ICSharpCode.Decompiler nonTrailingNamedArguments = false; } if (languageVersion < CSharp.LanguageVersion.CSharp7_3) { - //introduceUnmanagedTypeConstraint = false; + introduceUnmanagedConstraint = false; stackAllocInitializers = false; tupleComparisons = false; } @@ -100,7 +100,7 @@ namespace ICSharpCode.Decompiler public CSharp.LanguageVersion GetMinimumRequiredVersion() { - if (tupleComparisons || stackAllocInitializers) + if (introduceUnmanagedConstraint || tupleComparisons || stackAllocInitializers) return CSharp.LanguageVersion.CSharp7_3; if (introduceRefModifiersOnStructs || introduceReadonlyAndInModifiers || nonTrailingNamedArguments) return CSharp.LanguageVersion.CSharp7_2; @@ -687,6 +687,22 @@ namespace ICSharpCode.Decompiler } } + bool introduceUnmanagedConstraint = true; + + /// + /// If this option is active, [IsUnmanagedAttribute] on type parameters + /// is replaced with "T : unmanaged" constraints. + /// + public bool IntroduceUnmanagedConstraint { + get { return introduceUnmanagedConstraint; } + set { + if (introduceUnmanagedConstraint != value) { + introduceUnmanagedConstraint = value; + OnPropertyChanged(); + } + } + } + bool stackAllocInitializers = true; /// diff --git a/ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs b/ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs index c30cf174f..04ce3ef8f 100644 --- a/ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs +++ b/ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs @@ -94,14 +94,20 @@ namespace ICSharpCode.Decompiler.TypeSystem /// RefStructs = 0x100, /// + /// If this option is active, [IsUnmanagedAttribute] is removed from type parameters, + /// and HasUnmanagedConstraint is set instead. + /// + UnmanagedConstraints = 0x200, + /// /// If this option is active, [NullableAttribute] is removed and reference types with /// nullability annotations are used instead. /// - NullabilityAnnotations = 0x200, + NullabilityAnnotations = 0x400, /// /// Default settings: typical options for the decompiler, with all C# languages features enabled. /// - Default = Dynamic | Tuple | ExtensionMethods | DecimalConstants | ReadOnlyStructsAndParameters | RefStructs + Default = Dynamic | Tuple | ExtensionMethods | DecimalConstants | ReadOnlyStructsAndParameters + | RefStructs | UnmanagedConstraints | NullabilityAnnotations } /// @@ -127,6 +133,8 @@ namespace ICSharpCode.Decompiler.TypeSystem typeSystemOptions |= TypeSystemOptions.RefStructs; if (settings.IntroduceReadonlyAndInModifiers) typeSystemOptions |= TypeSystemOptions.ReadOnlyStructsAndParameters; + if (settings.IntroduceUnmanagedConstraint) + typeSystemOptions |= TypeSystemOptions.UnmanagedConstraints; if (settings.NullableReferenceTypes) typeSystemOptions |= TypeSystemOptions.NullabilityAnnotations; return typeSystemOptions; diff --git a/ICSharpCode.Decompiler/TypeSystem/ITypeParameter.cs b/ICSharpCode.Decompiler/TypeSystem/ITypeParameter.cs index 27a5c9cc4..722b550d5 100644 --- a/ICSharpCode.Decompiler/TypeSystem/ITypeParameter.cs +++ b/ICSharpCode.Decompiler/TypeSystem/ITypeParameter.cs @@ -83,10 +83,15 @@ namespace ICSharpCode.Decompiler.TypeSystem bool HasReferenceTypeConstraint { get; } /// - /// Gets if the type parameter has the 'struct' constraint. + /// Gets if the type parameter has the 'struct' or 'unmanaged' constraint. /// bool HasValueTypeConstraint { get; } + /// + /// Gets if the type parameter has the 'unmanaged' constraint. + /// + bool HasUnmanagedConstraint { get; } + /// /// Nullability of the reference type constraint. (e.g. "where T : class?"). /// diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/AbstractTypeParameter.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/AbstractTypeParameter.cs index 632dee0d2..7ad3d137c 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/AbstractTypeParameter.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/AbstractTypeParameter.cs @@ -158,6 +158,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation public abstract bool HasDefaultConstructorConstraint { get; } public abstract bool HasReferenceTypeConstraint { get; } public abstract bool HasValueTypeConstraint { get; } + public abstract bool HasUnmanagedConstraint { get; } public abstract Nullability NullabilityConstraint { get; } public TypeKind Kind { diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/AttributeListBuilder.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/AttributeListBuilder.cs index e30b05ea2..fc3f2e385 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/AttributeListBuilder.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/AttributeListBuilder.cs @@ -169,7 +169,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation #endregion #region Custom Attributes (ReadAttribute) - public void Add(CustomAttributeHandleCollection attributes) + public void Add(CustomAttributeHandleCollection attributes, SymbolKind target) { var metadata = module.metadata; foreach (var handle in attributes) { @@ -177,14 +177,14 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation // Attribute types shouldn't be generic (and certainly not open), so we don't need a generic context. var ctor = module.ResolveMethod(attribute.Constructor, new GenericContext()); var type = ctor.DeclaringType; - if (IgnoreAttribute(type)) { + if (IgnoreAttribute(type, target)) { continue; } Add(new CustomAttribute(module, ctor, handle)); } } - bool IgnoreAttribute(IType attributeType) + bool IgnoreAttribute(IType attributeType, SymbolKind target) { if (attributeType.DeclaringType != null || attributeType.TypeParameterCount != 0) return false; @@ -199,18 +199,20 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation case "ExtensionAttribute": return (options & TypeSystemOptions.ExtensionMethods) != 0; case "DecimalConstantAttribute": - return (options & TypeSystemOptions.DecimalConstants) != 0; + return (options & TypeSystemOptions.DecimalConstants) != 0 && target == SymbolKind.Field; case "IsReadOnlyAttribute": return (options & TypeSystemOptions.ReadOnlyStructsAndParameters) != 0; case "IsByRefLikeAttribute": - return (options & TypeSystemOptions.RefStructs) != 0; + return (options & TypeSystemOptions.RefStructs) != 0 && target == SymbolKind.TypeDefinition; + case "IsUnmanagedAttribute": + return (options & TypeSystemOptions.UnmanagedConstraints) != 0 && target == SymbolKind.TypeParameter; case "NullableAttribute": return (options & TypeSystemOptions.NullabilityAnnotations) != 0; default: return false; } case "System": - return attributeType.Name == "ParamArrayAttribute"; + return attributeType.Name == "ParamArrayAttribute" && target == SymbolKind.Parameter; default: return false; } diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultTypeParameter.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultTypeParameter.cs index 21f21ab7e..e99e17af7 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultTypeParameter.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultTypeParameter.cs @@ -69,6 +69,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation public override bool HasValueTypeConstraint => hasValueTypeConstraint; public override bool HasReferenceTypeConstraint => hasReferenceTypeConstraint; public override bool HasDefaultConstructorConstraint => hasDefaultConstructorConstraint; + public override bool HasUnmanagedConstraint => false; public override Nullability NullabilityConstraint => nullabilityConstraint; public override IEnumerable DirectBaseTypes { diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/DummyTypeParameter.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/DummyTypeParameter.cs index eb80028ba..6251abf67 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/DummyTypeParameter.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/DummyTypeParameter.cs @@ -162,21 +162,11 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation IReadOnlyCollection ITypeParameter.EffectiveInterfaceSet { get { return EmptyList.Instance; } } - - bool ITypeParameter.HasDefaultConstructorConstraint { - get { return false; } - } - - bool ITypeParameter.HasReferenceTypeConstraint { - get { return false; } - } - - bool ITypeParameter.HasValueTypeConstraint { - get { return false; } - } - Nullability ITypeParameter.NullabilityConstraint { - get { return Nullability.Oblivious; } - } + bool ITypeParameter.HasDefaultConstructorConstraint => false; + bool ITypeParameter.HasReferenceTypeConstraint => false; + bool ITypeParameter.HasValueTypeConstraint => false; + bool ITypeParameter.HasUnmanagedConstraint => false; + Nullability ITypeParameter.NullabilityConstraint => Nullability.Oblivious; } } diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/KnownAttributes.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/KnownAttributes.cs index 98b74d2a0..7cee38c46 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/KnownAttributes.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/KnownAttributes.cs @@ -86,6 +86,9 @@ namespace ICSharpCode.Decompiler.TypeSystem CallerFilePath, CallerLineNumber, + // Type parameter attributes: + IsUnmanaged, + // Marshalling attributes: MarshalAs, @@ -143,6 +146,8 @@ namespace ICSharpCode.Decompiler.TypeSystem new TopLevelTypeName("System.Runtime.CompilerServices", nameof(CallerMemberNameAttribute)), new TopLevelTypeName("System.Runtime.CompilerServices", nameof(CallerFilePathAttribute)), new TopLevelTypeName("System.Runtime.CompilerServices", nameof(CallerLineNumberAttribute)), + // Type parameter attributes: + new TopLevelTypeName("System.Runtime.CompilerServices", "IsUnmanagedAttribute"), // Marshalling attributes: new TopLevelTypeName("System.Runtime.InteropServices", nameof(MarshalAsAttribute)), // Security attributes: diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataEvent.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataEvent.cs index 92cf56448..43c4a868a 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataEvent.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataEvent.cs @@ -107,7 +107,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation var b = new AttributeListBuilder(module); var metadata = module.metadata; var eventDef = metadata.GetEventDefinition(handle); - b.Add(eventDef.GetCustomAttributes()); + b.Add(eventDef.GetCustomAttributes(), SymbolKind.Event); return b.Build(); } #endregion diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataField.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataField.cs index cc879d18b..9ff7a1849 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataField.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataField.cs @@ -146,7 +146,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation } b.AddMarshalInfo(fieldDef.GetMarshallingDescriptor()); - b.Add(fieldDef.GetCustomAttributes()); + b.Add(fieldDef.GetCustomAttributes(), SymbolKind.Field); return b.Build(); } diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataMethod.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataMethod.cs index 2af5acbcb..a7fec43e8 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataMethod.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataMethod.cs @@ -363,7 +363,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation } #endregion - b.Add(def.GetCustomAttributes()); + b.Add(def.GetCustomAttributes(), symbolKind); b.AddSecurityAttributes(def.GetDeclarativeSecurityAttributes()); return b.Build(); @@ -381,7 +381,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation var retParam = metadata.GetParameter(parameters.First()); if (retParam.SequenceNumber == 0) { b.AddMarshalInfo(retParam.GetMarshallingDescriptor()); - b.Add(retParam.GetCustomAttributes()); + b.Add(retParam.GetCustomAttributes(), symbolKind); } } return b.Build(); diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataParameter.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataParameter.cs index b49956c0d..24f1c219c 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataParameter.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataParameter.cs @@ -72,7 +72,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation if ((attributes & ParameterAttributes.Out) == ParameterAttributes.Out) b.Add(KnownAttribute.Out); } - b.Add(parameter.GetCustomAttributes()); + b.Add(parameter.GetCustomAttributes(), SymbolKind.Parameter); b.AddMarshalInfo(parameter.GetMarshallingDescriptor()); return b.Build(); diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataProperty.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataProperty.cs index 682848666..f0204a4b9 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataProperty.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataProperty.cs @@ -155,7 +155,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation if (IsIndexer && Name != "Item" && !IsExplicitInterfaceImplementation) { b.Add(KnownAttribute.IndexerName, KnownTypeCode.String, Name); } - b.Add(propertyDef.GetCustomAttributes()); + b.Add(propertyDef.GetCustomAttributes(), symbolKind); return b.Build(); } #endregion diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeDefinition.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeDefinition.cs index a74248972..91ad0be3b 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeDefinition.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeDefinition.cs @@ -372,7 +372,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation } #endregion - b.Add(typeDefinition.GetCustomAttributes()); + b.Add(typeDefinition.GetCustomAttributes(), SymbolKind.TypeDefinition); b.AddSecurityAttributes(typeDefinition.GetDeclarativeSecurityAttributes()); return b.Build(); diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeParameter.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeParameter.cs index 7e41621e4..8c84c0500 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeParameter.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeParameter.cs @@ -35,6 +35,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation // lazy-loaded: IReadOnlyList constraints; + byte unmanagedConstraint = ThreeState.Unknown; const byte nullabilityNotYetLoaded = 255; byte nullabilityConstraint = nullabilityNotYetLoaded; @@ -106,7 +107,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation var attributes = gp.GetCustomAttributes(); var b = new AttributeListBuilder(module, attributes.Count); - b.Add(attributes); + b.Add(attributes, SymbolKind.TypeParameter); return b.Build(); } @@ -114,6 +115,24 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation public override bool HasReferenceTypeConstraint => (attr & GenericParameterAttributes.ReferenceTypeConstraint) != 0; public override bool HasValueTypeConstraint => (attr & GenericParameterAttributes.NotNullableValueTypeConstraint) != 0; + public override bool HasUnmanagedConstraint { + get { + if (unmanagedConstraint == ThreeState.Unknown) { + unmanagedConstraint = ThreeState.From(LoadUnmanagedConstraint()); + } + return unmanagedConstraint == ThreeState.True; + } + } + + private bool LoadUnmanagedConstraint() + { + if ((module.TypeSystemOptions & TypeSystemOptions.UnmanagedConstraints) == 0) + return false; + var metadata = module.metadata; + var gp = metadata.GetGenericParameter(handle); + return gp.GetCustomAttributes().HasKnownAttribute(metadata, KnownAttribute.IsUnmanaged); + } + public override Nullability NullabilityConstraint { get { if (nullabilityConstraint == nullabilityNotYetLoaded) { diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/NullabilityAnnotatedType.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/NullabilityAnnotatedType.cs index 4ea5d8eb3..6721692a7 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/NullabilityAnnotatedType.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/NullabilityAnnotatedType.cs @@ -90,6 +90,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation bool ITypeParameter.HasDefaultConstructorConstraint => baseType.HasDefaultConstructorConstraint; bool ITypeParameter.HasReferenceTypeConstraint => baseType.HasReferenceTypeConstraint; bool ITypeParameter.HasValueTypeConstraint => baseType.HasValueTypeConstraint; + bool ITypeParameter.HasUnmanagedConstraint => baseType.HasUnmanagedConstraint; Nullability ITypeParameter.NullabilityConstraint => baseType.NullabilityConstraint; SymbolKind ISymbol.SymbolKind => SymbolKind.TypeParameter; IEnumerable ITypeParameter.GetAttributes() => baseType.GetAttributes(); diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedMethod.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedMethod.cs index fc4193508..a5e7079c2 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedMethod.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedMethod.cs @@ -242,17 +242,10 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation return o != null && baseTp.Equals(o.baseTp) && this.Owner.Equals(o.Owner); } - public override bool HasValueTypeConstraint { - get { return baseTp.HasValueTypeConstraint; } - } - - public override bool HasReferenceTypeConstraint { - get { return baseTp.HasReferenceTypeConstraint; } - } - - public override bool HasDefaultConstructorConstraint { - get { return baseTp.HasDefaultConstructorConstraint; } - } + public override bool HasValueTypeConstraint => baseTp.HasValueTypeConstraint; + public override bool HasReferenceTypeConstraint => baseTp.HasReferenceTypeConstraint; + public override bool HasDefaultConstructorConstraint => baseTp.HasDefaultConstructorConstraint; + public override bool HasUnmanagedConstraint => baseTp.HasUnmanagedConstraint; public override Nullability NullabilityConstraint => baseTp.NullabilityConstraint; diff --git a/ICSharpCode.Decompiler/TypeSystem/MetadataModule.cs b/ICSharpCode.Decompiler/TypeSystem/MetadataModule.cs index 925afed1e..ec6b0a9e7 100644 --- a/ICSharpCode.Decompiler/TypeSystem/MetadataModule.cs +++ b/ICSharpCode.Decompiler/TypeSystem/MetadataModule.cs @@ -598,7 +598,7 @@ namespace ICSharpCode.Decompiler.TypeSystem var b = new AttributeListBuilder(this); if (metadata.IsAssembly) { var assembly = metadata.GetAssemblyDefinition(); - b.Add(metadata.GetCustomAttributes(Handle.AssemblyDefinition)); + b.Add(metadata.GetCustomAttributes(Handle.AssemblyDefinition), SymbolKind.Module); b.AddSecurityAttributes(assembly.GetDeclarativeSecurityAttributes()); // AssemblyVersionAttribute @@ -617,7 +617,7 @@ namespace ICSharpCode.Decompiler.TypeSystem public IEnumerable GetModuleAttributes() { var b = new AttributeListBuilder(this); - b.Add(metadata.GetCustomAttributes(Handle.ModuleDefinition)); + b.Add(metadata.GetCustomAttributes(Handle.ModuleDefinition), SymbolKind.Module); if (!metadata.IsAssembly) { AddTypeForwarderAttributes(ref b); }