1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-23 17:05:26 +02:00

Clean up interfaces for control flow graph

This commit is contained in:
Alena Laskavaia 2010-05-25 02:16:11 +00:00
parent 6a49ab36dd
commit 3ec7ac60fa
16 changed files with 114 additions and 121 deletions

View file

@ -161,6 +161,8 @@ public class ControlFlowGraphBuilder {
CxxPlainNode node = factory.createPlainNode(body);
addOutgoing(prev, node);
return node;
} else if (body == null) {
// skip - sometimes body is empty such as no else
} else {
System.err.println("unknown statement for cfg: " + body); //$NON-NLS-1$
}
@ -172,16 +174,24 @@ public class ControlFlowGraphBuilder {
* @return
*/
private boolean isThrowStatement(IASTNode body) {
if (!(body instanceof IASTExpressionStatement)) return false;
IASTExpression expression = ((IASTExpressionStatement) body).getExpression();
if (!(expression instanceof IASTUnaryExpression)) return false;
if (!(body instanceof IASTExpressionStatement))
return false;
IASTExpression expression = ((IASTExpressionStatement) body)
.getExpression();
if (!(expression instanceof IASTUnaryExpression))
return false;
return ((IASTUnaryExpression) expression).getOperator() == IASTUnaryExpression.op_throw;
}
private boolean isExitStatement(IASTNode body) {
if (!(body instanceof IASTExpressionStatement)) return false;
IASTExpression expression = ((IASTExpressionStatement) body).getExpression();
if (!(expression instanceof IASTFunctionCallExpression)) return false;
IASTExpression functionNameExpression = ((IASTFunctionCallExpression) expression).getFunctionNameExpression();
if (!(body instanceof IASTExpressionStatement))
return false;
IASTExpression expression = ((IASTExpressionStatement) body)
.getExpression();
if (!(expression instanceof IASTFunctionCallExpression))
return false;
IASTExpression functionNameExpression = ((IASTFunctionCallExpression) expression)
.getFunctionNameExpression();
return functionNameExpression.getRawSignature().equals("exit"); //$NON-NLS-1$
}

View file

@ -14,6 +14,7 @@ import java.util.Collection;
import java.util.Iterator;
import org.eclipse.cdt.codan.core.cxx.internal.model.cfg.ControlFlowGraphBuilder;
import org.eclipse.cdt.codan.core.model.IChecker;
import org.eclipse.cdt.codan.core.model.cfg.IBasicBlock;
import org.eclipse.cdt.codan.core.model.cfg.IBranchNode;
import org.eclipse.cdt.codan.core.model.cfg.IConnectorNode;
@ -23,48 +24,21 @@ 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.core.test.CodanTestCase;
import org.eclipse.cdt.codan.core.test.CodanFastCxxAstTestCase;
import org.eclipse.cdt.codan.internal.core.cfg.AbstractBasicBlock;
import org.eclipse.cdt.codan.internal.core.cfg.ControlFlowGraph;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.c.CASTVisitor;
import org.eclipse.cdt.core.index.IIndex;
import org.eclipse.cdt.core.model.CoreModel;
import org.eclipse.cdt.core.model.ICElement;
import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.cdt.core.parser.ParserLanguage;
/**
* TODO: add description
*/
public class ControlFlowGraphTest extends CodanTestCase {
public class ControlFlowGraphTest extends CodanFastCxxAstTestCase {
ControlFlowGraph graph;
void processFile(IFile file) throws CoreException, InterruptedException {
// create translation unit and access index
ICElement model = CoreModel.getDefault().create(file);
if (!(model instanceof ITranslationUnit))
return; // not a C/C++ file
ITranslationUnit tu = (ITranslationUnit) model;
IIndex index = CCorePlugin.getIndexManager().getIndex(tu.getCProject());
// lock the index for read access
index.acquireReadLock();
try {
// create index based ast
IASTTranslationUnit ast = tu.getAST(index,
ITranslationUnit.AST_SKIP_INDEXED_HEADERS);
// traverse the ast using the visitor pattern.
processAst(ast);
} finally {
index.releaseReadLock();
}
}
/**
* @param ast
*/
@ -74,6 +48,7 @@ public class ControlFlowGraphTest extends CodanTestCase {
shouldVisitDeclarations = true;
}
@Override
public int visit(IASTDeclaration decl) {
if (decl instanceof IASTFunctionDefinition) {
graph = new ControlFlowGraphBuilder()
@ -86,17 +61,6 @@ public class ControlFlowGraphTest extends CodanTestCase {
ast.accept(visitor);
}
void buildCfg() {
try {
IResource el = cproject.getProject().findMember(
currentFile.getName());
processFile((IFile) el);
} catch (Exception e) {
e.printStackTrace();
fail(e.getMessage());
}
}
/**
*
*/
@ -115,16 +79,16 @@ public class ControlFlowGraphTest extends CodanTestCase {
* @param node
*/
private void checkNode(IBasicBlock node) {
for (Iterator<IBasicBlock> iterator = node.getIncomingIterator(); iterator
.hasNext();) {
IBasicBlock b = iterator.next();
if (!contains(node, b.getOutgoingIterator()))
IBasicBlock[] incomingNodes = node.getIncomingNodes();
for (int i = 0; i < incomingNodes.length; i++) {
IBasicBlock b = incomingNodes[i];
if (!contains(node, b.getOutgoingNodes()))
fail("Block " + node + " inconsitent prev/next " + b);
}
for (Iterator<IBasicBlock> iterator = node.getOutgoingIterator(); iterator
.hasNext();) {
IBasicBlock b = iterator.next();
if (!contains(node, b.getIncomingIterator()))
IBasicBlock[] outgoingNodes = node.getOutgoingNodes();
for (int i = 0; i < outgoingNodes.length; i++) {
IBasicBlock b = outgoingNodes[i];
if (!contains(node, b.getIncomingNodes()))
fail("Block " + node + " inconsitent next/prev " + b);
}
if (node instanceof IDecisionNode) {
@ -139,9 +103,9 @@ public class ControlFlowGraphTest extends CodanTestCase {
* @param outgoingIterator
* @return
*/
private boolean contains(IBasicBlock node, Iterator<IBasicBlock> iterator) {
for (; iterator.hasNext();) {
IBasicBlock b = iterator.next();
private boolean contains(IBasicBlock node, IBasicBlock[] blocks) {
for (int i = 0; i < blocks.length; i++) {
IBasicBlock b = blocks[i];
if (b.equals(node))
return true;
}
@ -151,18 +115,28 @@ public class ControlFlowGraphTest extends CodanTestCase {
protected void buildAndCheck(String code) {
buildAndCheck(code, false);
}
protected void buildAndCheck_cpp(String code) {
buildAndCheck(code, true);
}
/**
* @param file
*/
protected void buildAndCheck(String code, boolean cpp) {
loadcode(code, cpp);
buildCfg();
buildCfg(code, cpp);
checkCfg();
}
/**
* @param code
* @param cpp
*/
private void buildCfg(String code, boolean cpp) {
parse(code, cpp ? ParserLanguage.CPP : ParserLanguage.C, true);
processAst(tu);
}
/**
* @param des
* @return
@ -178,9 +152,10 @@ public class ControlFlowGraphTest extends CodanTestCase {
* @return
*/
private IBasicBlock branchEnd(IDecisionNode des, String label) {
for (Iterator<IBasicBlock> iterator = des.getOutgoingIterator(); iterator
.hasNext();) {
IBranchNode bn = (IBranchNode) iterator.next();
IBasicBlock[] outgoingNodes = des.getOutgoingNodes();
for (int i = 0; i < outgoingNodes.length; i++) {
IBasicBlock iBasicBlock = outgoingNodes[i];
IBranchNode bn = (IBranchNode) iBasicBlock;
if (label.equals(bn.getLabel()))
return bn.getOutgoing();
}
@ -273,6 +248,17 @@ public class ControlFlowGraphTest extends CodanTestCase {
IBasicBlock m1 = jumpEnd(bElse);
}
// main() {
// return;
// a++;
// }
public void test_dead() {
buildCfg(getAboveComment(), false);
IStartNode startNode = graph.getStartNode();
IExitNode ret = (IExitNode) startNode.getOutgoing();
assertEquals(1, graph.getUnconnectedNodeSize());
}
// main() {
// int a=10;
// if (a--) {
@ -281,7 +267,7 @@ public class ControlFlowGraphTest extends CodanTestCase {
// }
// }
public void test_if_dead() {
buildAndCheck(getAboveComment());
buildCfg(getAboveComment(), false);
IStartNode startNode = graph.getStartNode();
IPlainNode decl = (IPlainNode) startNode.getOutgoing();
IDecisionNode des = (IDecisionNode) decl.getOutgoing();
@ -337,4 +323,14 @@ public class ControlFlowGraphTest extends CodanTestCase {
IExitNode exit = exitNodeIterator.next();
assertEquals("exit(0);", data(exit));
}
/*
* (non-Javadoc)
*
* @see org.eclipse.cdt.codan.core.test.CodanFastCxxAstTestCase#getChecker()
*/
@Override
public IChecker getChecker() {
return null;
}
}

View file

@ -48,7 +48,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
*/
@SuppressWarnings("restriction")
public abstract class CodanFastCxxAstTestCase extends TestCase {
IASTTranslationUnit tu;
protected IASTTranslationUnit tu;
protected String getAboveComment() {
return getContents(1)[0].toString();
@ -118,6 +118,7 @@ public abstract class CodanFastCxxAstTestCase extends TestCase {
assertEquals(problems.length, 0);
}
}
this.tu = tu;
return tu;
}

View file

@ -14,6 +14,7 @@ package org.eclipse.cdt.codan.core.test;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.eclipse.cdt.codan.core.cfg.ControlFlowGraphTest;
import org.eclipse.cdt.codan.core.cxx.CxxAstUtilsTest;
import org.eclipse.cdt.codan.core.param.BasicProblemPreferenceTest;
import org.eclipse.cdt.codan.core.param.ListProblemPreferenceTest;
@ -41,6 +42,7 @@ public class CodanFastTestSuite extends TestSuite {
suite.addTestSuite(ListProblemPreferenceTest.class);
suite.addTestSuite(MapProblemPreferenceTest.class);
suite.addTestSuite(CxxAstUtilsTest.class);
suite.addTestSuite(ControlFlowGraphTest.class);
return suite;
}
}

View file

@ -1,6 +1,5 @@
package org.eclipse.cdt.codan.core.model.cfg;
import java.util.Iterator;
/**
*
@ -12,9 +11,9 @@ import java.util.Iterator;
* <li>{@link I}
*/
public interface IBasicBlock {
Iterator<IBasicBlock> getIncomingIterator();
IBasicBlock[] getIncomingNodes();
Iterator<IBasicBlock> getOutgoingIterator();
IBasicBlock[] getOutgoingNodes();
int getIncomingSize();

View file

@ -6,17 +6,24 @@ import org.eclipse.cdt.codan.core.model.cfg.IBasicBlock;
import org.eclipse.cdt.codan.core.model.cfg.ICfgData;
public abstract class AbstractBasicBlock implements IBasicBlock, ICfgData {
public final static IBasicBlock[] EMPTY_LIST = new IBasicBlock[0];
private Object data;
/* (non-Javadoc)
/*
* (non-Javadoc)
*
* @see org.eclipse.cdt.codan.internal.core.cfg.ICfgData#getData()
*/
public Object getData() {
return data;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.codan.internal.core.cfg.ICfgData#setData(java.lang.Object)
/*
* (non-Javadoc)
*
* @see
* org.eclipse.cdt.codan.internal.core.cfg.ICfgData#setData(java.lang.Object
* )
*/
public void setData(Object data) {
this.data = data;

View file

@ -1,7 +1,5 @@
package org.eclipse.cdt.codan.internal.core.cfg;
import java.util.Iterator;
import org.eclipse.cdt.codan.core.model.cfg.IBasicBlock;
import org.eclipse.cdt.codan.core.model.cfg.ISingleIncoming;
@ -17,8 +15,8 @@ public abstract class AbstractSingleIncomingNode extends AbstractBasicBlock
super();
}
public Iterator<IBasicBlock> getIncomingIterator() {
return new OneElementIterator<IBasicBlock>(prev);
public IBasicBlock[] getIncomingNodes() {
return new IBasicBlock[] { prev };
}
public int getIncomingSize() {

View file

@ -1,7 +1,5 @@
package org.eclipse.cdt.codan.internal.core.cfg;
import java.util.Iterator;
import org.eclipse.cdt.codan.core.model.cfg.IBasicBlock;
import org.eclipse.cdt.codan.core.model.cfg.ISingleOutgoing;
@ -17,8 +15,8 @@ public abstract class AbstractSingleOutgoingNode extends AbstractBasicBlock
super();
}
public Iterator<IBasicBlock> getOutgoingIterator() {
return new OneElementIterator<IBasicBlock>(next);
public IBasicBlock[] getOutgoingNodes() {
return new IBasicBlock[] { next };
}
public int getOutgoingSize() {

View file

@ -11,7 +11,6 @@
package org.eclipse.cdt.codan.internal.core.cfg;
import java.util.ArrayList;
import java.util.Iterator;
import org.eclipse.cdt.codan.core.model.cfg.IBasicBlock;
import org.eclipse.cdt.codan.core.model.cfg.IConnectorNode;
@ -39,8 +38,8 @@ public class ConnectorNode extends AbstractSingleOutgoingNode implements
* @seeorg.eclipse.cdt.codan.provisional.core.model.cfg.IBasicBlock#
* getIncomingIterator()
*/
public Iterator<IBasicBlock> getIncomingIterator() {
return incoming.iterator();
public IBasicBlock[] getIncomingNodes() {
return incoming.toArray(new IBasicBlock[incoming.size()]);
}
/*

View file

@ -79,10 +79,9 @@ public class ControlFlowGraph implements IControlFlowGraph {
+ ((AbstractBasicBlock) node).toStringData());
if (node instanceof IDecisionNode) {
// todo
Iterator<IBasicBlock> branches = ((IDecisionNode) node)
.getOutgoingIterator();
for (; branches.hasNext();) {
IBasicBlock brNode = branches.next();
IBasicBlock[] branches = ((IDecisionNode) node).getOutgoingNodes();
for (int i = 0; i < branches.length; i++) {
IBasicBlock brNode = branches[i];
System.out.println("{"); //$NON-NLS-1$
print(brNode);
System.out.println("}"); //$NON-NLS-1$
@ -139,9 +138,9 @@ public class ControlFlowGraph implements IControlFlowGraph {
if (result.contains(start))
return;
result.add(start);
for (Iterator<IBasicBlock> outgoingIterator = start
.getOutgoingIterator(); outgoingIterator.hasNext();) {
IBasicBlock b = outgoingIterator.next();
IBasicBlock[] outgoingNodes = start.getOutgoingNodes();
for (int i = 0; i < outgoingNodes.length; i++) {
IBasicBlock b = outgoingNodes[i];
getNodes(b, result);
}
}

View file

@ -11,7 +11,6 @@
package org.eclipse.cdt.codan.internal.core.cfg;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.eclipse.cdt.codan.core.model.cfg.IBasicBlock;
@ -46,8 +45,8 @@ public class DecisionNode extends AbstractSingleIncomingNode implements
* @seeorg.eclipse.cdt.codan.provisional.core.model.cfg.IBasicBlock#
* getOutgoingIterator()
*/
public Iterator<IBasicBlock> getOutgoingIterator() {
return next.iterator();
public IBasicBlock[] getOutgoingNodes() {
return next.toArray(new IBasicBlock[next.size()]);
}
/*

View file

@ -1,8 +1,5 @@
package org.eclipse.cdt.codan.internal.core.cfg;
import java.util.Collections;
import java.util.Iterator;
import org.eclipse.cdt.codan.core.model.cfg.IBasicBlock;
import org.eclipse.cdt.codan.core.model.cfg.IExitNode;
import org.eclipse.cdt.codan.core.model.cfg.IStartNode;
@ -18,9 +15,8 @@ public class ExitNode extends AbstractSingleIncomingNode implements IExitNode {
super();
}
@SuppressWarnings("unchecked")
public Iterator<IBasicBlock> getOutgoingIterator() {
return Collections.EMPTY_LIST.iterator();
public IBasicBlock[] getOutgoingNodes() {
return EMPTY_LIST;
}
public int getOutgoingSize() {

View file

@ -1,7 +1,5 @@
package org.eclipse.cdt.codan.internal.core.cfg;
import java.util.Iterator;
import org.eclipse.cdt.codan.core.model.cfg.IBasicBlock;
import org.eclipse.cdt.codan.core.model.cfg.IConnectorNode;
import org.eclipse.cdt.codan.core.model.cfg.IJumpNode;
@ -19,8 +17,8 @@ public class JumpNode extends AbstractSingleIncomingNode implements IJumpNode {
super();
}
public Iterator<IBasicBlock> getOutgoingIterator() {
return new OneElementIterator<IBasicBlock>(jump);
public IBasicBlock[] getOutgoingNodes() {
return new IBasicBlock[] { jump };
}
public int getOutgoingSize() {

View file

@ -1,7 +1,5 @@
package org.eclipse.cdt.codan.internal.core.cfg;
import java.util.Iterator;
import org.eclipse.cdt.codan.core.model.cfg.IBasicBlock;
import org.eclipse.cdt.codan.core.model.cfg.IPlainNode;
@ -16,8 +14,8 @@ public class PlainNode extends AbstractSingleIncomingNode implements IPlainNode
super();
}
public Iterator<IBasicBlock> getOutgoingIterator() {
return new OneElementIterator<IBasicBlock>(next);
public IBasicBlock[] getOutgoingNodes() {
return new IBasicBlock[] { next };
}
public int getOutgoingSize() {

View file

@ -1,8 +1,5 @@
package org.eclipse.cdt.codan.internal.core.cfg;
import java.util.Collections;
import java.util.Iterator;
import org.eclipse.cdt.codan.core.model.cfg.IBasicBlock;
import org.eclipse.cdt.codan.core.model.cfg.IStartNode;
@ -15,9 +12,8 @@ public class StartNode extends AbstractSingleOutgoingNode implements IStartNode
super();
}
@SuppressWarnings("unchecked")
public Iterator<IBasicBlock> getIncomingIterator() {
return Collections.EMPTY_LIST.iterator();
public IBasicBlock[] getIncomingNodes() {
return EMPTY_LIST;
}
public int getIncomingSize() {

View file

@ -2,7 +2,6 @@ package org.eclipse.cdt.codan.ui.cfgview.views;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import org.eclipse.cdt.codan.core.cxx.internal.model.cfg.ControlFlowGraphBuilder;
import org.eclipse.cdt.codan.core.cxx.internal.model.cfg.CxxControlFlowGraph;
@ -122,13 +121,11 @@ public class ControlFlowGraphView extends ViewPart {
return blocks.toArray();
} else if (parent instanceof IDecisionNode) {
ArrayList blocks = new ArrayList();
Iterator<IBasicBlock> iter = ((IDecisionNode) parent)
.getOutgoingIterator();
if (iter.hasNext()) {
for (; iter.hasNext();) {
IBasicBlock arc = iter.next();
blocks.add(arc);
}
IBasicBlock[] outgoingNodes = ((IDecisionNode) parent)
.getOutgoingNodes();
for (int i = 0; i < outgoingNodes.length; i++) {
IBasicBlock arc= outgoingNodes[i];
blocks.add(arc);
}
blocks.add(((IDecisionNode) parent).getMergeNode());
return blocks.toArray();