- Fix the cast rewriter to rewrite labels too.

- Fix the translation of switch statements to keep the labels "alive" (part of the AST).
- Added test case for the bug.

git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@3960 f5eafffb-2e1d-0410-98e4-8ec43c5233c4
This commit is contained in:
yinnon_haviv 2010-10-02 20:27:17 +00:00
parent 38f8a44044
commit fc0d5ecc47
4 changed files with 59 additions and 33 deletions

View File

@ -896,35 +896,44 @@ public class RhinoToAstTranslator {
case Token.FINALLY:
case Token.BLOCK:
case Token.LABEL: {
// CAstNode ast;
Node c1 = n.getFirstChild();
if (c1 != null && c1.getType() == Token.SWITCH) {
Node switchValue = c1.getFirstChild();
Node c1 = n.getFirstChild();
if (c1 != null && c1.getType() == Token.SWITCH) {
Node switchValue = c1.getFirstChild();
CAstNode defaultLabel = Ast.makeNode(CAstNode.LABEL_STMT, Ast.makeNode(CAstNode.EMPTY));
context.cfg().map(defaultLabel, defaultLabel);
CAstNode defaultLabel = Ast.makeNode(CAstNode.LABEL_STMT, Ast.makeNode(CAstNode.EMPTY));
context.cfg().map(defaultLabel, defaultLabel);
for (Node kase = switchValue.getNext(); kase != null; kase = kase.getNext()) {
assert kase.getType() == Token.CASE;
Node caseLbl = kase.getFirstChild();
Node target = ((Node.Jump) kase).target;
context.cfg().add(c1, target, walkNodes(caseLbl, context));
List<CAstNode> labelCasts = new ArrayList<CAstNode>();
for (Node kase = switchValue.getNext(); kase != null; kase = kase.getNext()) {
assert kase.getType() == Token.CASE;
Node caseLbl = kase.getFirstChild();
Node target = ((Node.Jump) kase).target;
CAstNode labelCast = walkNodes(caseLbl, context);
labelCasts.add(labelCast);
context.cfg().add(c1, target, labelCast);
}
CAstNode[] children = new CAstNode[labelCasts.size()+1];
int i = 0;
children[i++] = Ast.makeNode(CAstNode.BLOCK_STMT, defaultLabel, gatherChildren(n, context, 1));
// Note that we are placing the labels as children in the AST
// even if they are not used, because we want them copied when AST is re-written.
for (CAstNode labelCast : labelCasts){
children[i++] = labelCast;
}
context.cfg().add(c1, defaultLabel, CAstControlFlowMap.SWITCH_DEFAULT);
CAstNode switchAst = Ast.makeNode(CAstNode.SWITCH, walkNodes(switchValue, context), children);
noteSourcePosition(context, switchAst, c1);
context.cfg().map(c1, switchAst);
return switchAst;
}
context.cfg().add(c1, defaultLabel, CAstControlFlowMap.SWITCH_DEFAULT);
CAstNode switchAst = Ast.makeNode(CAstNode.SWITCH, walkNodes(switchValue, context), Ast.makeNode(CAstNode.BLOCK_STMT,
defaultLabel, gatherChildren(n, context, 1)));
noteSourcePosition(context, switchAst, c1);
context.cfg().map(c1, switchAst);
return switchAst;
else {
return Ast.makeNode(CAstNode.BLOCK_STMT, gatherChildren(n, context));
}
}
else {
return Ast.makeNode(CAstNode.BLOCK_STMT, gatherChildren(n, context));
}
}
case Token.EXPR_VOID:
case Token.EXPR_RESULT: {

View File

@ -0,0 +1,7 @@
function f(){
switch (a){
case b:
return "wow"
}
}
f();

View File

@ -256,8 +256,11 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape {
verifyGraphAssertions(CG, assertionsForPrototypeContamination);
verifyNoEdges(CG, "suffix:test1", "suffix:foo_of_B");
verifyNoEdges(CG, "suffix:test2", "suffix:foo_of_A");
}
@Test public void testRewriterDoesNotChangeLablesBug() throws IOException, IllegalArgumentException, CancelException {
CallGraph CG = Util.makeScriptCG("tests", "rewrite_does_not_change_lables_bug.js");
// all we need is for it to finish building CG successfully.
}
}

View File

@ -111,12 +111,12 @@ public abstract class CAstRewriter<C extends CAstRewriter.RewriteContext<K>, K e
}
while (LS.hasNext()) {
Object label = LS.next();
CAstNode oldTarget = orig.getTarget(oldSource, label);
Object origLabel = LS.next();
CAstNode oldTarget = orig.getTarget(oldSource, origLabel);
assert oldTarget != null;
if (DEBUG) {
System.err.println(("old: " + label + " --> " + CAstPrinter.print(oldTarget)));
System.err.println(("old: " + origLabel + " --> " + CAstPrinter.print(oldTarget)));
}
Pair targetKey;
@ -130,16 +130,23 @@ public abstract class CAstRewriter<C extends CAstRewriter.RewriteContext<K>, K e
}
} while (!nodeMap.containsKey(targetKey));
Object newLabel;
if (nodeMap.containsKey(Pair.make(origLabel, targetKey.snd))){ // label is mapped too
newLabel = nodeMap.get(Pair.make(origLabel, targetKey.snd));
} else {
newLabel = origLabel;
}
CAstNode newTarget;
if (nodeMap.containsKey(targetKey)) {
newTarget = (CAstNode) nodeMap.get(targetKey);
newMap.add(newSource, newTarget, label);
newMap.add(newSource, newTarget, newLabel);
allNewTargetNodes.add(newTarget);
} else {
newTarget = flowOutTo(nodeMap, oldSource, label, oldTarget, orig, newSrc);
newTarget = flowOutTo(nodeMap, oldSource, origLabel, oldTarget, orig, newSrc);
allNewTargetNodes.add(newTarget);
newMap.add(newSource, newTarget, label);
newMap.add(newSource, newTarget, newLabel);
if (newTarget != CAstControlFlowMap.EXCEPTION_TO_EXIT && !mappedOutsideNodes.contains(newTarget)) {
mappedOutsideNodes.add(newTarget);
newMap.map(newTarget, newTarget);
@ -147,8 +154,8 @@ public abstract class CAstRewriter<C extends CAstRewriter.RewriteContext<K>, K e
}
if (DEBUG) {
System.err.println(("mapping:old: " + CAstPrinter.print(oldSource) + "-- " + label + " --> " + CAstPrinter.print(oldTarget)));
System.err.println(("mapping:new: " + CAstPrinter.print(newSource) + "-- " + label + " --> " + CAstPrinter.print(newTarget)));
System.err.println(("mapping:old: " + CAstPrinter.print(oldSource) + "-- " + origLabel + " --> " + CAstPrinter.print(oldTarget)));
System.err.println(("mapping:new: " + CAstPrinter.print(newSource) + "-- " + newLabel + " --> " + CAstPrinter.print(newTarget)));
}
}
}