Browse Source

Fixed post-increment operator on fields in generic classes.

pull/100/head
Daniel Grunwald 15 years ago
parent
commit
fe4b3d44a0
  1. 15
      ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs
  2. 2
      ICSharpCode.Decompiler/Ast/Transforms/DelegateConstruction.cs
  3. 12
      ICSharpCode.Decompiler/ILAst/PeepholeTransform.cs
  4. 7
      ICSharpCode.Decompiler/ILAst/SimpleControlFlow.cs
  5. 31
      ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs

15
ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs

@ -518,7 +518,10 @@ namespace ICSharpCode.Decompiler.Ast @@ -518,7 +518,10 @@ namespace ICSharpCode.Decompiler.Ast
AstBuilder.ConvertType(((FieldReference)operand).DeclaringType)
.Member(((FieldReference)operand).Name).WithAnnotation(operand),
arg1);
case ILCode.Ldflda: return MakeRef(arg1.Member(((FieldReference) operand).Name).WithAnnotation(operand));
case ILCode.Ldflda:
if (arg1 is DirectionExpression)
arg1 = ((DirectionExpression)arg1).Expression.Detach();
return MakeRef(arg1.Member(((FieldReference) operand).Name).WithAnnotation(operand));
case ILCode.Ldsflda:
return MakeRef(
AstBuilder.ConvertType(((FieldReference)operand).DeclaringType)
@ -715,7 +718,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -715,7 +718,7 @@ namespace ICSharpCode.Decompiler.Ast
}
if (target is ThisReferenceExpression && !isVirtual) {
// a non-virtual call on "this" might be a "base"-call.
if ((cecilMethod.DeclaringType.IsGenericInstance ? cecilMethod.DeclaringType.GetElementType() : cecilMethod.DeclaringType) != methodDef.DeclaringType) {
if (cecilMethod.DeclaringType.GetElementType() != methodDef.DeclaringType) {
// If we're not calling a method in the current class; we must be calling one in the base class.
target = new BaseReferenceExpression();
}
@ -898,7 +901,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -898,7 +901,7 @@ namespace ICSharpCode.Decompiler.Ast
Ast.Expression Convert(Ast.Expression expr, Cecil.TypeReference actualType, Cecil.TypeReference reqType)
{
if (reqType == null || actualType == reqType) {
if (actualType == null || reqType == null || TypeAnalysis.IsSameType(actualType, reqType)) {
return expr;
} else if (actualType is ByReferenceType && reqType is PointerType && expr is DirectionExpression) {
return Convert(
@ -943,12 +946,10 @@ namespace ICSharpCode.Decompiler.Ast @@ -943,12 +946,10 @@ namespace ICSharpCode.Decompiler.Ast
}
bool actualIsPrimitiveType = actualIsIntegerOrEnum
|| (actualType != null && (actualType.MetadataType == MetadataType.Single || actualType.MetadataType == MetadataType.Double));
|| actualType.MetadataType == MetadataType.Single || actualType.MetadataType == MetadataType.Double;
bool requiredIsPrimitiveType = requiredIsIntegerOrEnum
|| (reqType != null && (reqType.MetadataType == MetadataType.Single || reqType.MetadataType == MetadataType.Double));
|| reqType.MetadataType == MetadataType.Single || reqType.MetadataType == MetadataType.Double;
if (actualIsPrimitiveType && requiredIsPrimitiveType) {
if (actualType.FullName == reqType.FullName)
return expr;
return expr.CastTo(AstBuilder.ConvertType(reqType));
}
return expr;

2
ICSharpCode.Decompiler/Ast/Transforms/DelegateConstruction.cs

@ -58,7 +58,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms @@ -58,7 +58,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
methodIdent.Remove();
if (!annotation.IsVirtual && obj is ThisReferenceExpression) {
// maybe it's getting the pointer of a base method?
if (method.DeclaringType != context.CurrentType) {
if (method.DeclaringType.GetElementType() != context.CurrentType) {
obj = new BaseReferenceExpression();
}
}

12
ICSharpCode.Decompiler/ILAst/PeepholeTransform.cs

@ -425,7 +425,7 @@ namespace ICSharpCode.Decompiler.ILAst @@ -425,7 +425,7 @@ namespace ICSharpCode.Decompiler.ILAst
MethodReference setter = setterOperand as MethodReference;
if (getter == null || setter == null)
return false;
if (getter.DeclaringType != setter.DeclaringType)
if (!TypeAnalysis.IsSameType(getter.DeclaringType, setter.DeclaringType))
return false;
MethodDefinition getterDef = getter.Resolve();
MethodDefinition setterDef = setter.Resolve();
@ -472,8 +472,16 @@ namespace ICSharpCode.Decompiler.ILAst @@ -472,8 +472,16 @@ namespace ICSharpCode.Decompiler.ILAst
return null;
if (expr.Code == ILCode.Stfld) {
if (!(initialValue.Code == ILCode.Ldfld && initialValue.Operand == expr.Operand))
if (initialValue.Code != ILCode.Ldfld)
return null;
// There might be two different FieldReference instances, so we compare the field's signatures:
FieldReference getField = (FieldReference)initialValue.Operand;
FieldReference setField = (FieldReference)expr.Operand;
if (!(TypeAnalysis.IsSameType(getField.DeclaringType, setField.DeclaringType)
&& getField.Name == setField.Name && TypeAnalysis.IsSameType(getField.FieldType, setField.FieldType)))
{
return null;
}
} else if (expr.Code == ILCode.Stobj) {
if (!(initialValue.Code == ILCode.Ldobj && initialValue.Operand == expr.Operand))
return null;

7
ICSharpCode.Decompiler/ILAst/SimpleControlFlow.cs

@ -63,6 +63,7 @@ namespace ICSharpCode.Decompiler.ILAst @@ -63,6 +63,7 @@ namespace ICSharpCode.Decompiler.ILAst
bool isStloc = trueLocVar != null;
ILCode opCode = isStloc ? ILCode.Stloc : ILCode.Ret;
TypeReference retType = isStloc ? trueLocVar.Type : this.context.CurrentMethod.ReturnType;
bool retTypeIsBoolean = TypeAnalysis.IsBoolean(retType);
int leftBoolVal;
int rightBoolVal;
ILExpression newExpr;
@ -72,7 +73,7 @@ namespace ICSharpCode.Decompiler.ILAst @@ -72,7 +73,7 @@ namespace ICSharpCode.Decompiler.ILAst
// a ? b : true is equivalent to !a || b
// a ? b : false is equivalent to a && b
// a ? false : b is equivalent to !a && b
if (retType == typeSystem.Boolean &&
if (retTypeIsBoolean &&
trueExpr.Match(ILCode.Ldc_I4, out leftBoolVal) &&
falseExpr.Match(ILCode.Ldc_I4, out rightBoolVal) &&
((leftBoolVal != 0 && rightBoolVal == 0) || (leftBoolVal == 0 && rightBoolVal != 0))
@ -84,14 +85,14 @@ namespace ICSharpCode.Decompiler.ILAst @@ -84,14 +85,14 @@ namespace ICSharpCode.Decompiler.ILAst
} else {
newExpr = new ILExpression(ILCode.LogicNot, null, condExpr);
}
} else if (retType == typeSystem.Boolean && trueExpr.Match(ILCode.Ldc_I4, out leftBoolVal)) {
} else if (retTypeIsBoolean && trueExpr.Match(ILCode.Ldc_I4, out leftBoolVal)) {
// It can be expressed as logical expression
if (leftBoolVal != 0) {
newExpr = MakeLeftAssociativeShortCircuit(ILCode.LogicOr, condExpr, falseExpr);
} else {
newExpr = MakeLeftAssociativeShortCircuit(ILCode.LogicAnd, new ILExpression(ILCode.LogicNot, null, condExpr), falseExpr);
}
} else if (retType == typeSystem.Boolean && falseExpr.Match(ILCode.Ldc_I4, out rightBoolVal)) {
} else if (retTypeIsBoolean && falseExpr.Match(ILCode.Ldc_I4, out rightBoolVal)) {
// It can be expressed as logical expression
if (rightBoolVal != 0) {
newExpr = MakeLeftAssociativeShortCircuit(ILCode.LogicOr, new ILExpression(ILCode.LogicNot, null, condExpr), trueExpr);

31
ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs

@ -231,7 +231,7 @@ namespace ICSharpCode.Decompiler.ILAst @@ -231,7 +231,7 @@ namespace ICSharpCode.Decompiler.ILAst
/// <returns>The inferred type</returns>
TypeReference InferTypeForExpression(ILExpression expr, TypeReference expectedType, bool forceInferChildren = false)
{
if (expectedType != null && expr.ExpectedType != expectedType) {
if (expectedType != null && !IsSameType(expr.ExpectedType, expectedType)) {
expr.ExpectedType = expectedType;
if (expr.Code != ILCode.Stloc) // stloc is special case and never gets re-evaluated
forceInferChildren = true;
@ -422,7 +422,7 @@ namespace ICSharpCode.Decompiler.ILAst @@ -422,7 +422,7 @@ namespace ICSharpCode.Decompiler.ILAst
if (forceInferChildren) {
if (pointerType is PointerType)
InferTypeForExpression(expr.Arguments[0], new PointerType(operandType));
else if (operandType != expr.Operand)
else if (!IsSameType(operandType, expr.Operand as TypeReference))
InferTypeForExpression(expr.Arguments[0], new ByReferenceType(operandType));
InferTypeForExpression(expr.Arguments[1], operandType);
}
@ -823,11 +823,11 @@ namespace ICSharpCode.Decompiler.ILAst @@ -823,11 +823,11 @@ namespace ICSharpCode.Decompiler.ILAst
ILExpression right = expr.Arguments[1];
TypeReference leftPreferred = DoInferTypeForExpression(left, expectedType);
TypeReference rightPreferred = DoInferTypeForExpression(right, expectedType);
if (leftPreferred == rightPreferred) {
if (IsSameType(leftPreferred, rightPreferred)) {
return left.InferredType = right.InferredType = left.ExpectedType = right.ExpectedType = leftPreferred;
} else if (rightPreferred == DoInferTypeForExpression(left, rightPreferred)) {
} else if (IsSameType(rightPreferred, DoInferTypeForExpression(left, rightPreferred))) {
return left.InferredType = right.InferredType = left.ExpectedType = right.ExpectedType = rightPreferred;
} else if (leftPreferred == DoInferTypeForExpression(right, leftPreferred)) {
} else if (IsSameType(leftPreferred, DoInferTypeForExpression(right, leftPreferred))) {
return left.InferredType = right.InferredType = left.ExpectedType = right.ExpectedType = leftPreferred;
} else {
left.ExpectedType = right.ExpectedType = TypeWithMoreInformation(leftPreferred, rightPreferred);
@ -852,11 +852,11 @@ namespace ICSharpCode.Decompiler.ILAst @@ -852,11 +852,11 @@ namespace ICSharpCode.Decompiler.ILAst
InferTypeForExpression(left, typeSystem.IntPtr);
right.InferredType = right.ExpectedType = rightPreferred;
return rightPreferred;
} else if (leftPreferred == rightPreferred) {
} else if (IsSameType(leftPreferred, rightPreferred)) {
return left.InferredType = right.InferredType = left.ExpectedType = right.ExpectedType = leftPreferred;
} else if (rightPreferred == DoInferTypeForExpression(left, rightPreferred)) {
} else if (IsSameType(rightPreferred, DoInferTypeForExpression(left, rightPreferred))) {
return left.InferredType = right.InferredType = left.ExpectedType = right.ExpectedType = rightPreferred;
} else if (leftPreferred == DoInferTypeForExpression(right, leftPreferred)) {
} else if (IsSameType(leftPreferred, DoInferTypeForExpression(right, leftPreferred))) {
return left.InferredType = right.InferredType = left.ExpectedType = right.ExpectedType = leftPreferred;
} else {
left.ExpectedType = right.ExpectedType = TypeWithMoreInformation(leftPreferred, rightPreferred);
@ -878,11 +878,11 @@ namespace ICSharpCode.Decompiler.ILAst @@ -878,11 +878,11 @@ namespace ICSharpCode.Decompiler.ILAst
return leftPreferred;
} else {
TypeReference rightPreferred = DoInferTypeForExpression(right, expectedType);
if (leftPreferred == rightPreferred) {
if (IsSameType(leftPreferred, rightPreferred)) {
return left.InferredType = right.InferredType = left.ExpectedType = right.ExpectedType = leftPreferred;
} else if (rightPreferred == DoInferTypeForExpression(left, rightPreferred)) {
} else if (IsSameType(rightPreferred, DoInferTypeForExpression(left, rightPreferred))) {
return left.InferredType = right.InferredType = left.ExpectedType = right.ExpectedType = rightPreferred;
} else if (leftPreferred == DoInferTypeForExpression(right, leftPreferred)) {
} else if (IsSameType(leftPreferred, DoInferTypeForExpression(right, leftPreferred))) {
return left.InferredType = right.InferredType = left.ExpectedType = right.ExpectedType = leftPreferred;
} else {
left.ExpectedType = right.ExpectedType = TypeWithMoreInformation(leftPreferred, rightPreferred);
@ -1049,5 +1049,14 @@ namespace ICSharpCode.Decompiler.ILAst @@ -1049,5 +1049,14 @@ namespace ICSharpCode.Decompiler.ILAst
v.Type = null;
}
}
public static bool IsSameType(TypeReference type1, TypeReference type2)
{
if (type1 == type2)
return true;
if (type1 == null || type2 == null)
return false;
return type1.FullName == type2.FullName; // TODO: implement this more efficiently?
}
}
}

Loading…
Cancel
Save