mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-06-07 17:56:01 +02:00
Bug 394521 Do Constant folding propagation when building CFG
When building control flow graph we can consider constants and not add some branches in decisions nodes, that make CFG more accurate and elimate some false positives Change-Id: I19c623e1e6d2dc7416a0e796a98168df7a976111 Signed-off-by: Alena Laskavaia <elaskavaia.cdt@gmail.com> Reviewed-on: https://git.eclipse.org/r/28726
This commit is contained in:
parent
3d78256606
commit
db43e03878
3 changed files with 94 additions and 5 deletions
|
@ -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.IASTSwitchStatement;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression;
|
import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTWhileStatement;
|
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.ICPPASTCatchHandler;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTryBlockStatement;
|
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
|
* This class creates C control flow graph
|
||||||
|
@ -463,14 +465,37 @@ public class ControlFlowGraphBuilder {
|
||||||
if (prev instanceof IExitNode || prev == null) {
|
if (prev instanceof IExitNode || prev == null) {
|
||||||
dead.add(node);
|
dead.add(node);
|
||||||
return;
|
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);
|
dead.add(node);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
((AbstractBasicBlock) prev).addOutgoing(node);
|
} else {
|
||||||
|
dead.add(node);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
((AbstractBasicBlock) prev).addOutgoing(node);
|
||||||
if (!(node instanceof IStartNode))
|
if (!(node instanceof IStartNode))
|
||||||
((AbstractBasicBlock) node).addIncoming(prev);
|
((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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -294,8 +294,8 @@ public class ControlFlowGraphTest extends CodanFastCxxAstTestCase {
|
||||||
assertEquals(1, graph.getUnconnectedNodeSize());
|
assertEquals(1, graph.getUnconnectedNodeSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
// foo() {
|
// foo(int x) {
|
||||||
// int a=10, x=5;
|
// int a=10;
|
||||||
// if (a--) {
|
// if (a--) {
|
||||||
// if (x<0)
|
// if (x<0)
|
||||||
// a++;
|
// a++;
|
||||||
|
@ -408,4 +408,46 @@ public class ControlFlowGraphTest extends CodanFastCxxAstTestCase {
|
||||||
IStartNode startNode = graph.getStartNode();
|
IStartNode startNode = graph.getStartNode();
|
||||||
assertEquals(1, graph.getUnconnectedNodeSize());
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -384,4 +384,26 @@ public class ReturnCheckerTest extends CheckerTestCase {
|
||||||
checkNoErrors();
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Add table
Reference in a new issue