Browse Source

DefiniteAssignmentAnalysis bugfix

pull/100/head
Daniel Grunwald 15 years ago
parent
commit
6b638ec330
  1. 38
      NRefactory/ICSharpCode.NRefactory/CSharp/Analysis/DefiniteAssignmentAnalysis.cs

38
NRefactory/ICSharpCode.NRefactory/CSharp/Analysis/DefiniteAssignmentAnalysis.cs

@ -123,6 +123,10 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
} }
// Verify that we created nodes for all statements: // Verify that we created nodes for all statements:
Debug.Assert(!rootStatement.DescendantsAndSelf.OfType<Statement>().Except(allNodes.Select(n => n.NextStatement)).Any()); Debug.Assert(!rootStatement.DescendantsAndSelf.OfType<Statement>().Except(allNodes.Select(n => n.NextStatement)).Any());
// Verify that we put all nodes into the dictionaries:
Debug.Assert(rootStatement.DescendantsAndSelf.OfType<Statement>().All(stmt => beginNodeDict.ContainsKey(stmt)));
Debug.Assert(rootStatement.DescendantsAndSelf.OfType<Statement>().All(stmt => endNodeDict.ContainsKey(stmt)));
this.analyzedRangeStart = 0; this.analyzedRangeStart = 0;
this.analyzedRangeEnd = allNodes.Count - 1; this.analyzedRangeEnd = allNodes.Count - 1;
} }
@ -166,6 +170,7 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
/// <remarks>Both 'start' and 'end' are inclusive.</remarks> /// <remarks>Both 'start' and 'end' are inclusive.</remarks>
public void SetAnalyzedRange(Statement start, Statement end) public void SetAnalyzedRange(Statement start, Statement end)
{ {
Debug.Assert(beginNodeDict.ContainsKey(start) && endNodeDict.ContainsKey(end));
int startIndex = beginNodeDict[start].Index; int startIndex = beginNodeDict[start].Index;
int endIndex = endNodeDict[end].Index; int endIndex = endNodeDict[end].Index;
if (startIndex > endIndex) if (startIndex > endIndex)
@ -353,27 +358,26 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
DefiniteAssignmentStatus oldStatus = edgeStatus[edge]; DefiniteAssignmentStatus oldStatus = edgeStatus[edge];
if (oldStatus == newStatus) if (oldStatus == newStatus)
return; return;
// Ensure that status can change only in one direction: // Ensure that status can cannot change back to CodeUnreachable after it once was reachable.
// CodeUnreachable -> PotentiallyAssigned -> DefinitelyAssigned // Also, don't ever use AssignedAfter... for statements.
// Going against this direction indicates a bug and could cause infinite loops. if (newStatus == DefiniteAssignmentStatus.CodeUnreachable
switch (oldStatus) { || newStatus == DefiniteAssignmentStatus.AssignedAfterFalseExpression
case DefiniteAssignmentStatus.PotentiallyAssigned: || newStatus == DefiniteAssignmentStatus.AssignedAfterTrueExpression)
if (newStatus != DefiniteAssignmentStatus.DefinitelyAssigned) {
throw new InvalidOperationException("Invalid state transition"); throw new InvalidOperationException();
break;
case DefiniteAssignmentStatus.CodeUnreachable:
if (!(newStatus == DefiniteAssignmentStatus.PotentiallyAssigned || newStatus == DefiniteAssignmentStatus.DefinitelyAssigned))
throw new InvalidOperationException("Invalid state transition");
break;
case DefiniteAssignmentStatus.DefinitelyAssigned:
throw new InvalidOperationException("Invalid state transition");
default:
throw new InvalidOperationException("Invalid value for DefiniteAssignmentStatus");
} }
// Note that the status can change from DefinitelyAssigned
// back to PotentiallyAssigned as unreachable input edges are
// discovered to be reachable.
edgeStatus[edge] = newStatus; edgeStatus[edge] = newStatus;
DefiniteAssignmentNode targetNode = (DefiniteAssignmentNode)edge.To; DefiniteAssignmentNode targetNode = (DefiniteAssignmentNode)edge.To;
if (analyzedRangeStart <= targetNode.Index && targetNode.Index <= analyzedRangeEnd) if (analyzedRangeStart <= targetNode.Index && targetNode.Index <= analyzedRangeEnd) {
// TODO: potential optimization: visit previously unreachable nodes with higher priority
// (e.g. use Deque and enqueue previously unreachable nodes at the front, but
// other nodes at the end)
nodesWithModifiedInput.Enqueue(targetNode); nodesWithModifiedInput.Enqueue(targetNode);
}
} }
/// <summary> /// <summary>

Loading…
Cancel
Save