mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-08-03 14:25:37 +02:00
- added more tests and support for goto/label statements
This commit is contained in:
parent
0f78d0c5fd
commit
5a5d22c50d
8 changed files with 268 additions and 56 deletions
|
@ -12,6 +12,7 @@ package org.eclipse.cdt.codan.core.cxx.internal.model.cfg;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
|
||||
import org.eclipse.cdt.codan.internal.core.cfg.AbstractBasicBlock;
|
||||
import org.eclipse.cdt.codan.internal.core.cfg.ConnectorNode;
|
||||
|
@ -34,7 +35,9 @@ import org.eclipse.cdt.core.dom.ast.IASTDoStatement;
|
|||
import org.eclipse.cdt.core.dom.ast.IASTExpressionStatement;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTForStatement;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTGotoStatement;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTIfStatement;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTLabelStatement;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTReturnStatement;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTStatement;
|
||||
|
@ -52,6 +55,7 @@ public class ControlFlowGraphBuilder {
|
|||
CxxNodeFactory factory = new CxxNodeFactory();
|
||||
IConnectorNode outerBreak;
|
||||
IConnectorNode outerContinue;
|
||||
HashMap<String, IBasicBlock> labels = new HashMap<String, IBasicBlock>(0);
|
||||
|
||||
/**
|
||||
* @param def
|
||||
|
@ -68,7 +72,9 @@ public class ControlFlowGraphBuilder {
|
|||
returnExit.setStartNode(start);
|
||||
addOutgoing(last, returnExit);
|
||||
}
|
||||
return new CxxControlFlowGraph(start, exits);
|
||||
CxxControlFlowGraph graph = new CxxControlFlowGraph(start, exits);
|
||||
graph.setUnconnectedNodes(dead);
|
||||
return graph;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -112,10 +118,53 @@ public class ControlFlowGraphBuilder {
|
|||
return prev;
|
||||
} else if (body instanceof IASTSwitchStatement) {
|
||||
return createSwitch(prev, (IASTSwitchStatement) body);
|
||||
} else if (body instanceof IASTLabelStatement) {
|
||||
IASTLabelStatement ast = (IASTLabelStatement) body;
|
||||
String labelName = ast.getName().toString();
|
||||
IBranchNode labNode = (IBranchNode) labels.get(labelName);
|
||||
IConnectorNode conn;
|
||||
if (labNode != null) {
|
||||
conn = (IConnectorNode) labNode.getOutgoing();
|
||||
addOutgoing(prev, labNode);
|
||||
} else {
|
||||
// labeled statement contains of connector for jumps, branch for
|
||||
// label
|
||||
// and nested statement
|
||||
conn = createLabelNodes(prev, labelName);
|
||||
}
|
||||
return createSubGraph(conn, ast.getNestedStatement());
|
||||
} else if (body instanceof IASTGotoStatement) {
|
||||
IASTGotoStatement ast = (IASTGotoStatement)body;
|
||||
String labelName = ast.getName().toString();
|
||||
IConnectorNode conn;
|
||||
IBranchNode labNode = (IBranchNode) labels.get(labelName);
|
||||
if (labNode!=null) {
|
||||
conn = (IConnectorNode) labNode.getOutgoing();
|
||||
} else {
|
||||
conn = createLabelNodes(null, labelName);
|
||||
}
|
||||
IJumpNode gotoNode = factory.createJumpNode();
|
||||
((JumpNode) gotoNode).setJump(conn, labNode!=null);
|
||||
addOutgoing(prev, gotoNode);
|
||||
return gotoNode;
|
||||
}
|
||||
return prev;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param prev
|
||||
* @param labelName
|
||||
* @return
|
||||
*/
|
||||
protected IConnectorNode createLabelNodes(IBasicBlock prev, String labelName) {
|
||||
IBranchNode branch = factory.createBranchNode(labelName);
|
||||
if (prev!=null) addOutgoing(prev, branch);
|
||||
labels.put(labelName, branch);
|
||||
IConnectorNode conn = factory.createConnectorNode();
|
||||
addOutgoing(branch, conn);
|
||||
return conn;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param prev
|
||||
* @param body
|
||||
|
@ -127,11 +176,11 @@ public class ControlFlowGraphBuilder {
|
|||
addOutgoing(prev, ifNode);
|
||||
IConnectorNode mergeNode = factory.createConnectorNode();
|
||||
ifNode.setMergeNode(mergeNode);
|
||||
IBranchNode thenNode = factory.createLabeledNode(IBranchNode.THEN);
|
||||
IBranchNode thenNode = factory.createBranchNode(IBranchNode.THEN);
|
||||
addOutgoing(ifNode, thenNode);
|
||||
IBasicBlock then = createSubGraph(thenNode, body.getThenClause());
|
||||
addJump(then, mergeNode);
|
||||
IBranchNode elseNode = factory.createLabeledNode(IBranchNode.ELSE);
|
||||
IBranchNode elseNode = factory.createBranchNode(IBranchNode.ELSE);
|
||||
addOutgoing(ifNode, elseNode);
|
||||
IBasicBlock els = createSubGraph(elseNode, body.getElseClause());
|
||||
addJump(els, mergeNode);
|
||||
|
@ -173,7 +222,7 @@ public class ControlFlowGraphBuilder {
|
|||
}
|
||||
if (elem instanceof IASTDefaultStatement) {
|
||||
IBranchNode lbl = factory
|
||||
.createLabeledNode(IBranchNode.DEFAULT);
|
||||
.createBranchNode(IBranchNode.DEFAULT);
|
||||
if (!(prev instanceof IExitNode) && prev != switchNode)
|
||||
addOutgoing(prev, lbl);
|
||||
addOutgoing(switchNode, lbl);
|
||||
|
@ -185,9 +234,9 @@ public class ControlFlowGraphBuilder {
|
|||
IBranchNode lbl = null;
|
||||
if (elem instanceof IASTCaseStatement) {
|
||||
IASTCaseStatement caseSt = (IASTCaseStatement) elem;
|
||||
lbl = factory.createLabeledNode(caseSt);
|
||||
lbl = factory.createBranchNode(caseSt);
|
||||
} else if (elem instanceof IASTDefaultStatement) {
|
||||
lbl = factory.createLabeledNode(IBranchNode.DEFAULT);
|
||||
lbl = factory.createBranchNode(IBranchNode.DEFAULT);
|
||||
}
|
||||
if (!(prev instanceof IExitNode) && prev != switchNode) {
|
||||
IConnectorNode here = factory.createConnectorNode();
|
||||
|
@ -231,7 +280,7 @@ public class ControlFlowGraphBuilder {
|
|||
IConnectorNode nBreak = factory.createConnectorNode();
|
||||
decision.setMergeNode(nBreak);
|
||||
// create body and jump to continue node
|
||||
IBranchNode loopStart = factory.createLabeledNode(IBranchNode.THEN);
|
||||
IBranchNode loopStart = factory.createBranchNode(IBranchNode.THEN);
|
||||
addOutgoing(decision, loopStart);
|
||||
// set break/continue
|
||||
IConnectorNode nContinue = factory.createConnectorNode();
|
||||
|
@ -250,7 +299,7 @@ public class ControlFlowGraphBuilder {
|
|||
// connect with backward link
|
||||
addJump(inc, beforeCheck, true);
|
||||
// add "else" branch
|
||||
IBranchNode loopEnd = factory.createLabeledNode(IBranchNode.ELSE);
|
||||
IBranchNode loopEnd = factory.createBranchNode(IBranchNode.ELSE);
|
||||
addOutgoing(decision, loopEnd);
|
||||
addJump(loopEnd, nBreak);
|
||||
return nBreak;
|
||||
|
@ -273,7 +322,7 @@ public class ControlFlowGraphBuilder {
|
|||
IConnectorNode nBreak = factory.createConnectorNode();
|
||||
decision.setMergeNode(nBreak);
|
||||
// create body and jump to continue node
|
||||
IBranchNode loopStart = factory.createLabeledNode(IBranchNode.THEN);
|
||||
IBranchNode loopStart = factory.createBranchNode(IBranchNode.THEN);
|
||||
addOutgoing(decision, loopStart);
|
||||
// set break/continue
|
||||
IConnectorNode savedContinue = outerContinue;
|
||||
|
@ -287,7 +336,7 @@ public class ControlFlowGraphBuilder {
|
|||
// backward jump
|
||||
addJump(endBody, nContinue, true);
|
||||
// connect with else branch
|
||||
IBranchNode loopEnd = factory.createLabeledNode(IBranchNode.ELSE);
|
||||
IBranchNode loopEnd = factory.createBranchNode(IBranchNode.ELSE);
|
||||
addOutgoing(decision, loopEnd);
|
||||
addJump(loopEnd, nBreak);
|
||||
return nBreak;
|
||||
|
@ -315,7 +364,7 @@ public class ControlFlowGraphBuilder {
|
|||
.getCondition());
|
||||
addOutgoing(nContinue, decision);
|
||||
// then branch
|
||||
IBranchNode thenNode = factory.createLabeledNode(IBranchNode.THEN);
|
||||
IBranchNode thenNode = factory.createBranchNode(IBranchNode.THEN);
|
||||
addOutgoing(decision, thenNode);
|
||||
IJumpNode jumpToStart = factory.createJumpNode();
|
||||
addOutgoing(thenNode, jumpToStart);
|
||||
|
@ -323,7 +372,7 @@ public class ControlFlowGraphBuilder {
|
|||
// connect with backward link
|
||||
addOutgoing(jumpToStart, loopStart);
|
||||
// connect with else branch
|
||||
IBranchNode loopEnd = factory.createLabeledNode(IBranchNode.ELSE);
|
||||
IBranchNode loopEnd = factory.createBranchNode(IBranchNode.ELSE);
|
||||
addOutgoing(decision, loopEnd);
|
||||
// add break connector
|
||||
decision.setMergeNode(nBreak);
|
||||
|
@ -339,6 +388,8 @@ public class ControlFlowGraphBuilder {
|
|||
boolean backward) {
|
||||
if (prev instanceof IJumpNode)
|
||||
return (IJumpNode) prev;
|
||||
if (prev instanceof IExitNode)
|
||||
return null;
|
||||
IJumpNode jump = factory.createJumpNode();
|
||||
addOutgoing(prev, jump);
|
||||
addOutgoing(jump, conn);
|
||||
|
@ -351,12 +402,13 @@ public class ControlFlowGraphBuilder {
|
|||
* @param node
|
||||
*/
|
||||
private void addOutgoing(IBasicBlock prev, IBasicBlock node) {
|
||||
if (!(node instanceof IStartNode))
|
||||
((AbstractBasicBlock) node).addIncoming(prev);
|
||||
if (prev instanceof IExitNode) {
|
||||
if (prev instanceof IExitNode || prev == null) {
|
||||
dead.add(node);
|
||||
return;
|
||||
} else if (prev instanceof AbstractBasicBlock) {
|
||||
((AbstractBasicBlock) prev).addOutgoing(node);
|
||||
}
|
||||
if (!(node instanceof IStartNode))
|
||||
((AbstractBasicBlock) node).addIncoming(prev);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,8 +61,8 @@ public class CxxNodeFactory extends NodeFactory implements INodeFactory {
|
|||
* @param caseSt
|
||||
* @return
|
||||
*/
|
||||
public IBranchNode createLabeledNode(IASTNode caseSt) {
|
||||
IBranchNode node = createLabeledNode(caseSt.getRawSignature());
|
||||
public IBranchNode createBranchNode(IASTNode caseSt) {
|
||||
IBranchNode node = createBranchNode(caseSt.getRawSignature());
|
||||
((AbstractBasicBlock) node).setData(caseSt);
|
||||
return node;
|
||||
}
|
||||
|
|
|
@ -15,9 +15,17 @@ import java.util.Iterator;
|
|||
|
||||
import org.eclipse.cdt.codan.core.cxx.internal.model.cfg.ControlFlowGraphBuilder;
|
||||
import org.eclipse.cdt.codan.core.test.CodanTestCase;
|
||||
import org.eclipse.cdt.codan.internal.core.cfg.AbstractBasicBlock;
|
||||
import org.eclipse.cdt.codan.internal.core.cfg.ControlFlowGraph;
|
||||
import org.eclipse.cdt.codan.provisional.core.model.cfg.IBasicBlock;
|
||||
import org.eclipse.cdt.codan.provisional.core.model.cfg.IBranchNode;
|
||||
import org.eclipse.cdt.codan.provisional.core.model.cfg.IConnectorNode;
|
||||
import org.eclipse.cdt.codan.provisional.core.model.cfg.IDecisionNode;
|
||||
import org.eclipse.cdt.codan.provisional.core.model.cfg.IExitNode;
|
||||
import org.eclipse.cdt.codan.provisional.core.model.cfg.IJumpNode;
|
||||
import org.eclipse.cdt.codan.provisional.core.model.cfg.IPlainNode;
|
||||
import org.eclipse.cdt.codan.provisional.core.model.cfg.ISingleOutgoing;
|
||||
import org.eclipse.cdt.codan.provisional.core.model.cfg.IStartNode;
|
||||
import org.eclipse.cdt.core.CCorePlugin;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
|
||||
|
@ -36,6 +44,7 @@ import org.eclipse.core.runtime.CoreException;
|
|||
*/
|
||||
public class ControlFlowGraphTest extends CodanTestCase {
|
||||
ControlFlowGraph graph;
|
||||
|
||||
void processFile(IFile file) throws CoreException, InterruptedException {
|
||||
// create translation unit and access index
|
||||
ICElement model = CoreModel.getDefault().create(file);
|
||||
|
@ -64,28 +73,30 @@ public class ControlFlowGraphTest extends CodanTestCase {
|
|||
{
|
||||
shouldVisitDeclarations = true;
|
||||
}
|
||||
|
||||
public int visit(IASTDeclaration decl) {
|
||||
if (decl instanceof IASTFunctionDefinition) {
|
||||
graph = new ControlFlowGraphBuilder().build((IASTFunctionDefinition) decl);
|
||||
graph = new ControlFlowGraphBuilder()
|
||||
.build((IASTFunctionDefinition) decl);
|
||||
return PROCESS_ABORT;
|
||||
}
|
||||
return PROCESS_CONTINUE;
|
||||
}
|
||||
};
|
||||
ast.accept(visitor);
|
||||
|
||||
}
|
||||
|
||||
void buildCfg() {
|
||||
try {
|
||||
|
||||
IResource el = cproject.getProject().findMember(currentFile.getName());
|
||||
IResource el = cproject.getProject().findMember(
|
||||
currentFile.getName());
|
||||
processFile((IFile) el);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
fail(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
@ -93,28 +104,32 @@ public class ControlFlowGraphTest extends CodanTestCase {
|
|||
assertNotNull(graph);
|
||||
assertNotNull(graph.getStartNode());
|
||||
Collection<IBasicBlock> nodes = graph.getNodes();
|
||||
for (Iterator<IBasicBlock> iterator = nodes.iterator(); iterator.hasNext();) {
|
||||
IBasicBlock node = iterator.next();
|
||||
for (Iterator<IBasicBlock> iterator = nodes.iterator(); iterator
|
||||
.hasNext();) {
|
||||
IBasicBlock node = iterator.next();
|
||||
checkNode(node);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param node
|
||||
*/
|
||||
private void checkNode(IBasicBlock node) {
|
||||
for (Iterator<IBasicBlock> iterator = node.getIncomingIterator(); iterator.hasNext();) {
|
||||
for (Iterator<IBasicBlock> iterator = node.getIncomingIterator(); iterator
|
||||
.hasNext();) {
|
||||
IBasicBlock b = iterator.next();
|
||||
if (!contains(node, b.getOutgoingIterator()))
|
||||
fail("Block "+node+" inconsitent prev/next "+b);
|
||||
fail("Block " + node + " inconsitent prev/next " + b);
|
||||
}
|
||||
for (Iterator<IBasicBlock> iterator = node.getOutgoingIterator(); iterator.hasNext();) {
|
||||
for (Iterator<IBasicBlock> iterator = node.getOutgoingIterator(); iterator
|
||||
.hasNext();) {
|
||||
IBasicBlock b = iterator.next();
|
||||
if (!contains(node, b.getIncomingIterator()))
|
||||
fail("Block "+node+" inconsitent next/prev "+b);
|
||||
fail("Block " + node + " inconsitent next/prev " + b);
|
||||
}
|
||||
if (node instanceof IDecisionNode) {
|
||||
assertTrue("decision node outgping size",node.getOutgoingSize()>1);
|
||||
assertTrue("decision node outgping size",
|
||||
node.getOutgoingSize() > 1);
|
||||
assertNotNull(((IDecisionNode) node).getMergeNode());
|
||||
}
|
||||
}
|
||||
|
@ -124,15 +139,62 @@ public class ControlFlowGraphTest extends CodanTestCase {
|
|||
* @param outgoingIterator
|
||||
* @return
|
||||
*/
|
||||
private boolean contains(IBasicBlock node,
|
||||
Iterator<IBasicBlock> iterator) {
|
||||
private boolean contains(IBasicBlock node, Iterator<IBasicBlock> iterator) {
|
||||
for (; iterator.hasNext();) {
|
||||
IBasicBlock b = iterator.next();
|
||||
if (b.equals(node)) return true;
|
||||
if (b.equals(node))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param file
|
||||
*/
|
||||
protected void buildAndCheck(String file) {
|
||||
load(file);
|
||||
buildCfg();
|
||||
checkCfg();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param des
|
||||
* @return
|
||||
*/
|
||||
private String data(IBasicBlock des) {
|
||||
return ((AbstractBasicBlock) des).toStringData();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return first node after the branch
|
||||
*
|
||||
* @param des
|
||||
* @return
|
||||
*/
|
||||
private IBasicBlock branchEnd(IDecisionNode des, String label) {
|
||||
for (Iterator<IBasicBlock> iterator = des.getOutgoingIterator(); iterator
|
||||
.hasNext();) {
|
||||
IBranchNode bn = (IBranchNode) iterator.next();
|
||||
if (label.equals(bn.getLabel()))
|
||||
return bn.getOutgoing();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return node where control jumps, following the chain until jump is hit
|
||||
*
|
||||
* @param a
|
||||
* @return
|
||||
*/
|
||||
private IBasicBlock jumpEnd(IBasicBlock a) {
|
||||
if (a instanceof IJumpNode)
|
||||
return ((IJumpNode) a).getOutgoing();
|
||||
if (a instanceof ISingleOutgoing)
|
||||
return jumpEnd(((ISingleOutgoing) a).getOutgoing());
|
||||
return null;
|
||||
}
|
||||
|
||||
/*-
|
||||
<code file="test1.c">
|
||||
main() {
|
||||
|
@ -141,11 +203,8 @@ public class ControlFlowGraphTest extends CodanTestCase {
|
|||
}
|
||||
</code>
|
||||
*/
|
||||
public void test1() {
|
||||
load("test1.c");
|
||||
buildCfg();
|
||||
checkCfg();
|
||||
|
||||
public void test_basic() {
|
||||
buildAndCheck("test1.c");
|
||||
}
|
||||
|
||||
/*-
|
||||
|
@ -159,10 +218,110 @@ public class ControlFlowGraphTest extends CodanTestCase {
|
|||
</code>
|
||||
*/
|
||||
public void test_while() {
|
||||
load("test2.c");
|
||||
buildCfg();
|
||||
checkCfg();
|
||||
|
||||
buildAndCheck("test2.c");
|
||||
IStartNode startNode = graph.getStartNode();
|
||||
IPlainNode decl = (IPlainNode) startNode.getOutgoing();
|
||||
IConnectorNode conn = (IConnectorNode) decl.getOutgoing();
|
||||
IDecisionNode des = (IDecisionNode) conn.getOutgoing();
|
||||
assertEquals("a--", data(des));
|
||||
IPlainNode bThen = (IPlainNode) branchEnd(des, IBranchNode.THEN);
|
||||
assertEquals("a=a-2;", data(bThen));
|
||||
IBasicBlock bElse = branchEnd(des, IBranchNode.ELSE);
|
||||
IBasicBlock m2 = jumpEnd(bThen);
|
||||
IBasicBlock m1 = jumpEnd(bElse);
|
||||
assertSame(conn, m2);
|
||||
IExitNode ret = (IExitNode) ((IConnectorNode) m1).getOutgoing();
|
||||
}
|
||||
|
||||
/*-
|
||||
<code file="test3.c">
|
||||
main() {
|
||||
int a=10;
|
||||
if (a--) {
|
||||
a=a-2;
|
||||
}
|
||||
}
|
||||
</code>
|
||||
*/
|
||||
public void test_if() {
|
||||
buildAndCheck("test3.c");
|
||||
IStartNode startNode = graph.getStartNode();
|
||||
IPlainNode decl = (IPlainNode) startNode.getOutgoing();
|
||||
IDecisionNode des = (IDecisionNode) decl.getOutgoing();
|
||||
assertEquals("a--", data(des));
|
||||
IPlainNode bThen = (IPlainNode) branchEnd(des, IBranchNode.THEN);
|
||||
assertEquals("a=a-2;", data(bThen));
|
||||
IBasicBlock bElse = branchEnd(des, IBranchNode.ELSE);
|
||||
IBasicBlock m2 = jumpEnd(bThen);
|
||||
IBasicBlock m1 = jumpEnd(bElse);
|
||||
assertSame(m1, m2);
|
||||
}
|
||||
|
||||
/*-
|
||||
<code file="test4.c">
|
||||
main() {
|
||||
int a=10;
|
||||
if (a--) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
</code>
|
||||
*/
|
||||
public void test_if_ret() {
|
||||
buildAndCheck("test4.c");
|
||||
IStartNode startNode = graph.getStartNode();
|
||||
IPlainNode decl = (IPlainNode) startNode.getOutgoing();
|
||||
IDecisionNode des = (IDecisionNode) decl.getOutgoing();
|
||||
assertEquals("a--", data(des));
|
||||
IExitNode bThen = (IExitNode) branchEnd(des, IBranchNode.THEN);
|
||||
IBasicBlock bElse = branchEnd(des, IBranchNode.ELSE);
|
||||
IBasicBlock m1 = jumpEnd(bElse);
|
||||
}
|
||||
/*-
|
||||
<code file="test5.c">
|
||||
main() {
|
||||
int a=10;
|
||||
if (a--) {
|
||||
return;
|
||||
a++;
|
||||
}
|
||||
}
|
||||
</code>
|
||||
*/
|
||||
public void test_if_dead() {
|
||||
buildAndCheck("test5.c");
|
||||
IStartNode startNode = graph.getStartNode();
|
||||
IPlainNode decl = (IPlainNode) startNode.getOutgoing();
|
||||
IDecisionNode des = (IDecisionNode) decl.getOutgoing();
|
||||
assertEquals("a--", data(des));
|
||||
IExitNode bThen = (IExitNode) branchEnd(des, IBranchNode.THEN);
|
||||
IBasicBlock bElse = branchEnd(des, IBranchNode.ELSE);
|
||||
IBasicBlock m1 = jumpEnd(bElse);
|
||||
assertEquals(1,graph.getUnconnectedNodeSize());
|
||||
}
|
||||
/*-
|
||||
<code file="test_ifif.c">
|
||||
foo() {
|
||||
int a=10, x=5;
|
||||
if (a--) {
|
||||
if (x<0)
|
||||
a++;
|
||||
}
|
||||
}
|
||||
</code>
|
||||
*/
|
||||
public void test_ifif() {
|
||||
buildAndCheck("test_ifif.c");
|
||||
IStartNode startNode = graph.getStartNode();
|
||||
IPlainNode decl = (IPlainNode) startNode.getOutgoing();
|
||||
IDecisionNode des = (IDecisionNode) decl.getOutgoing();
|
||||
assertEquals("a--", data(des));
|
||||
IDecisionNode bThen = (IDecisionNode) branchEnd(des, IBranchNode.THEN);
|
||||
assertEquals("x<0", data(bThen));
|
||||
IBasicBlock bElse = branchEnd(des, IBranchNode.ELSE);
|
||||
IBasicBlock m2 = jumpEnd(branchEnd(bThen,IBranchNode.THEN));
|
||||
IBasicBlock m1 = jumpEnd(bElse);
|
||||
IBasicBlock m3 = jumpEnd(m2);
|
||||
assertSame(m1, m3);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ public abstract class AbstractBasicBlock implements IBasicBlock {
|
|||
*/
|
||||
public String toStringData() {
|
||||
if (getData() == null)
|
||||
return "";
|
||||
return "0x" + Integer.toHexString(System.identityHashCode(this));
|
||||
return getData().toString();
|
||||
}
|
||||
|
||||
|
|
|
@ -18,11 +18,11 @@ import java.util.LinkedHashSet;
|
|||
import java.util.List;
|
||||
|
||||
import org.eclipse.cdt.codan.provisional.core.model.cfg.IBasicBlock;
|
||||
import org.eclipse.cdt.codan.provisional.core.model.cfg.IBranchNode;
|
||||
import org.eclipse.cdt.codan.provisional.core.model.cfg.IConnectorNode;
|
||||
import org.eclipse.cdt.codan.provisional.core.model.cfg.IControlFlowGraph;
|
||||
import org.eclipse.cdt.codan.provisional.core.model.cfg.IDecisionNode;
|
||||
import org.eclipse.cdt.codan.provisional.core.model.cfg.IExitNode;
|
||||
import org.eclipse.cdt.codan.provisional.core.model.cfg.IBranchNode;
|
||||
import org.eclipse.cdt.codan.provisional.core.model.cfg.ISingleOutgoing;
|
||||
import org.eclipse.cdt.codan.provisional.core.model.cfg.IStartNode;
|
||||
|
||||
|
@ -55,6 +55,11 @@ public class ControlFlowGraph implements IControlFlowGraph {
|
|||
exitNodes));
|
||||
}
|
||||
|
||||
public void setUnconnectedNodes(Collection<IBasicBlock> nodes) {
|
||||
this.deadNodes = Collections
|
||||
.unmodifiableList(new ArrayList<IBasicBlock>(nodes));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
|
@ -97,8 +102,7 @@ public class ControlFlowGraph implements IControlFlowGraph {
|
|||
* getUnconnectedNodeIterator()
|
||||
*/
|
||||
public Iterator<IBasicBlock> getUnconnectedNodeIterator() {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
return deadNodes.iterator();
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -108,8 +112,7 @@ public class ControlFlowGraph implements IControlFlowGraph {
|
|||
* getUnconnectedNodeSize()
|
||||
*/
|
||||
public int getUnconnectedNodeSize() {
|
||||
// TODO Auto-generated method stub
|
||||
return 0;
|
||||
return deadNodes.size();
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -22,7 +22,7 @@ public interface INodeFactory {
|
|||
|
||||
IConnectorNode createConnectorNode();
|
||||
|
||||
IBranchNode createLabeledNode(String label);
|
||||
IBranchNode createBranchNode(String label);
|
||||
|
||||
IStartNode createStartNode();
|
||||
|
||||
|
|
|
@ -101,7 +101,7 @@ public class NodeFactory implements INodeFactory {
|
|||
return new ExitNode();
|
||||
}
|
||||
|
||||
public IBranchNode createLabeledNode(String label) {
|
||||
public IBranchNode createBranchNode(String label) {
|
||||
return new BranchNode(label);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -171,12 +171,10 @@ public class ControlFlowGraphView extends ViewPart {
|
|||
if (obj instanceof AbstractBasicBlock) {
|
||||
strdata = ((AbstractBasicBlock) obj).toStringData();
|
||||
}
|
||||
if (strdata == null || strdata.length() == 0) {
|
||||
if (obj instanceof IConnectorNode) {
|
||||
strdata = blockHexLabel(obj);
|
||||
} else if (obj instanceof IJumpNode) {
|
||||
strdata = blockHexLabel(((IJumpNode) obj).getJumpNode());
|
||||
}
|
||||
if (obj instanceof IConnectorNode) {
|
||||
strdata = blockHexLabel(obj) ;
|
||||
} else if (obj instanceof IJumpNode) {
|
||||
strdata = "jump to "+blockHexLabel(((IJumpNode) obj).getJumpNode());
|
||||
}
|
||||
return obj.getClass().getSimpleName() + ": " + strdata;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue