Browse Source

Fix bug in DataFlowVisitor.VisitSwitchInstruction

pull/728/head
Daniel Grunwald 9 years ago
parent
commit
5998d39827
  1. 45
      ICSharpCode.Decompiler/CSharp/Transforms/DeclareVariables.cs
  2. 4
      ICSharpCode.Decompiler/FlowAnalysis/DataFlowVisitor.cs

45
ICSharpCode.Decompiler/CSharp/Transforms/DeclareVariables.cs

@ -94,7 +94,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -94,7 +94,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
}
}
Dictionary<ILVariable, VariableToDeclare> variableDict = new Dictionary<ILVariable, VariableToDeclare>();
readonly Dictionary<ILVariable, VariableToDeclare> variableDict = new Dictionary<ILVariable, VariableToDeclare>();
TransformContext context;
@ -103,7 +103,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -103,7 +103,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
try {
this.context = context;
FindInsertionPoints(rootNode, 0);
ResolveOverlap();
ResolveCollisions();
InsertVariableDeclarations();
} finally {
variableDict.Clear();
@ -118,6 +118,10 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -118,6 +118,10 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
///
/// `level` == nesting depth of `node` within root node.
/// </summary>
/// <remarks>
/// Insertion point for a variable = common parent of all uses of that variable
/// = smallest possible scope that contains all the uses of the variable
/// </remarks>
void FindInsertionPoints(AstNode node, int nodeLevel)
{
for (AstNode child = node.FirstChild; child != null; child = child.NextSibling) {
@ -160,11 +164,43 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -160,11 +164,43 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
}
#endregion
void ResolveOverlap()
/// <summary>
/// Some variable declarations in C# are illegal (colliding),
/// even though the variable live ranges are not overlapping.
///
/// Multiple declarations in same block:
/// <code>
/// int i = 1; use(1);
/// int i = 2; use(2);
/// </code>
///
/// "Hiding" declaration in nested block:
/// <code>
/// int i = 1; use(1);
/// if (...) {
/// int i = 2; use(2);
/// }
/// </code>
///
/// Nested blocks are illegal even if the parent block
/// declares the variable later:
/// <code>
/// if (...) {
/// int i = 1; use(i);
/// }
/// int i = 2; use(i);
/// </code>
///
/// ResolveCollisions() detects all these cases, and combines the variable declarations
/// to a single declaration that is usable for the combined scopes.
/// </summary>
void ResolveCollisions()
{
var multiDict = new MultiDictionary<string, VariableToDeclare>();
foreach (var v in variableDict.Values) {
// Go up to the next BlockStatement (we can't add variable declarations anywhere else in the AST)
// We can only insert variable declarations in blocks, but FindInsertionPoints() didn't
// guarantee that it finds only blocks.
// Fix that up now.
while (!(v.InsertionPoint.nextNode.Parent is BlockStatement)) {
v.InsertionPoint = v.InsertionPoint.Up();
}
@ -176,6 +212,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -176,6 +212,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
// Go up until both nodes are on the same level:
InsertionPoint point1 = prev.InsertionPoint.UpTo(v.InsertionPoint.level);
InsertionPoint point2 = v.InsertionPoint.UpTo(prev.InsertionPoint.level);
Debug.Assert(point1.level == point2.level);
if (point1.nextNode.Parent == point2.nextNode.Parent) {
// We found a collision!
prev.RemovedDueToCollision = true;

4
ICSharpCode.Decompiler/FlowAnalysis/DataFlowVisitor.cs

@ -559,7 +559,9 @@ namespace ICSharpCode.Decompiler.FlowAnalysis @@ -559,7 +559,9 @@ namespace ICSharpCode.Decompiler.FlowAnalysis
DebugStartPoint(inst);
inst.Value.AcceptVisitor(this);
State beforeSections = state.Clone();
State afterSections = bottomState.Clone();
// It's possible for none of the cases to match,
// so afterSections is reachable without executing any section
State afterSections = state.Clone();
foreach (var section in inst.Sections) {
state.ReplaceWith(beforeSections);
section.AcceptVisitor(this);

Loading…
Cancel
Save