mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-23 08:55:25 +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();
|
||||
addOutgoing(prev, labNode);
|
||||
} else {
|
||||
// labeled statement contains of connector for jumps, branch for
|
||||
// label
|
||||
// and nested statement
|
||||
// labeled statement consists of connectors for jumps, branch for
|
||||
// label and nested statement
|
||||
conn = createLabelNodes(prev, labelName);
|
||||
}
|
||||
return createSubGraph(conn, ast.getNestedStatement());
|
||||
|
@ -383,8 +382,42 @@ public class ControlFlowGraphBuilder {
|
|||
}
|
||||
|
||||
private IBasicBlock createRangeBasedFor(IBasicBlock prev, ICPPASTRangeBasedForStatement forNode) {
|
||||
// TODO(Alena Laskavaia): Implement proper graph.
|
||||
return createSubGraph(prev, forNode.getBody());
|
||||
// Add initializer
|
||||
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) {
|
||||
|
|
|
@ -65,7 +65,7 @@ public class ControlFlowGraphTest extends CodanFastCxxAstTestCase {
|
|||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
private void checkCfg(boolean decision) {
|
||||
assertNotNull(graph);
|
||||
|
@ -153,6 +153,14 @@ public class ControlFlowGraphTest extends CodanFastCxxAstTestCase {
|
|||
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
|
||||
* @return
|
||||
|
@ -163,7 +171,7 @@ public class ControlFlowGraphTest extends CodanFastCxxAstTestCase {
|
|||
|
||||
/**
|
||||
* Return first node after the branch
|
||||
*
|
||||
*
|
||||
* @param des
|
||||
* @return
|
||||
*/
|
||||
|
@ -180,7 +188,7 @@ public class ControlFlowGraphTest extends CodanFastCxxAstTestCase {
|
|||
|
||||
/**
|
||||
* Return node where control jumps, following the chain until jump is hit
|
||||
*
|
||||
*
|
||||
* @param a
|
||||
* @return
|
||||
*/
|
||||
|
@ -199,7 +207,7 @@ public class ControlFlowGraphTest extends CodanFastCxxAstTestCase {
|
|||
|
||||
// main() {
|
||||
// int a;
|
||||
// a=1;
|
||||
// a=1;
|
||||
// }
|
||||
public void test_basic() {
|
||||
buildAndCheck(getAboveComment());
|
||||
|
@ -342,7 +350,7 @@ public class ControlFlowGraphTest extends CodanFastCxxAstTestCase {
|
|||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
*
|
||||
* @see org.eclipse.cdt.codan.core.test.CodanFastCxxAstTestCase#getChecker()
|
||||
*/
|
||||
@Override
|
||||
|
@ -436,7 +444,7 @@ public class ControlFlowGraphTest extends CodanFastCxxAstTestCase {
|
|||
// }
|
||||
// }
|
||||
public void test_infiniloop() {
|
||||
buildCfg(getAboveComment(), false);
|
||||
buildCfg_C(getAboveComment());
|
||||
checkCfg(false);
|
||||
IStartNode startNode = graph.getStartNode();
|
||||
IConnectorNode conn = (IConnectorNode) startNode.getOutgoing();
|
||||
|
@ -450,4 +458,53 @@ public class ControlFlowGraphTest extends CodanFastCxxAstTestCase {
|
|||
assertNotNull(m2);
|
||||
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