From d2f248dc70dce74281384a5ad1243c346a872081 Mon Sep 17 00:00:00 2001 From: Alena Laskavaia Date: Tue, 9 Sep 2014 22:42:19 -0400 Subject: [PATCH] Bug 353352 - CFG doesn't handle range-based for loop Change-Id: Ic71c15d26d31d954fbc4c91882dd9361d9b23eae --- .../model/cfg/ControlFlowGraphBuilder.java | 43 ++++++++++-- .../codan/core/cfg/ControlFlowGraphTest.java | 69 +++++++++++++++++-- 2 files changed, 101 insertions(+), 11 deletions(-) diff --git a/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/internal/model/cfg/ControlFlowGraphBuilder.java b/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/internal/model/cfg/ControlFlowGraphBuilder.java index 82c004ab60d..fa609834f05 100644 --- a/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/internal/model/cfg/ControlFlowGraphBuilder.java +++ b/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/internal/model/cfg/ControlFlowGraphBuilder.java @@ -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) { diff --git a/codan/org.eclipse.cdt.codan.core.test/src/org/eclipse/cdt/codan/core/cfg/ControlFlowGraphTest.java b/codan/org.eclipse.cdt.codan.core.test/src/org/eclipse/cdt/codan/core/cfg/ControlFlowGraphTest.java index d483f52b425..e1cf5596a41 100644 --- a/codan/org.eclipse.cdt.codan.core.test/src/org/eclipse/cdt/codan/core/cfg/ControlFlowGraphTest.java +++ b/codan/org.eclipse.cdt.codan.core.test/src/org/eclipse/cdt/codan/core/cfg/ControlFlowGraphTest.java @@ -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