Browse Source

Fix 'this' type in generic classes/structs.

pull/728/head
Daniel Grunwald 9 years ago
parent
commit
184b371f72
  1. 28
      ICSharpCode.Decompiler/IL/ILReader.cs
  2. 8
      ICSharpCode.Decompiler/Tests/TestCases/Generics.cs
  3. 20
      ICSharpCode.Decompiler/Tests/TestCases/ValueTypeCall.cs

28
ICSharpCode.Decompiler/IL/ILReader.cs

@ -138,8 +138,32 @@ namespace ICSharpCode.Decompiler.IL @@ -138,8 +138,32 @@ namespace ICSharpCode.Decompiler.IL
ILVariable CreateILVariable(ParameterDefinition p)
{
var variableKind = p.Index == -1 ? VariableKind.This : VariableKind.Parameter;
var ilVar = new ILVariable(variableKind, typeSystem.Resolve(p.ParameterType), p.Index);
VariableKind variableKind;
IType parameterType;
if (p.Index == -1) {
variableKind = VariableKind.This;
// Manually construct ctor parameter type due to Cecil bug:
// https://github.com/jbevain/cecil/issues/275
ITypeDefinition def = typeSystem.Resolve(body.Method.DeclaringType).GetDefinition();
if (def != null && def.TypeParameterCount > 0) {
parameterType = new ParameterizedType(def, def.TypeArguments);
if (def.IsReferenceType == false) {
parameterType = new NRefactory.TypeSystem.ByReferenceType(parameterType);
}
} else {
parameterType = typeSystem.Resolve(p.ParameterType);
}
} else {
variableKind = VariableKind.Parameter;
parameterType = typeSystem.Resolve(p.ParameterType);
}
Debug.Assert(!parameterType.IsUnbound());
if (parameterType.IsUnbound()) {
// parameter types should not be unbound, the only known cause for these is a Cecil bug:
Debug.Assert(p.Index < 0); // cecil bug occurs only for "this"
parameterType = new ParameterizedType(parameterType.GetDefinition(), parameterType.TypeArguments);
}
var ilVar = new ILVariable(variableKind, parameterType, p.Index);
ilVar.StoreCount = 1; // count the initial store when the method is called with an argument
if (variableKind == VariableKind.This)
ilVar.Name = "this";

8
ICSharpCode.Decompiler/Tests/TestCases/Generics.cs

@ -48,4 +48,12 @@ namespace Generics @@ -48,4 +48,12 @@ namespace Generics
Console.WriteLine(typeof(T1) + " " + typeof(T2));
}
}
class GenericClass<T>
{
public void M(out GenericClass<T> self)
{
self = this;
}
}
}

20
ICSharpCode.Decompiler/Tests/TestCases/ValueTypeCall.cs

@ -13,6 +13,24 @@ namespace ValueTypeCall @@ -13,6 +13,24 @@ namespace ValueTypeCall
}
}
public struct GenericValueType<T>
{
T data;
int num;
public GenericValueType(T data)
{
this.data = data;
this.num = 1;
}
public void Call(ref GenericValueType<T> v)
{
num++;
Console.WriteLine("Call #{0}: {1} with v=#{2}", num, data, v.num);
}
}
public class Program
{
public static void Main()
@ -22,6 +40,8 @@ namespace ValueTypeCall @@ -22,6 +40,8 @@ namespace ValueTypeCall
ValueParameter(m);
Field();
Box();
var gvt = new GenericValueType<string>("Test");
gvt.Call(ref gvt);
}
static void RefParameter(ref MutValueType m)

Loading…
Cancel
Save