1
0
Fork 0
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:
Alena Laskavaia 2014-09-09 22:42:19 -04:00
parent 63c28d216f
commit d2f248dc70
2 changed files with 101 additions and 11 deletions

View file

@ -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) {

View file

@ -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
}
}