Browse Source

#1195: Remove modopts/modreqs from the type system; they confuse the decompiler.

pull/1243/head
Daniel Grunwald 7 years ago
parent
commit
79352d18d7
  1. 34
      ICSharpCode.Decompiler/TypeSystem/ApplyAttributeTypeVisitor.cs
  2. 13
      ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs
  3. 2
      ILSpy/LoadedAssembly.cs

34
ICSharpCode.Decompiler/TypeSystem/ApplyAttributeTypeVisitor.cs

@ -39,15 +39,12 @@ namespace ICSharpCode.Decompiler.TypeSystem
TypeSystemOptions options, TypeSystemOptions options,
bool typeChildrenOnly = false) bool typeChildrenOnly = false)
{ {
if ((options & (TypeSystemOptions.Dynamic | TypeSystemOptions.Tuple)) == TypeSystemOptions.None) {
return inputType;
}
bool useDynamicType = (options & TypeSystemOptions.Dynamic) != 0; bool useDynamicType = (options & TypeSystemOptions.Dynamic) != 0;
bool useTupleTypes = (options & TypeSystemOptions.Tuple) != 0; bool useTupleTypes = (options & TypeSystemOptions.Tuple) != 0;
bool hasDynamicAttribute = false; bool hasDynamicAttribute = false;
bool[] dynamicAttributeData = null; bool[] dynamicAttributeData = null;
string[] tupleElementNames = null; string[] tupleElementNames = null;
if (attributes != null) { if (attributes != null && (useDynamicType || useTupleTypes)) {
foreach (var attrHandle in attributes.Value) { foreach (var attrHandle in attributes.Value) {
var attr = metadata.GetCustomAttribute(attrHandle); var attr = metadata.GetCustomAttribute(attrHandle);
var attrType = attr.GetAttributeType(metadata); var attrType = attr.GetAttributeType(metadata);
@ -73,9 +70,9 @@ namespace ICSharpCode.Decompiler.TypeSystem
} }
} }
} }
if (hasDynamicAttribute || useTupleTypes) { if (hasDynamicAttribute || (options & (TypeSystemOptions.Tuple | TypeSystemOptions.KeepModifiers)) != TypeSystemOptions.KeepModifiers) {
var visitor = new ApplyAttributeTypeVisitor( var visitor = new ApplyAttributeTypeVisitor(
compilation, hasDynamicAttribute, dynamicAttributeData, useTupleTypes, tupleElementNames compilation, hasDynamicAttribute, dynamicAttributeData, options, tupleElementNames
); );
if (typeChildrenOnly) { if (typeChildrenOnly) {
return inputType.VisitChildren(visitor); return inputType.VisitChildren(visitor);
@ -90,20 +87,36 @@ namespace ICSharpCode.Decompiler.TypeSystem
readonly ICompilation compilation; readonly ICompilation compilation;
readonly bool hasDynamicAttribute; readonly bool hasDynamicAttribute;
readonly bool[] dynamicAttributeData; readonly bool[] dynamicAttributeData;
readonly bool useTupleTypes; readonly TypeSystemOptions options;
readonly string[] tupleElementNames; readonly string[] tupleElementNames;
int dynamicTypeIndex = 0; int dynamicTypeIndex = 0;
int tupleTypeIndex = 0; int tupleTypeIndex = 0;
private ApplyAttributeTypeVisitor(ICompilation compilation, bool hasDynamicAttribute, bool[] dynamicAttributeData, bool useTupleTypes, string[] tupleElementNames) private ApplyAttributeTypeVisitor(ICompilation compilation, bool hasDynamicAttribute, bool[] dynamicAttributeData, TypeSystemOptions options, string[] tupleElementNames)
{ {
this.compilation = compilation ?? throw new ArgumentNullException(nameof(compilation)); this.compilation = compilation ?? throw new ArgumentNullException(nameof(compilation));
this.hasDynamicAttribute = hasDynamicAttribute; this.hasDynamicAttribute = hasDynamicAttribute;
this.dynamicAttributeData = dynamicAttributeData; this.dynamicAttributeData = dynamicAttributeData;
this.useTupleTypes = useTupleTypes; this.options = options;
this.tupleElementNames = tupleElementNames; this.tupleElementNames = tupleElementNames;
} }
public override IType VisitModOpt(ModifiedType type)
{
if ((options & TypeSystemOptions.KeepModifiers) != 0)
return base.VisitModOpt(type);
else
return type.ElementType.AcceptVisitor(this);
}
public override IType VisitModReq(ModifiedType type)
{
if ((options & TypeSystemOptions.KeepModifiers) != 0)
return base.VisitModReq(type);
else
return type.ElementType.AcceptVisitor(this);
}
public override IType VisitPointerType(PointerType type) public override IType VisitPointerType(PointerType type)
{ {
dynamicTypeIndex++; dynamicTypeIndex++;
@ -124,6 +137,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
public override IType VisitParameterizedType(ParameterizedType type) public override IType VisitParameterizedType(ParameterizedType type)
{ {
bool useTupleTypes = (options & TypeSystemOptions.Tuple) != 0;
if (useTupleTypes && TupleType.IsTupleCompatible(type, out int tupleCardinality)) { if (useTupleTypes && TupleType.IsTupleCompatible(type, out int tupleCardinality)) {
if (tupleCardinality > 1) { if (tupleCardinality > 1) {
var valueTupleAssembly = type.GetDefinition()?.ParentModule; var valueTupleAssembly = type.GetDefinition()?.ParentModule;
@ -168,7 +182,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
} }
} }
// Visit generic type and type arguments. // Visit generic type and type arguments.
// Like base implementation, except that it increments typeIndex. // Like base implementation, except that it increments dynamicTypeIndex.
var genericType = type.GenericType.AcceptVisitor(this); var genericType = type.GenericType.AcceptVisitor(this);
bool changed = type.GenericType != genericType; bool changed = type.GenericType != genericType;
var arguments = new IType[type.TypeArguments.Count]; var arguments = new IType[type.TypeArguments.Count];

13
ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs

@ -71,13 +71,20 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// Also, some code in the decompiler expects to be able to compare type/member definitions by reference equality, /// Also, some code in the decompiler expects to be able to compare type/member definitions by reference equality,
/// and thus will fail with uncached type systems. /// and thus will fail with uncached type systems.
/// </summary> /// </summary>
Uncached = 16, Uncached = 0x10,
/// <summary> /// <summary>
/// If this option is active, [DecimalConstantAttribute] is removed and constant values are transformed into simple decimal literals. /// If this option is active, [DecimalConstantAttribute] is removed and constant values are transformed into simple decimal literals.
/// </summary> /// </summary>
DecimalConstants = 32, DecimalConstants = 0x20,
/// <summary> /// <summary>
/// Default settings: all features enabled. /// If this option is active, modopt and modreq types are preserved in the type system.
///
/// Note: the decompiler currently does not support handling modified types;
/// activating this option may lead to incorrect decompilation or internal errors.
/// </summary>
KeepModifiers = 0x40,
/// <summary>
/// Default settings: typical options for the decompiler, with all C# languages features enabled.
/// </summary> /// </summary>
Default = Dynamic | Tuple | ExtensionMethods | DecimalConstants Default = Dynamic | Tuple | ExtensionMethods | DecimalConstants
} }

2
ILSpy/LoadedAssembly.cs

@ -111,7 +111,7 @@ namespace ICSharpCode.ILSpy
if (module == null) if (module == null)
return null; return null;
return typeSystem = new SimpleCompilation( return typeSystem = new SimpleCompilation(
module.WithOptions(TypeSystemOptions.Default | TypeSystemOptions.Uncached), module.WithOptions(TypeSystemOptions.Default | TypeSystemOptions.Uncached | TypeSystemOptions.KeepModifiers),
MinimalCorlib.Instance); MinimalCorlib.Instance);
} }

Loading…
Cancel
Save