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 69809d2ae60..139b4af08b2 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 @@ -52,8 +52,10 @@ import org.eclipse.cdt.core.dom.ast.IASTStatement; import org.eclipse.cdt.core.dom.ast.IASTSwitchStatement; import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression; import org.eclipse.cdt.core.dom.ast.IASTWhileStatement; +import org.eclipse.cdt.core.dom.ast.IValue; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCatchHandler; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTryBlockStatement; +import org.eclipse.cdt.internal.core.dom.parser.Value; /** * This class creates C control flow graph @@ -463,14 +465,37 @@ public class ControlFlowGraphBuilder { if (prev instanceof IExitNode || prev == null) { dead.add(node); return; - } else if (prev instanceof ICfgData) { - if (prev instanceof IDecisionNode && !(node instanceof IBranchNode)) { + } + if (prev instanceof IDecisionNode) { + if (node instanceof IBranchNode) { + IDecisionNode decisionNode = (IDecisionNode) prev; + if (isConstant(decisionNode, 1) && ((IBranchNode) node).getLabel().equals(IBranchNode.ELSE)) { + dead.add(node); + return; + } else if (isConstant(decisionNode, 0) && ((IBranchNode) node).getLabel().equals(IBranchNode.THEN)) { + dead.add(node); + return; + } + } else { dead.add(node); return; } - ((AbstractBasicBlock) prev).addOutgoing(node); } + ((AbstractBasicBlock) prev).addOutgoing(node); if (!(node instanceof IStartNode)) ((AbstractBasicBlock) node).addIncoming(prev); } + + private boolean isConstant(IDecisionNode node, long testvalue) { + if (node instanceof ICfgData) { + IASTNode ast = (IASTNode) ((ICfgData) node).getData(); + if (ast instanceof IASTExpression) { + IValue dvalue = Value.create((IASTExpression) ast, 5); + Long numericalValue = dvalue.numericalValue(); + if (numericalValue==null) return false; + return (numericalValue==testvalue); + } + } + return false; + } } 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 dd6c6d20592..d483f52b425 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 @@ -294,8 +294,8 @@ public class ControlFlowGraphTest extends CodanFastCxxAstTestCase { assertEquals(1, graph.getUnconnectedNodeSize()); } - // foo() { - // int a=10, x=5; + // foo(int x) { + // int a=10; // if (a--) { // if (x<0) // a++; @@ -408,4 +408,46 @@ public class ControlFlowGraphTest extends CodanFastCxxAstTestCase { IStartNode startNode = graph.getStartNode(); assertEquals(1, graph.getUnconnectedNodeSize()); } + + // foo() { + // int a=10,x=5; + // if (x<0) + // a++; + // } + public void test_deadbranch() { + buildCfg(getAboveComment(), false); + checkCfg(false); + IStartNode startNode = graph.getStartNode(); + IPlainNode decl = (IPlainNode) startNode.getOutgoing(); + IDecisionNode des = (IDecisionNode) decl.getOutgoing(); + assertEquals("x<0", data(des)); + IBasicBlock bElse = branchEnd(des, IBranchNode.ELSE); + IBasicBlock m2 = jumpEnd(branchEnd(des, IBranchNode.THEN)); + IBasicBlock m1 = jumpEnd(bElse); + + assertNull(m2); + assertNotNull(m1); + } + +// int test1_f() +// { +// while (1) +// { +// } +// } + public void test_infiniloop() { + buildCfg(getAboveComment(), false); + checkCfg(false); + IStartNode startNode = graph.getStartNode(); + IConnectorNode conn = (IConnectorNode) startNode.getOutgoing(); + IDecisionNode des = (IDecisionNode) conn.getOutgoing(); + assertEquals("1", data(des)); + IBasicBlock bElse = branchEnd(des, IBranchNode.ELSE); + IBasicBlock bThen = branchEnd(des, IBranchNode.THEN); + IBasicBlock m2 = jumpEnd(bThen); + IBasicBlock m1 = jumpEnd(bElse); + + assertNotNull(m2); + assertNull(m1); + } } diff --git a/codan/org.eclipse.cdt.codan.core.test/src/org/eclipse/cdt/codan/core/internal/checkers/ReturnCheckerTest.java b/codan/org.eclipse.cdt.codan.core.test/src/org/eclipse/cdt/codan/core/internal/checkers/ReturnCheckerTest.java index d56ff169f05..e1e1f1775c1 100644 --- a/codan/org.eclipse.cdt.codan.core.test/src/org/eclipse/cdt/codan/core/internal/checkers/ReturnCheckerTest.java +++ b/codan/org.eclipse.cdt.codan.core.test/src/org/eclipse/cdt/codan/core/internal/checkers/ReturnCheckerTest.java @@ -384,4 +384,26 @@ public class ReturnCheckerTest extends CheckerTestCase { checkNoErrors(); } +// int test1() { +// do { +// return 1; +// } while (0); +// } + public void testNoRetInfinitLoop() throws Exception { + // Bug 394521 + loadCodeAndRunCpp(getAboveComment()); + checkNoErrors(); + } + +// int test1_f() // WARNING HERE: "No return, in function returning non-void" +// { +// while (1) +// { +// } +// } + public void testNoRetInfinitLoop2() throws Exception { + // Bug 394521 + loadCodeAndRunCpp(getAboveComment()); + checkNoErrors(); + } } \ No newline at end of file