Browse Source

#1349: Fix type substitution for members of unknown generic types (due to unresolved references)

Also, assume that unknown inputs to ldfld are temporaries, not unmanaged pointers.
This avoids emitting weird pointer casts when accessing fields on unresolved value types.
pull/1612/head
Daniel Grunwald 6 years ago
parent
commit
c366235246
  1. 6
      ICSharpCode.Decompiler/IL/ILReader.cs
  2. 4
      ICSharpCode.Decompiler/IL/Instructions/LdFlda.cs
  3. 8
      ICSharpCode.Decompiler/TypeSystem/MetadataModule.cs

6
ICSharpCode.Decompiler/IL/ILReader.cs

@ -1187,14 +1187,14 @@ namespace ICSharpCode.Decompiler.IL
return Pop(StackType.O); return Pop(StackType.O);
case false: case false:
// field of value type: ldfld can handle temporaries // field of value type: ldfld can handle temporaries
if (PeekStackType() == StackType.O) if (PeekStackType() == StackType.O || PeekStackType() == StackType.Unknown)
return new AddressOf(Pop()); return new AddressOf(Pop());
else else
return PopPointer(); return PopPointer();
default: default:
// field in unresolved type // field in unresolved type
if (PeekStackType() == StackType.O) if (PeekStackType() == StackType.O || PeekStackType() == StackType.Unknown)
return Pop(StackType.O); return Pop();
else else
return PopPointer(); return PopPointer();
} }

4
ICSharpCode.Decompiler/IL/Instructions/LdFlda.cs

@ -36,7 +36,9 @@ namespace ICSharpCode.Decompiler.IL
break; break;
case null: case null:
// field of unresolved type // field of unresolved type
Debug.Assert(target.ResultType == StackType.O || target.ResultType == StackType.I || target.ResultType == StackType.Ref); Debug.Assert(target.ResultType == StackType.O || target.ResultType == StackType.I
|| target.ResultType == StackType.Ref || target.ResultType == StackType.Unknown,
"Field of unresolved type with invalid target");
break; break;
} }
} }

8
ICSharpCode.Decompiler/TypeSystem/MetadataModule.cs

@ -477,7 +477,9 @@ namespace ICSharpCode.Decompiler.TypeSystem
typeParameters.Add(new DefaultTypeParameter(m, i)); typeParameters.Add(new DefaultTypeParameter(m, i));
} }
m.TypeParameters = typeParameters; m.TypeParameters = typeParameters;
substitution = new TypeParameterSubstitution(null, typeParameters); substitution = new TypeParameterSubstitution(declaringType.TypeArguments, typeParameters);
} else if (declaringType.TypeArguments.Count > 0) {
substitution = declaringType.GetSubstitution();
} }
var parameters = new List<IParameter>(); var parameters = new List<IParameter>();
for (int i = 0; i < signature.RequiredParameterCount; i++) { for (int i = 0; i < signature.RequiredParameterCount; i++) {
@ -553,6 +555,10 @@ namespace ICSharpCode.Decompiler.TypeSystem
var field = declaringType.GetFields(f => f.Name == name && CompareTypes(f.ReturnType, signature), var field = declaringType.GetFields(f => f.Name == name && CompareTypes(f.ReturnType, signature),
GetMemberOptions.IgnoreInheritedMembers).FirstOrDefault(); GetMemberOptions.IgnoreInheritedMembers).FirstOrDefault();
if (field == null) { if (field == null) {
// If it's a field in a generic type, we need to substitute the type arguments:
if (declaringType.TypeArguments.Count > 0) {
signature = signature.AcceptVisitor(declaringType.GetSubstitution());
}
field = new FakeField(Compilation) { field = new FakeField(Compilation) {
ReturnType = signature, ReturnType = signature,
Name = name, Name = name,

Loading…
Cancel
Save