Skip to content

Commit

Permalink
Fix icsharpcode#2039: "Could not convert BlockContainer to single exp…
Browse files Browse the repository at this point in the history
…ression" workaround produces uncompilable code - potentially unassigned variables.
  • Loading branch information
ElektroKill committed Aug 8, 2021
1 parent e640b80 commit 80c85bb
Showing 1 changed file with 22 additions and 14 deletions.
36 changes: 22 additions & 14 deletions ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1080,10 +1080,10 @@ TranslatedExpression FallBackToBytePointer()
return null;
if (inst.Operator == BinaryNumericOperator.Sub && inst.LeftInputType == StackType.Ref && inst.RightInputType == StackType.Ref) {
// ref - ref => i
return CallUnsafeIntrinsic("ByteOffset", new[] {
return CallUnsafeIntrinsic("ByteOffset", new[] {
// ByteOffset() expects the parameters the wrong way around, so order using named arguments
new NamedArgumentExpression("target", left.Expression),
new NamedArgumentExpression("origin", right.Expression)
new NamedArgumentExpression("target", left.Expression),
new NamedArgumentExpression("origin", right.Expression)
}, compilation.FindType(KnownTypeCode.IntPtr), inst);
}
if (inst.LeftInputType == StackType.Ref && inst.RightInputType.IsIntegerType()
Expand Down Expand Up @@ -1152,7 +1152,7 @@ TranslatedExpression EnsureIntegerType(TranslatedExpression expr)
{
if (!expr.Type.IsCSharpPrimitiveIntegerType() && !expr.Type.IsCSharpNativeIntegerType()) {
// pointer arithmetic accepts all primitive integer types, but no enums etc.
expr = expr.ConvertTo(FindArithmeticType(expr.Type.GetStackType(), expr.Type.GetSign()), this);
expr = expr.ConvertTo(FindArithmeticType(expr.Type.GetStackType(), expr.Type.GetSign()), this);
}
return expr;
}
Expand Down Expand Up @@ -1242,7 +1242,7 @@ bool IsMatchingPointerType(IType type)
return false;
}
}

TranslatedExpression HandleBinaryNumeric(BinaryNumericInstruction inst, BinaryOperatorType op, TranslationContext context)
{
var resolverWithOverflowCheck = resolver.WithCheckForOverflow(inst.CheckForOverflow);
Expand All @@ -1265,7 +1265,7 @@ TranslatedExpression HandleBinaryNumeric(BinaryNumericInstruction inst, BinaryOp

if (op == BinaryOperatorType.Subtract && inst.Left.MatchLdcI(0)) {
IType rightUType = NullableType.GetUnderlyingType(right.Type);
if (rightUType.IsKnownType(KnownTypeCode.Int32) || rightUType.IsKnownType(KnownTypeCode.Int64)
if (rightUType.IsKnownType(KnownTypeCode.Int32) || rightUType.IsKnownType(KnownTypeCode.Int64)
|| rightUType.IsCSharpSmallIntegerType() || rightUType.IsCSharpNativeIntegerType()) {
// unary minus is supported on signed int and long, and on the small integer types (since they promote to int)
var uoe = new UnaryOperatorExpression(UnaryOperatorType.Minus, right.Expression);
Expand Down Expand Up @@ -1335,7 +1335,7 @@ IType FindType(StackType stackType, Sign sign)

/// <summary>
/// Gets a type used for performing arithmetic with the stack type and sign.
///
///
/// This may result in a larger type than requested when the selected C# version
/// doesn't support native integers.
/// Should only be used after a call to PrepareArithmeticArgument()
Expand All @@ -1350,7 +1350,7 @@ IType FindArithmeticType(StackType stackType, Sign sign)
// If native integers are not available, use 64-bit arithmetic instead
stackType = StackType.I8;
}
}
}
return compilation.FindType(stackType.ToKnownTypeCode(sign));
}

Expand Down Expand Up @@ -2031,19 +2031,27 @@ protected internal override TranslatedExpression VisitBlockContainer(BlockContai
statementBuilder.currentIsIterator = false;
try {
var body = statementBuilder.ConvertAsBlock(container);
body.InsertChildAfter(null, new Comment(" Could not convert BlockContainer to single expression"), Roles.Comment);
var comment = new Comment(" Could not convert BlockContainer to single expression");
body.InsertChildAfter(null, comment, Roles.Comment);
// set ILVariable.HasInitialValue for any variables being used inside the container
foreach (var stloc in container.Descendants.OfType<StLoc>())
stloc.Variable.HasInitialValue = true;
var ame = new AnonymousMethodExpression { Body = body };
var systemFuncType = compilation.FindType(typeof(Func<>));
var blockReturnType = InferReturnType(body);
var delegateType = new ParameterizedType(systemFuncType, blockReturnType);
var invocationTarget = new CastExpression(ConvertType(delegateType), ame);
ResolveResult rr;
// This might happen when trying to decompile an assembly built for a target framework where System.Func<T> does not exist yet.
// This might happen when trying to decompile an assembly built for a target framework
// where System.Func<T> does not exist yet.
if (systemFuncType.Kind == TypeKind.Unknown) {
rr = new ResolveResult(blockReturnType);
} else {
var invokeMethod = delegateType.GetDelegateInvokeMethod();
rr = new CSharpInvocationResolveResult(new ResolveResult(delegateType), invokeMethod, EmptyList<ResolveResult>.Instance);
rr = new CSharpInvocationResolveResult(
new ResolveResult(delegateType),
invokeMethod,
EmptyList<ResolveResult>.Instance);
}
return new InvocationExpression(new MemberReferenceExpression(invocationTarget, "Invoke"))
.WithILInstruction(container)
Expand Down Expand Up @@ -2331,7 +2339,7 @@ protected internal override TranslatedExpression VisitLdElema(LdElema inst, Tran
return new DirectionExpression(FieldDirection.Ref, expr)
.WithoutILInstruction().WithRR(new ByReferenceResolveResult(expr.Type, ReferenceKind.Ref));
}

TranslatedExpression TranslateArrayIndex(ILInstruction i)
{
var input = Translate(i);
Expand All @@ -2341,7 +2349,7 @@ TranslatedExpression TranslateArrayIndex(ILInstruction i)
IType targetType = FindArithmeticType(i.ResultType, input.Type.GetSign());
return input.ConvertTo(targetType, this);
}

internal static bool IsUnboxAnyWithIsInst(UnboxAny unboxAny, IsInst isInst)
{
return unboxAny.Type.Equals(isInst.Type)
Expand Down Expand Up @@ -2967,7 +2975,7 @@ protected internal override TranslatedExpression VisitSwitchInstruction(SwitchIn
} else {
resultType = compilation.FindType(inst.ResultType.ToKnownTypeCode());
}

foreach (var section in inst.Sections) {
if (section == defaultSection)
continue;
Expand Down

0 comments on commit 80c85bb

Please sign in to comment.