Browse Source

Fixed bug in yield return decompiler when decompiling a method consisting only of 'yield break;'.

pull/70/head
Daniel Grunwald 15 years ago
parent
commit
69fe6bc7c2
  1. 48
      ICSharpCode.Decompiler/ILAst/YieldReturnDecompiler.cs

48
ICSharpCode.Decompiler/ILAst/YieldReturnDecompiler.cs

@ -471,12 +471,19 @@ namespace ICSharpCode.Decompiler.ILAst @@ -471,12 +471,19 @@ namespace ICSharpCode.Decompiler.ILAst
case ILCode.Brtrue:
{
SymbolicValue val = Eval(expr.Arguments[0]);
if (val.Type != SymbolicValueType.StateEquals)
if (val.Type == SymbolicValueType.StateEquals) {
ranges[(ILLabel)expr.Operand].UnionWith(nodeRange, val.Constant, val.Constant);
StateRange nextRange = ranges[body[i + 1]];
nextRange.UnionWith(nodeRange, int.MinValue, val.Constant - 1);
nextRange.UnionWith(nodeRange, val.Constant + 1, int.MaxValue);
} else if (val.Type == SymbolicValueType.StateInEquals) {
ranges[body[i + 1]].UnionWith(nodeRange, val.Constant, val.Constant);
StateRange targetRange = ranges[(ILLabel)expr.Operand];
targetRange.UnionWith(nodeRange, int.MinValue, val.Constant - 1);
targetRange.UnionWith(nodeRange, val.Constant + 1, int.MaxValue);
} else {
throw new YieldAnalysisFailedException();
ranges[(ILLabel)expr.Operand].UnionWith(nodeRange, val.Constant, val.Constant);
StateRange nextRange = ranges[body[i + 1]];
nextRange.UnionWith(nodeRange, int.MinValue, val.Constant - 1);
nextRange.UnionWith(nodeRange, val.Constant + 1, int.MaxValue);
}
break;
}
case ILCode.Nop:
@ -531,7 +538,11 @@ namespace ICSharpCode.Decompiler.ILAst @@ -531,7 +538,11 @@ namespace ICSharpCode.Decompiler.ILAst
/// <summary>
/// bool: State == Constant
/// </summary>
StateEquals
StateEquals,
/// <summary>
/// bool: State != Constant
/// </summary>
StateInEquals
}
struct SymbolicValue
@ -589,6 +600,14 @@ namespace ICSharpCode.Decompiler.ILAst @@ -589,6 +600,14 @@ namespace ICSharpCode.Decompiler.ILAst
// bool: (state + left.Constant == right.Constant)
// bool: (state == right.Constant - left.Constant)
return new SymbolicValue(SymbolicValueType.StateEquals, unchecked ( right.Constant - left.Constant ));
case ILCode.LogicNot:
SymbolicValue val = Eval(expr.Arguments[0]);
if (val.Type == SymbolicValueType.StateEquals)
return new SymbolicValue(SymbolicValueType.StateInEquals, val.Constant);
else if (val.Type == SymbolicValueType.StateInEquals)
return new SymbolicValue(SymbolicValueType.StateEquals, val.Constant);
else
throw new YieldAnalysisFailedException();
default:
throw new YieldAnalysisFailedException();
}
@ -679,14 +698,24 @@ namespace ICSharpCode.Decompiler.ILAst @@ -679,14 +698,24 @@ namespace ICSharpCode.Decompiler.ILAst
bodyLength -= 2; // don't conside the 'ret(false)' part of the body
}
returnFalseLabel = body.ElementAtOrDefault(--bodyLength) as ILLabel;
if (returnFalseLabel == null || bodyLength == 0)
// verify that the last element in the body is a label pointing to the 'ret(false)'
returnFalseLabel = body.ElementAtOrDefault(bodyLength - 1) as ILLabel;
if (returnFalseLabel == null)
throw new YieldAnalysisFailedException();
InitStateRanges(body[0]);
int pos = AssignStateRanges(body, bodyLength, forDispose: false);
while (pos > 0 && body[pos - 1] is ILLabel)
if (pos > 0 && body[pos - 1] is ILLabel) {
pos--;
} else {
// ensure that the first element at body[pos] is a label:
ILLabel newLabel = new ILLabel();
newLabel.Name = "YieldReturnEntryPoint";
ranges[newLabel] = ranges[body[pos]]; // give the label the range of the instruction at body[pos]
body.Insert(pos, newLabel);
bodyLength++;
}
List<KeyValuePair<ILLabel, StateRange>> labels = new List<KeyValuePair<ILLabel, StateRange>>();
for (int i = pos; i < bodyLength; i++) {
@ -795,7 +824,6 @@ namespace ICSharpCode.Decompiler.ILAst @@ -795,7 +824,6 @@ namespace ICSharpCode.Decompiler.ILAst
newBody.Add(body[pos]);
}
}
newBody.Add(returnFalseLabel);
newBody.Add(new ILExpression(ILCode.YieldBreak, null));
}

Loading…
Cancel
Save