1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-19 15:05:36 +02:00

Bug 335909 - adjusted cfg generation for switch and dead code

This commit is contained in:
Alena Laskavaia 2011-02-09 03:19:10 +00:00
parent aadbf2a477
commit 53ecdbbc27
4 changed files with 89 additions and 7 deletions

View file

@ -13,6 +13,7 @@ package org.eclipse.cdt.codan.core.cxx.internal.model.cfg;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import org.eclipse.cdt.codan.core.model.cfg.IBasicBlock;
import org.eclipse.cdt.codan.core.model.cfg.IBranchNode;
@ -22,6 +23,7 @@ import org.eclipse.cdt.codan.core.model.cfg.IDecisionNode;
import org.eclipse.cdt.codan.core.model.cfg.IExitNode;
import org.eclipse.cdt.codan.core.model.cfg.IJumpNode;
import org.eclipse.cdt.codan.core.model.cfg.IPlainNode;
import org.eclipse.cdt.codan.core.model.cfg.ISingleOutgoing;
import org.eclipse.cdt.codan.core.model.cfg.IStartNode;
import org.eclipse.cdt.codan.internal.core.cfg.AbstractBasicBlock;
import org.eclipse.cdt.codan.internal.core.cfg.DecisionNode;
@ -80,12 +82,35 @@ public class ControlFlowGraphBuilder {
returnExit.setStartNode(start);
addOutgoing(last, returnExit);
exits.add(returnExit);
if (dead.size() > 0) {
for (Iterator iterator = dead.iterator(); iterator.hasNext();) {
IBasicBlock ds = (IBasicBlock) iterator.next();
IBasicBlock dl = findLast(ds);
if (dl != null && dl.getOutgoingSize() == 0
&& dl != returnExit) {
((AbstractBasicBlock) dl).addOutgoing(returnExit);
}
}
}
}
CxxControlFlowGraph graph = new CxxControlFlowGraph(start, exits);
graph.setUnconnectedNodes(dead);
return graph;
}
public IBasicBlock findLast(IBasicBlock node) {
if (node instanceof IJumpNode)
return null;
if (node.getOutgoingSize() == 0)
return node;
if (node instanceof ISingleOutgoing) {
return findLast(((ISingleOutgoing) node).getOutgoing());
} else if (node instanceof IDecisionNode) {
return findLast(((IDecisionNode) node).getMergeNode().getOutgoing());
}
return node;
}
/**
* @param start2
* @param body
@ -335,6 +360,7 @@ public class ControlFlowGraphBuilder {
IBasicBlock last = createSubGraph(prev, elem);
prev = last;
}
addJump(prev, mergeNode);
}
/**

View file

@ -61,38 +61,58 @@ public class ControlFlowGraphTest extends CodanFastCxxAstTestCase {
ast.accept(visitor);
}
private void checkCfg() {
checkCfg(true);
}
/**
*
*/
private void checkCfg() {
private void checkCfg(boolean decision) {
assertNotNull(graph);
assertNotNull(graph.getStartNode());
Collection<IBasicBlock> nodes = graph.getNodes();
for (Iterator<IBasicBlock> iterator = nodes.iterator(); iterator
.hasNext();) {
IBasicBlock node = iterator.next();
checkNode(node);
checkNode(node, decision);
}
}
/**
* @param node
*/
private void checkNode(IBasicBlock node) {
private void checkNode(IBasicBlock node, boolean decision) {
IBasicBlock[] incomingNodes = node.getIncomingNodes();
for (int i = 0; i < incomingNodes.length; i++) {
nodes: for (int i = 0; i < incomingNodes.length; i++) {
IBasicBlock b = incomingNodes[i];
if (!contains(node, b.getOutgoingNodes()))
if (b == null) {
// check if dead node
Iterator<IBasicBlock> iterator = graph
.getUnconnectedNodeIterator();
boolean dead = false;
for (; iterator.hasNext();) {
IBasicBlock d = iterator.next();
if (node == d) {
dead = true;
break;
}
}
if (!dead)
fail("Block " + node + " prev is null");
} else if (!contains(node, b.getOutgoingNodes()))
fail("Block " + node + " inconsitent prev/next " + b);
}
IBasicBlock[] outgoingNodes = node.getOutgoingNodes();
for (int i = 0; i < outgoingNodes.length; i++) {
IBasicBlock b = outgoingNodes[i];
if (b == null)
fail("Block " + node + " next is null");
if (!contains(node, b.getIncomingNodes()))
fail("Block " + node + " inconsitent next/prev " + b);
}
if (node instanceof IDecisionNode) {
assertTrue("decision node outgping size",
if (node instanceof IDecisionNode && decision) {
assertTrue("decision node outgoing size " + node.getOutgoingSize(),
node.getOutgoingSize() > 1);
assertNotNull(((IDecisionNode) node).getMergeNode());
}
@ -360,4 +380,36 @@ public class ControlFlowGraphTest extends CodanFastCxxAstTestCase {
IBasicBlock m1 = jumpEnd(bElse);
assertSame(m1, m2);
}
// foo() {
// switch (0) {
// case 1: ;
// }
// }
public void test_switch1() {
buildCfg(getAboveComment(), false);
checkCfg(false);
}
// foo() {
// switch (0) {
// case 1: break;
// }
// }
public void test_switchbreak() {
buildCfg(getAboveComment(), false);
checkCfg(false);
}
// foo() {
// switch (0) {
// a++;
// }
// }
public void test_switchdead() {
buildCfg(getAboveComment(), false);
checkCfg(false);
IStartNode startNode = graph.getStartNode();
assertEquals(1, graph.getUnconnectedNodeSize());
}
}

View file

@ -135,6 +135,8 @@ public class ControlFlowGraph implements IControlFlowGraph {
* @param result
*/
private void getNodes(IBasicBlock start, Collection<IBasicBlock> result) {
if (start == null)
return; // huh
if (result.contains(start))
return;
result.add(start);

View file

@ -29,6 +29,8 @@ public class PlainNode extends AbstractSingleIncomingNode implements IPlainNode
}
public int getOutgoingSize() {
if (next == null)
return 0;
return 1;
}