mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-09-10 12:03:16 +02:00
Bug 353352 - CFG doesn't handle range-based for loop
Change-Id: Ic71c15d26d31d954fbc4c91882dd9361d9b23eae
This commit is contained in:
parent
63c28d216f
commit
d2f248dc70
2 changed files with 101 additions and 11 deletions
|
@ -183,9 +183,8 @@ public class ControlFlowGraphBuilder {
|
||||||
conn = (IConnectorNode) labNode.getOutgoing();
|
conn = (IConnectorNode) labNode.getOutgoing();
|
||||||
addOutgoing(prev, labNode);
|
addOutgoing(prev, labNode);
|
||||||
} else {
|
} else {
|
||||||
// labeled statement contains of connector for jumps, branch for
|
// labeled statement consists of connectors for jumps, branch for
|
||||||
// label
|
// label and nested statement
|
||||||
// and nested statement
|
|
||||||
conn = createLabelNodes(prev, labelName);
|
conn = createLabelNodes(prev, labelName);
|
||||||
}
|
}
|
||||||
return createSubGraph(conn, ast.getNestedStatement());
|
return createSubGraph(conn, ast.getNestedStatement());
|
||||||
|
@ -383,8 +382,42 @@ public class ControlFlowGraphBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
private IBasicBlock createRangeBasedFor(IBasicBlock prev, ICPPASTRangeBasedForStatement forNode) {
|
private IBasicBlock createRangeBasedFor(IBasicBlock prev, ICPPASTRangeBasedForStatement forNode) {
|
||||||
// TODO(Alena Laskavaia): Implement proper graph.
|
// Add initializer
|
||||||
return createSubGraph(prev, forNode.getBody());
|
IPlainNode init = factory.createPlainNode(forNode.getDeclaration());
|
||||||
|
addOutgoing(prev, init);
|
||||||
|
prev = init;
|
||||||
|
// Add continue connector
|
||||||
|
IConnectorNode beforeCheck = factory.createConnectorNode();
|
||||||
|
addOutgoing(prev, beforeCheck);
|
||||||
|
// Decision node
|
||||||
|
CxxDecisionNode decision = factory.createDecisionNode(forNode.getInitializerClause()); // XXX test expression
|
||||||
|
addOutgoing(beforeCheck, decision);
|
||||||
|
// Add break connector
|
||||||
|
IConnectorNode nBreak = factory.createConnectorNode();
|
||||||
|
decision.setMergeNode(nBreak);
|
||||||
|
// Create body and jump to continue node
|
||||||
|
IBranchNode loopStart = factory.createBranchNode(IBranchNode.THEN);
|
||||||
|
addOutgoing(decision, loopStart);
|
||||||
|
// Set break/continue
|
||||||
|
IConnectorNode nContinue = factory.createConnectorNode();
|
||||||
|
IConnectorNode savedContinue = outerContinue;
|
||||||
|
IConnectorNode savedBreak = outerBreak;
|
||||||
|
outerContinue = nContinue;
|
||||||
|
outerBreak = nBreak;
|
||||||
|
IBasicBlock endBody = createSubGraph(loopStart, forNode.getBody());
|
||||||
|
outerContinue = savedContinue;
|
||||||
|
outerBreak = savedBreak;
|
||||||
|
// inc
|
||||||
|
IPlainNode inc = factory.createPlainNode(); // XXX increment
|
||||||
|
addOutgoing(endBody, nContinue);
|
||||||
|
addOutgoing(nContinue, inc);
|
||||||
|
// Connect with backward link
|
||||||
|
addJump(inc, beforeCheck, true);
|
||||||
|
// Add "else" branch
|
||||||
|
IBranchNode loopEnd = factory.createBranchNode(IBranchNode.ELSE);
|
||||||
|
addOutgoing(decision, loopEnd);
|
||||||
|
addJump(loopEnd, nBreak);
|
||||||
|
return nBreak;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected IBasicBlock createWhile(IBasicBlock prev, IASTWhileStatement body) {
|
protected IBasicBlock createWhile(IBasicBlock prev, IASTWhileStatement body) {
|
||||||
|
|
|
@ -65,7 +65,7 @@ public class ControlFlowGraphTest extends CodanFastCxxAstTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
private void checkCfg(boolean decision) {
|
private void checkCfg(boolean decision) {
|
||||||
assertNotNull(graph);
|
assertNotNull(graph);
|
||||||
|
@ -153,6 +153,14 @@ public class ControlFlowGraphTest extends CodanFastCxxAstTestCase {
|
||||||
processAst(tu);
|
processAst(tu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void buildCfg_C(String code) {
|
||||||
|
parse(code, ParserLanguage.C, true);
|
||||||
|
processAst(tu);
|
||||||
|
}
|
||||||
|
private void buildCfg_CPP(String code) {
|
||||||
|
parse(code, ParserLanguage.CPP, true);
|
||||||
|
processAst(tu);
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* @param des
|
* @param des
|
||||||
* @return
|
* @return
|
||||||
|
@ -163,7 +171,7 @@ public class ControlFlowGraphTest extends CodanFastCxxAstTestCase {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return first node after the branch
|
* Return first node after the branch
|
||||||
*
|
*
|
||||||
* @param des
|
* @param des
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
|
@ -180,7 +188,7 @@ public class ControlFlowGraphTest extends CodanFastCxxAstTestCase {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return node where control jumps, following the chain until jump is hit
|
* Return node where control jumps, following the chain until jump is hit
|
||||||
*
|
*
|
||||||
* @param a
|
* @param a
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
|
@ -199,7 +207,7 @@ public class ControlFlowGraphTest extends CodanFastCxxAstTestCase {
|
||||||
|
|
||||||
// main() {
|
// main() {
|
||||||
// int a;
|
// int a;
|
||||||
// a=1;
|
// a=1;
|
||||||
// }
|
// }
|
||||||
public void test_basic() {
|
public void test_basic() {
|
||||||
buildAndCheck(getAboveComment());
|
buildAndCheck(getAboveComment());
|
||||||
|
@ -342,7 +350,7 @@ public class ControlFlowGraphTest extends CodanFastCxxAstTestCase {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
*
|
*
|
||||||
* @see org.eclipse.cdt.codan.core.test.CodanFastCxxAstTestCase#getChecker()
|
* @see org.eclipse.cdt.codan.core.test.CodanFastCxxAstTestCase#getChecker()
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
|
@ -436,7 +444,7 @@ public class ControlFlowGraphTest extends CodanFastCxxAstTestCase {
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
public void test_infiniloop() {
|
public void test_infiniloop() {
|
||||||
buildCfg(getAboveComment(), false);
|
buildCfg_C(getAboveComment());
|
||||||
checkCfg(false);
|
checkCfg(false);
|
||||||
IStartNode startNode = graph.getStartNode();
|
IStartNode startNode = graph.getStartNode();
|
||||||
IConnectorNode conn = (IConnectorNode) startNode.getOutgoing();
|
IConnectorNode conn = (IConnectorNode) startNode.getOutgoing();
|
||||||
|
@ -450,4 +458,53 @@ public class ControlFlowGraphTest extends CodanFastCxxAstTestCase {
|
||||||
assertNotNull(m2);
|
assertNotNull(m2);
|
||||||
assertNull(m1);
|
assertNull(m1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// void foo() {
|
||||||
|
// for (int i=0;i<N;i++) {
|
||||||
|
// bar();
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
public void test_for() {
|
||||||
|
buildCfg_CPP(getAboveComment());
|
||||||
|
checkCfg(false);
|
||||||
|
|
||||||
|
IStartNode startNode = graph.getStartNode();
|
||||||
|
IPlainNode decl = (IPlainNode) startNode.getOutgoing();
|
||||||
|
IConnectorNode conn = (IConnectorNode) decl.getOutgoing();
|
||||||
|
IDecisionNode des = (IDecisionNode) conn.getOutgoing();
|
||||||
|
assertEquals("i<N", data(des));
|
||||||
|
IPlainNode bThen = (IPlainNode) branchEnd(des, IBranchNode.THEN);
|
||||||
|
assertEquals("bar();", data(bThen));
|
||||||
|
IBasicBlock bElse = branchEnd(des, IBranchNode.ELSE);
|
||||||
|
|
||||||
|
IBasicBlock m1 = jumpEnd(bElse);
|
||||||
|
IBasicBlock m2 = bThen.getOutgoing();
|
||||||
|
assertNotNull(m1);
|
||||||
|
assertSame(conn, jumpEnd(bThen));
|
||||||
|
assertEquals("i++", data(((IConnectorNode) m2).getOutgoing()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// void foo() {
|
||||||
|
// for (int i : arr) {
|
||||||
|
// bar();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
public void test_range_loop() {
|
||||||
|
buildCfg_CPP(getAboveComment());
|
||||||
|
checkCfg(false);
|
||||||
|
|
||||||
|
IStartNode startNode = graph.getStartNode();
|
||||||
|
IPlainNode decl = (IPlainNode) startNode.getOutgoing();
|
||||||
|
IConnectorNode conn = (IConnectorNode) decl.getOutgoing();
|
||||||
|
IDecisionNode des = (IDecisionNode) conn.getOutgoing();
|
||||||
|
assertEquals("arr", data(des)); // condition
|
||||||
|
IPlainNode bThen = (IPlainNode) branchEnd(des, IBranchNode.THEN);
|
||||||
|
assertEquals("bar();", data(bThen));
|
||||||
|
IBasicBlock bElse = branchEnd(des, IBranchNode.ELSE);
|
||||||
|
assertNotNull(bElse);
|
||||||
|
IBasicBlock m2 = bThen.getOutgoing();
|
||||||
|
|
||||||
|
assertSame(conn, jumpEnd(bThen));
|
||||||
|
assertEquals("", data(((IConnectorNode) m2).getOutgoing())); // increment
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue