1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-24 01:15:29 +02:00

- added control flow graph - initial commit

This commit is contained in:
Alena Laskavaia 2010-03-29 02:32:42 +00:00
parent 6b922df8c2
commit 62c9bdecc9
31 changed files with 1360 additions and 343 deletions

View file

@ -11,6 +11,7 @@ Require-Bundle: org.eclipse.core.runtime,
Bundle-ActivationPolicy: lazy
Export-Package: org.eclipse.cdt.codan.core.cxx,
org.eclipse.cdt.codan.core.cxx.internal.model;x-friends:="org.eclipse.cdt.codan.checkers.ui,org.eclipse.cdt.codan.ui,org.eclipse.cdt.codan.ui.cxx",
org.eclipse.cdt.codan.core.cxx.internal.model.cfg;x-friends:="org.eclipse.cdt.codan.core.test",
org.eclipse.cdt.codan.core.cxx.model
Bundle-RequiredExecutionEnvironment: J2SE-1.5
Bundle-Vendor: Eclipse CDT

View file

@ -0,0 +1,106 @@
/*******************************************************************************
* Copyright (c) 2009 Alena Laskavaia
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Alena Laskavaia - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.codan.core.cxx.internal.model.cfg;
import java.util.ArrayList;
import java.util.Collection;
import org.eclipse.cdt.codan.internal.core.cfg.AbstractBasicBlock;
import org.eclipse.cdt.codan.internal.core.cfg.ConnectorNode;
import org.eclipse.cdt.codan.internal.core.cfg.DecisionNode;
import org.eclipse.cdt.codan.provisional.core.model.cfg.IBasicBlock;
import org.eclipse.cdt.codan.provisional.core.model.cfg.IExitNode;
import org.eclipse.cdt.core.dom.ast.IASTCompoundStatement;
import org.eclipse.cdt.core.dom.ast.IASTDeclarationStatement;
import org.eclipse.cdt.core.dom.ast.IASTExpressionStatement;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.IASTIfStatement;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTReturnStatement;
import org.eclipse.cdt.core.dom.ast.IASTStatement;
/**
* TODO: add description
*/
public class ControlFlowGraphBuilder {
CxxStartNode start;
Collection<IExitNode> exits;
Collection<IBasicBlock> dead;
CxxExitNode returnExit;
/**
* @param def
* @return
*/
public CxxControlFlowGraph build(IASTFunctionDefinition def) {
IASTStatement body = def.getBody();
start = new CxxStartNode(null);
exits = new ArrayList<IExitNode>();
dead = new ArrayList<IBasicBlock>();
IBasicBlock last = createSubGraph(start, body);
if (!(last instanceof IExitNode)) {
returnExit = new CxxExitNode(last, start, null);
addOutgoing(last, returnExit);
}
return new CxxControlFlowGraph(start, exits);
}
/**
* @param start2
* @param body
*/
private IBasicBlock createSubGraph(IBasicBlock prev, IASTNode body) {
if (body instanceof IASTCompoundStatement) {
IASTCompoundStatement comp = (IASTCompoundStatement) body;
IASTNode[] children = comp.getChildren();
for (int i = 0; i < children.length; i++) {
IASTNode node = children[i];
IBasicBlock last = createSubGraph(prev, node);
prev = last;
}
} else if (body instanceof IASTExpressionStatement
|| body instanceof IASTDeclarationStatement) {
CxxPlainNode node = new CxxPlainNode(prev, body);
addOutgoing(prev, node);
return node;
} else if (body instanceof IASTIfStatement) {
DecisionNode node = new DecisionNode(prev);
addOutgoing(prev, node);
ConnectorNode conn = new ConnectorNode();
node.setConnectorNode(conn);
IBasicBlock els = createSubGraph(node, ((IASTIfStatement) body)
.getElseClause());
conn.addIncoming(els);
addOutgoing(els, conn);
IBasicBlock then = createSubGraph(node, ((IASTIfStatement) body)
.getThenClause());
conn.addIncoming(then);
addOutgoing(then, conn);
return conn;
} else if (body instanceof IASTReturnStatement) {
CxxExitNode node = new CxxExitNode(prev, start, body);
addOutgoing(prev, node);
return node;
}
return prev;
}
/**
* @param prev
* @param node
*/
private void addOutgoing(IBasicBlock prev, IBasicBlock node) {
if (prev instanceof IExitNode) {
dead.add(node);
} else if (prev instanceof AbstractBasicBlock) {
((AbstractBasicBlock) prev).addOutgoing(node);
}
}
}

View file

@ -0,0 +1,45 @@
/*******************************************************************************
* Copyright (c) 2009 Alena Laskavaia
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Alena Laskavaia - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.codan.core.cxx.internal.model.cfg;
import java.util.Collection;
import org.eclipse.cdt.codan.internal.core.cfg.ControlFlowGraph;
import org.eclipse.cdt.codan.provisional.core.model.cfg.IExitNode;
import org.eclipse.cdt.codan.provisional.core.model.cfg.IStartNode;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
/**
* TODO: add description
*/
public class CxxControlFlowGraph extends ControlFlowGraph {
/**
* @param start
* @param exitNodes
*/
public CxxControlFlowGraph(IStartNode start, Collection<IExitNode> exitNodes) {
super(start, exitNodes);
}
public static CxxControlFlowGraph build(IASTFunctionDefinition def) {
return new ControlFlowGraphBuilder().build(def);
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
// TODO Auto-generated method stub
return super.toString();
}
}

View file

@ -0,0 +1,66 @@
/*******************************************************************************
* Copyright (c) 2009 Alena Laskavaia
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Alena Laskavaia - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.codan.core.cxx.internal.model.cfg;
import org.eclipse.cdt.codan.internal.core.cfg.ExitNode;
import org.eclipse.cdt.codan.provisional.core.model.cfg.IBasicBlock;
import org.eclipse.cdt.codan.provisional.core.model.cfg.IExitNode;
import org.eclipse.cdt.codan.provisional.core.model.cfg.IStartNode;
import org.eclipse.cdt.core.dom.ast.IASTNode;
/**
* TODO: add description
*/
public class CxxExitNode extends ExitNode implements IExitNode {
/**
* @param prev
* @param start
*/
public CxxExitNode(IBasicBlock prev, IStartNode start, IASTNode node) {
super(prev, start);
setNode(node);
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
if (getNode()!=null)
return getNode().getRawSignature();
return "return; // fake";
}
/**
* @param node
* the node to set
*/
public void setNode(IASTNode node) {
setData(node);
}
/**
* @return the node
*/
public IASTNode getNode() {
return (IASTNode) getData();
}
/**
* @return
*/
public String toStringData() {
if (getNode() == null)
return "";
return getNode().getRawSignature();
}
}

View file

@ -0,0 +1,61 @@
/*******************************************************************************
* Copyright (c) 2009 Alena Laskavaia
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Alena Laskavaia - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.codan.core.cxx.internal.model.cfg;
import org.eclipse.cdt.codan.internal.core.cfg.PlainNode;
import org.eclipse.cdt.codan.provisional.core.model.cfg.IBasicBlock;
import org.eclipse.cdt.core.dom.ast.IASTNode;
/**
* TODO: add description
*/
public class CxxPlainNode extends PlainNode {
/**
* @param prev
* @param body
*/
public CxxPlainNode(IBasicBlock prev, IASTNode body) {
super(prev, null);
this.setNode(body);
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return getNode().getRawSignature();
}
/**
* @param node the node to set
*/
public void setNode(IASTNode node) {
setData(node);
}
/**
* @return the node
*/
public IASTNode getNode() {
return (IASTNode) getData();
}
/**
* @return
*/
public String toStringData() {
if (getNode() == null)
return "";
return getNode().getRawSignature();
}
}

View file

@ -0,0 +1,36 @@
/*******************************************************************************
* Copyright (c) 2009 Alena Laskavaia
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Alena Laskavaia - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.codan.core.cxx.internal.model.cfg;
import org.eclipse.cdt.codan.internal.core.cfg.StartNode;
import org.eclipse.cdt.codan.provisional.core.model.cfg.IBasicBlock;
/**
* TODO: add description
*/
public class CxxStartNode extends StartNode {
/**
* @param next
*/
public CxxStartNode(IBasicBlock next) {
super(next);
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "start";
}
}

View file

@ -10,7 +10,8 @@ Require-Bundle: org.eclipse.core.runtime,
org.eclipse.core.resources;bundle-version="3.5.0",
org.eclipse.cdt.core.tests,
org.junit;bundle-version="3.8.2",
org.eclipse.cdt.codan.core;bundle-version="1.0.0"
org.eclipse.cdt.codan.core;bundle-version="1.0.0",
org.eclipse.cdt.codan.core.cxx;bundle-version="1.0.0"
Bundle-ActivationPolicy: lazy
Bundle-RequiredExecutionEnvironment: J2SE-1.5
Bundle-Vendor: Eclipse CDT

View file

@ -0,0 +1,97 @@
/*******************************************************************************
* Copyright (c) 2009 Alena Laskavaia
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Alena Laskavaia - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.codan.core.cfg;
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.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.core.runtime.Path;
/**
* TODO: add description
*/
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);
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
*/
private void processAst(IASTTranslationUnit ast) {
CASTVisitor visitor = new CASTVisitor() {
{
shouldVisitDeclarations = true;
}
public int visit(IASTDeclaration decl) {
if (decl instanceof IASTFunctionDefinition) {
graph = new ControlFlowGraphBuilder().build((IASTFunctionDefinition) decl);
return PROCESS_ABORT;
}
return PROCESS_CONTINUE;
}
};
ast.accept(visitor);
}
void buildCfg() {
try {
Path path = new Path(currentFile.toString());
IResource el = cproject.getProject().findMember(currentFile.getName());
processFile((IFile) el);
} catch (Exception e) {
e.printStackTrace();
fail(e.getMessage());
}
}
/*-
<code file="test1.c">
main() {
int a;
a=1;
}
</code>
*/
public void test1() {
load("test1.c");
buildCfg();
graph.print(graph.getStartNode());
}
}

View file

@ -10,208 +10,20 @@
*******************************************************************************/
package org.eclipse.cdt.codan.core.test;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.cdt.codan.core.CodanRuntime;
import org.eclipse.cdt.codan.core.model.IProblemReporter;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.IPDOMManager;
import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.core.testplugin.CProjectHelper;
import org.eclipse.cdt.core.testplugin.util.BaseTestCase;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
/**
* @author Alena
*
*/
public class CheckerTestCase extends BaseTestCase {
ArrayList<File> tempFiles = new ArrayList<File>();
protected File tmpDir;
private ICProject cproject;
public class CheckerTestCase extends CodanTestCase {
private IMarker[] markers;
private File currentFile;
/**
* Override for c++
*
* @return is c++ tests
*/
public boolean isCpp() {
return false;
}
public void setUp() throws Exception {
super.setUp();
removeLeftOverProjects();
cproject = createProject(isCpp());
tmpDir = cproject.getProject().getLocation().makeAbsolute().toFile();
}
public File load(String file) {
CodanCoreTestActivator plugin = CodanCoreTestActivator.getDefault();
String name = getClass().getName();
String classFile = name.replaceAll("\\.", "/");
classFile += ".java";
InputStream st = null;
File f = null;
try {
if (plugin != null) {
URL resource = plugin.getBundle().getResource(
"src/" + classFile);
st = resource.openStream();
} else {
st = getClass().getResourceAsStream(classFile);
}
} catch (IOException e) {
fail("Cannot find java file: " + classFile);
}
try {
f = saveFile(st, file);
st.close();
currentFile = f;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return f;
}
static final Pattern filePattern = Pattern.compile("file=\"(.*)\"");
/**
* @param st
* @param file
* @return
* @throws IOException
*/
private File saveFile(InputStream st, String file) throws IOException {
BufferedReader r = new BufferedReader(new InputStreamReader(st));
String line;
File testFile = new File(tmpDir, file);
tempFiles.add(testFile);
PrintStream wr = new PrintStream(testFile);
try {
boolean print = false;
while ((line = r.readLine()) != null) {
if (line.contains("<code ")) {
Matcher m = filePattern.matcher(line);
if (m.find()) {
String userFile = m.group(1);
if (userFile.equals(file)) {
print = true;
}
}
} else if (line.contains("</code>")) {
print = false;
} else if (print) {
wr.println(line);
}
}
} finally {
wr.close();
}
return testFile;
}
public void tearDown() throws CoreException {
if (cproject != null) {
try {
cproject.getProject().delete(
IResource.FORCE
| IResource.ALWAYS_DELETE_PROJECT_CONTENT,
new NullProgressMonitor());
} catch (CoreException e) {
throw e;
}
}
}
/**
* @throws CoreException
*/
private void removeLeftOverProjects() throws CoreException {
final IWorkspace workspace = ResourcesPlugin.getWorkspace();
IProject[] projects = workspace.getRoot().getProjects();
for (int i = 0; i < projects.length; i++) {
IProject p = projects[i];
if (p.getName().startsWith("Codan")) {
p.delete(IResource.FORCE
| IResource.ALWAYS_DELETE_PROJECT_CONTENT,
new NullProgressMonitor());
}
}
}
protected ICProject createProject(final boolean cpp) throws CoreException {
final ICProject cprojects[] = new ICProject[1];
ModelJoiner mj = new ModelJoiner();
try {
// Create the cproject
final String projectName = "CodanProjTest_"
+ System.currentTimeMillis();
final IWorkspace workspace = ResourcesPlugin.getWorkspace();
workspace.run(new IWorkspaceRunnable() {
public void run(IProgressMonitor monitor) throws CoreException {
// Create the cproject
ICProject cproject = cpp ? CProjectHelper.createCCProject(
projectName, null, IPDOMManager.ID_NO_INDEXER)
: CProjectHelper.createCProject(projectName, null,
IPDOMManager.ID_NO_INDEXER);
cprojects[0] = cproject;
}
}, null);
mj.join();
// Index the cproject
CCorePlugin.getIndexManager().setIndexerId(cprojects[0],
IPDOMManager.ID_FAST_INDEXER);
// wait until the indexer is done
assertTrue(CCorePlugin.getIndexManager().joinIndexer(360000,
new NullProgressMonitor()));
} finally {
mj.dispose();
}
return cprojects[0];
}
protected void loadFiles() throws CoreException {
ModelJoiner mj = new ModelJoiner();
try {
final IWorkspace workspace = ResourcesPlugin.getWorkspace();
workspace.run(new IWorkspaceRunnable() {
public void run(IProgressMonitor monitor) throws CoreException {
cproject.getProject().refreshLocal(1, monitor);
}
}, null);
mj.join();
// Index the cproject
CCorePlugin.getIndexManager().setIndexerId(cproject,
IPDOMManager.ID_FAST_INDEXER);
// wait until the indexer is done
assertTrue(CCorePlugin.getIndexManager().joinIndexer(360000,
new NullProgressMonitor()));
} finally {
mj.dispose();
}
return;
}
/**
* @param i
@ -243,31 +55,6 @@ public class CheckerTestCase extends BaseTestCase {
assertTrue("Error on line " + i + " not found ", found);
}
/**
* @param pos
* @return
* @throws IOException
*/
private int pos2line(int pos) throws IOException {
FileInputStream st = new FileInputStream(currentFile);
try {
int c;
int line = 1;
int cur = 0;
while ((c = st.read()) != -1) {
if (c == '\n')
line++;
if (cur >= pos)
return line;
cur++;
}
;
} finally {
st.close();
}
return 0;
}
public void checkNoErrors() {
assertTrue("Found errors but should not", markers == null
|| markers.length == 0);

View file

@ -0,0 +1,205 @@
/*******************************************************************************
* Copyright (c) 2009 Alena Laskavaia
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Alena Laskavaia - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.codan.core.test;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.IPDOMManager;
import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.core.testplugin.CProjectHelper;
import org.eclipse.cdt.core.testplugin.util.BaseTestCase;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
/**
* TODO: add description
*/
public class CodanTestCase extends BaseTestCase {
ArrayList<File> tempFiles = new ArrayList<File>();
protected File tmpDir;
protected ICProject cproject;
protected File currentFile;
/**
*
*/
public CodanTestCase() {
super();
}
/**
* @param name
*/
public CodanTestCase(String name) {
super(name);
}
/**
* Override for c++
*
* @return is c++ tests
*/
public boolean isCpp() {
return false;
}
public void setUp() throws Exception {
super.setUp();
removeLeftOverProjects();
cproject = createProject(isCpp());
tmpDir = cproject.getProject().getLocation().makeAbsolute().toFile();
}
public File load(String file) {
Class clazz = getClass();
InputStream st = null;
try {
st = TestUtils.getJavaFileText(clazz);
} catch (IOException e) {
fail("Cannot find java file: " + clazz + ": " + e.getMessage());
}
try {
File testFile = new File(tmpDir, file);
tempFiles.add(testFile);
TestUtils.saveFile(st, testFile);
st.close();
currentFile = testFile;
try {
cproject.getProject().refreshLocal(1, null);
} catch (CoreException e) {
// hmm
}
return testFile;
} catch (IOException e) {
fail("Cannot save test: " + file + ": " + e.getMessage());
return null;
}
}
public void tearDown() throws CoreException {
if (cproject != null) {
try {
cproject.getProject().delete(
IResource.FORCE
| IResource.ALWAYS_DELETE_PROJECT_CONTENT,
new NullProgressMonitor());
} catch (CoreException e) {
throw e;
}
}
}
/**
* @throws CoreException
*/
private void removeLeftOverProjects() throws CoreException {
final IWorkspace workspace = ResourcesPlugin.getWorkspace();
IProject[] projects = workspace.getRoot().getProjects();
for (int i = 0; i < projects.length; i++) {
IProject p = projects[i];
if (p.getName().startsWith("Codan")) {
p.delete(IResource.FORCE
| IResource.ALWAYS_DELETE_PROJECT_CONTENT,
new NullProgressMonitor());
}
}
}
protected ICProject createProject(final boolean cpp) throws CoreException {
final ICProject cprojects[] = new ICProject[1];
ModelJoiner mj = new ModelJoiner();
try {
// Create the cproject
final String projectName = "CodanProjTest_"
+ System.currentTimeMillis();
final IWorkspace workspace = ResourcesPlugin.getWorkspace();
workspace.run(new IWorkspaceRunnable() {
public void run(IProgressMonitor monitor) throws CoreException {
// Create the cproject
ICProject cproject = cpp ? CProjectHelper.createCCProject(
projectName, null, IPDOMManager.ID_NO_INDEXER)
: CProjectHelper.createCProject(projectName, null,
IPDOMManager.ID_NO_INDEXER);
cprojects[0] = cproject;
}
}, null);
mj.join();
// Index the cproject
CCorePlugin.getIndexManager().setIndexerId(cprojects[0],
IPDOMManager.ID_FAST_INDEXER);
// wait until the indexer is done
assertTrue(CCorePlugin.getIndexManager().joinIndexer(360000,
new NullProgressMonitor()));
} finally {
mj.dispose();
}
return cprojects[0];
}
protected void loadFiles() throws CoreException {
ModelJoiner mj = new ModelJoiner();
try {
final IWorkspace workspace = ResourcesPlugin.getWorkspace();
workspace.run(new IWorkspaceRunnable() {
public void run(IProgressMonitor monitor) throws CoreException {
cproject.getProject().refreshLocal(1, monitor);
}
}, null);
mj.join();
// Index the cproject
CCorePlugin.getIndexManager().setIndexerId(cproject,
IPDOMManager.ID_FAST_INDEXER);
// wait until the indexer is done
assertTrue(CCorePlugin.getIndexManager().joinIndexer(360000,
new NullProgressMonitor()));
} finally {
mj.dispose();
}
return;
}
/**
* @param pos
* @return
* @throws IOException
*/
protected int pos2line(int pos) throws IOException {
FileInputStream st = new FileInputStream(currentFile);
try {
int c;
int line = 1;
int cur = 0;
while ((c = st.read()) != -1) {
if (c == '\n')
line++;
if (cur >= pos)
return line;
cur++;
}
;
} finally {
st.close();
}
return 0;
}
}

View file

@ -0,0 +1,86 @@
/*******************************************************************************
* Copyright (c) 2009 Alena Laskavaia
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Alena Laskavaia - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.codan.core.test;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.URL;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* TODO: add description
*/
public class TestUtils {
static final Pattern filePattern = Pattern.compile("file=\"(.*)\"");
/**
* @param st
* @param testFile
* @return
* @throws FileNotFoundException
* @throws IOException
*/
public static File saveFile(InputStream st, File testFile)
throws FileNotFoundException, IOException {
BufferedReader r = new BufferedReader(new InputStreamReader(st));
String line;
PrintStream wr = new PrintStream(testFile);
try {
boolean print = false;
while ((line = r.readLine()) != null) {
if (line.contains("<code ")) {
Matcher m = filePattern.matcher(line);
if (m.find()) {
String userFile = m.group(1);
if (userFile.equals(testFile.getName())) {
print = true;
}
}
} else if (line.contains("</code>")) {
print = false;
} else if (print) {
wr.println(line);
}
}
} finally {
wr.close();
}
return testFile;
}
/**
* @param clazz
* @return
* @throws IOException
*/
public static InputStream getJavaFileText(Class clazz) throws IOException {
CodanCoreTestActivator plugin = CodanCoreTestActivator.getDefault();
String classFile = clazz.getName().replaceAll("\\.", "/");
classFile += ".java";
InputStream st = null;
if (plugin != null) {
URL resource = plugin.getBundle().getResource(
"src/" + classFile);
st = resource.openStream();
} else {
st = clazz.getResourceAsStream(classFile);
}
return st;
}
}

View file

@ -16,4 +16,6 @@ Export-Package: org.eclipse.cdt.codan.core,
org.eclipse.cdt.codan.core.cxx,
org.eclipse.cdt.codan.core.test,
org.eclipse.cdt.codan.ui",
org.eclipse.cdt.codan.internal.core.model;x-friends:="org.eclipse.cdt.codan.core.cxx,org.eclipse.cdt.codan.core.test,org.eclipse.cdt.codan.ui"
org.eclipse.cdt.codan.internal.core.cfg;x-friends:="org.eclipse.cdt.codan.core.cxx",
org.eclipse.cdt.codan.internal.core.model;x-friends:="org.eclipse.cdt.codan.core.cxx,org.eclipse.cdt.codan.core.test,org.eclipse.cdt.codan.ui",
org.eclipse.cdt.codan.provisional.core.model.cfg

View file

@ -1,29 +0,0 @@
package org.eclipse.cdt.codan.internal.core.cfg;
import java.util.Iterator;
import org.eclipse.cdt.codan.provisional.core.model.cfg.IBasicBlock;
public abstract class AbstarctBasicBlock implements IBasicBlock {
static class OneElementIterator<T> implements Iterator<T> {
private T o;
public OneElementIterator(T o) {
this.o = o;
}
public boolean hasNext() {
return o != null;
}
public T next() {
T x = o;
o = null;
return x;
}
public void remove() {
throw new UnsupportedOperationException();
}
}
}

View file

@ -0,0 +1,49 @@
package org.eclipse.cdt.codan.internal.core.cfg;
import java.util.Iterator;
import org.eclipse.cdt.codan.provisional.core.model.cfg.IBasicBlock;
public abstract class AbstractBasicBlock implements IBasicBlock {
private Object data;
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
static class OneElementIterator<V> implements Iterator<V> {
private V o;
public OneElementIterator(V o) {
this.o = o;
}
public boolean hasNext() {
return o != null;
}
public V next() {
V x = o;
o = null;
return x;
}
public void remove() {
throw new UnsupportedOperationException();
}
}
public abstract void addOutgoing(IBasicBlock node);
/**
* @return
*/
public String toStringData() {
if (getData() == null)
return "";
return getData().toString();
}
}

View file

@ -0,0 +1,31 @@
package org.eclipse.cdt.codan.internal.core.cfg;
import java.util.Iterator;
import org.eclipse.cdt.codan.provisional.core.model.cfg.IBasicBlock;
import org.eclipse.cdt.codan.provisional.core.model.cfg.ISingleIncoming;
/**
* Abstrat node with one incoming arc
*
*/
public abstract class AbstractSingleIncomingNode extends AbstractBasicBlock
implements ISingleIncoming {
final IBasicBlock prev;
public AbstractSingleIncomingNode(IBasicBlock prev) {
super();
this.prev = prev;
}
public Iterator<IBasicBlock> getIncomingIterator() {
return new OneElementIterator<IBasicBlock>(prev);
}
public int getIncomingSize() {
return 1;
}
public IBasicBlock getIncoming() {
return prev;
}
}

View file

@ -0,0 +1,51 @@
package org.eclipse.cdt.codan.internal.core.cfg;
import java.util.Iterator;
import org.eclipse.cdt.codan.provisional.core.model.cfg.IBasicBlock;
import org.eclipse.cdt.codan.provisional.core.model.cfg.ISingleOutgoing;
/**
* Abstract impl of basic block with single outgoing arc
*
*/
public abstract class AbstractSingleOutgoingNode extends AbstractBasicBlock
implements ISingleOutgoing {
private IBasicBlock next;
public AbstractSingleOutgoingNode(IBasicBlock next) {
super();
this.next = next;
}
public Iterator<IBasicBlock> getOutgoingIterator() {
return new OneElementIterator<IBasicBlock>(next);
}
public int getOutgoingSize() {
return 1;
}
public IBasicBlock getOutgoing() {
return next;
}
public void setOutgoing(IBasicBlock exit) {
if (this.next != null)
throw new IllegalArgumentException(
"Cannot modify already exiting connector"); //$NON-NLS-1$
this.next = exit;
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.cdt.codan.internal.core.cfg.AbstractBasicBlock#addOutgoing
* (org.eclipse.cdt.codan.provisional.core.model.cfg.IBasicBlock)
*/
@Override
public void addOutgoing(IBasicBlock node) {
setOutgoing(node);
}
}

View file

@ -0,0 +1,57 @@
/*******************************************************************************
* Copyright (c) 2009 Alena Laskavaia
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Alena Laskavaia - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.codan.internal.core.cfg;
import java.util.ArrayList;
import java.util.Iterator;
import org.eclipse.cdt.codan.provisional.core.model.cfg.IBasicBlock;
import org.eclipse.cdt.codan.provisional.core.model.cfg.IConnectorNode;
/**
* TODO: add description
*/
public class ConnectorNode extends AbstractSingleOutgoingNode implements
IConnectorNode {
ArrayList<IBasicBlock> incoming = new ArrayList<IBasicBlock>(2);
/**
* @param next
*/
public ConnectorNode() {
super(null);
}
public void addIncoming(IBasicBlock node) {
incoming.add(node);
}
/*
* (non-Javadoc)
*
* @seeorg.eclipse.cdt.codan.provisional.core.model.cfg.IBasicBlock#
* getIncomingIterator()
*/
public Iterator<IBasicBlock> getIncomingIterator() {
return incoming.iterator();
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.cdt.codan.provisional.core.model.cfg.IBasicBlock#getIncomingSize
* ()
*/
public int getIncomingSize() {
// TODO Auto-generated method stub
return incoming.size();
}
}

View file

@ -0,0 +1,99 @@
/*******************************************************************************
* Copyright (c) 2009 Alena Laskavaia
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Alena Laskavaia - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.codan.internal.core.cfg;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import org.eclipse.cdt.codan.provisional.core.model.cfg.IBasicBlock;
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.IDecisionArc;
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.ISingleOutgoing;
import org.eclipse.cdt.codan.provisional.core.model.cfg.IStartNode;
/**
* TODO: add description
*/
public class ControlFlowGraph implements IControlFlowGraph {
private List<IExitNode> exitNodes;
private IStartNode start;
public ControlFlowGraph(IStartNode start, Collection<IExitNode> exitNodes) {
setExitNodes(exitNodes);
this.start = start;
}
public Iterator<IExitNode> getExitNodeIterator() {
return exitNodes.iterator();
}
public int getExitNodeSize() {
return exitNodes.size();
}
public void setExitNodes(Collection<IExitNode> exitNodes) {
if (this.exitNodes != null)
throw new IllegalArgumentException(
"Cannot modify already exiting connector"); //$NON-NLS-1$
this.exitNodes = Collections.unmodifiableList(new ArrayList<IExitNode>(
exitNodes));
}
/*
* (non-Javadoc)
*
* @seeorg.eclipse.cdt.codan.provisional.core.model.cfg.IControlFlowGraph#
* getStartNode()
*/
public IStartNode getStartNode() {
return start;
}
void setStartNode(IStartNode start) {
this.start = start;
}
public void print(IBasicBlock node) {
System.out.println(node.toString());
if (node instanceof IConnectorNode)
return;
if (node instanceof IDecisionNode) {
// todo
Iterator<IDecisionArc> decisionArcs = ((IDecisionNode) node)
.getDecisionArcs();
for (; decisionArcs.hasNext();) {
IDecisionArc arc = decisionArcs.next();
System.out.println("{" + arc.getIndex() + ":");
print(arc.getOutgoing());
System.out.println("}");
}
print(((IDecisionNode) node).getConnectionNode());
} else if (node instanceof ISingleOutgoing) {
print(((ISingleOutgoing) node).getOutgoing());
}
}
/*
* (non-Javadoc)
*
* @seeorg.eclipse.cdt.codan.provisional.core.model.cfg.IControlFlowGraph#
* getUnconnectedNodeIterator()
*/
public Iterator<IBasicBlock> getUnconnectedNodeIterator() {
// TODO Auto-generated method stub
return null;
}
}

View file

@ -0,0 +1,153 @@
/*******************************************************************************
* Copyright (c) 2009 Alena Laskavaia
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Alena Laskavaia - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.codan.internal.core.cfg;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import org.eclipse.cdt.codan.provisional.core.model.cfg.IBasicBlock;
import org.eclipse.cdt.codan.provisional.core.model.cfg.IConnectorNode;
import org.eclipse.cdt.codan.provisional.core.model.cfg.IDecisionArc;
import org.eclipse.cdt.codan.provisional.core.model.cfg.IDecisionNode;
/**
* @see {@link IDecisionNode}
*/
public class DecisionNode extends AbstractSingleIncomingNode implements
IDecisionNode {
private List<IDecisionArc> next = new ArrayList<IDecisionArc>(2);
private IConnectorNode conn;
class DecisionArc implements IDecisionArc {
int index;
IBasicBlock node;
DecisionArc(int i, IBasicBlock node) {
this.index = i;
this.node = node;
}
public int getIndex() {
return index;
}
public IBasicBlock getOutgoing() {
return node;
}
public IDecisionNode getDecisionNode() {
return DecisionNode.this;
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return index + "";
}
}
/**
* @param prev
*/
public DecisionNode(IBasicBlock prev) {
super(prev);
}
public void setDecisionArcs(Collection<IDecisionArc> next) {
this.next = Collections.unmodifiableList(new ArrayList<IDecisionArc>(
next));
}
@Override
public void addOutgoing(IBasicBlock node) {
DecisionArc arc = new DecisionArc(getDecisionArcSize(), node);
next.add(arc);
}
/*
* (non-Javadoc)
*
* @seeorg.eclipse.cdt.codan.provisional.core.model.cfg.IDecisionNode#
* getDecisionArcs()
*/
public Iterator<IDecisionArc> getDecisionArcs() {
return next.iterator();
}
/*
* (non-Javadoc)
*
* @seeorg.eclipse.cdt.codan.provisional.core.model.cfg.IDecisionNode#
* getDecisionArcSize()
*/
public int getDecisionArcSize() {
return next.size();
}
/*
* (non-Javadoc)
*
* @seeorg.eclipse.cdt.codan.provisional.core.model.cfg.IBasicBlock#
* getOutgoingIterator()
*/
public Iterator<IBasicBlock> getOutgoingIterator() {
return new Iterator<IBasicBlock>() {
private Iterator<IDecisionArc> it;
{
it = next.iterator();
}
public boolean hasNext() {
return it.hasNext();
}
public IBasicBlock next() {
IDecisionArc arc = it.next();
return arc.getOutgoing();
}
public void remove() {
throw new UnsupportedOperationException();
}
};
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.cdt.codan.provisional.core.model.cfg.IBasicBlock#getOutgoingSize
* ()
*/
public int getOutgoingSize() {
return next.size();
}
/*
* (non-Javadoc)
*
* @seeorg.eclipse.cdt.codan.provisional.core.model.cfg.IDecisionNode#
* getConnectionNode()
*/
public IConnectorNode getConnectionNode() {
return conn;
}
public void setConnectorNode(IConnectorNode conn) {
this.conn = conn;
}
}

View file

@ -0,0 +1,60 @@
package org.eclipse.cdt.codan.internal.core.cfg;
import java.util.Collections;
import java.util.Iterator;
import org.eclipse.cdt.codan.provisional.core.model.cfg.IBasicBlock;
import org.eclipse.cdt.codan.provisional.core.model.cfg.IExitNode;
import org.eclipse.cdt.codan.provisional.core.model.cfg.IStartNode;
/**
* Plain node has one prev one jump
*
*/
public class ExitNode extends AbstractBasicBlock implements IExitNode {
private IBasicBlock prev;
private IStartNode start;
public ExitNode(IBasicBlock prev, IStartNode start) {
super();
this.prev = prev;
this.start = start;
}
public Iterator<IBasicBlock> getIncomingIterator() {
return new OneElementIterator<IBasicBlock>(prev);
}
@SuppressWarnings("unchecked")
public Iterator<IBasicBlock> getOutgoingIterator() {
return Collections.EMPTY_LIST.iterator();
}
public int getIncomingSize() {
return 1;
}
public int getOutgoingSize() {
return 0;
}
public IBasicBlock getIncoming() {
return prev;
}
public IStartNode getStartNode() {
return start;
}
public void setIncoming(IBasicBlock prev) {
this.prev = prev;
}
public void setStartNode(IStartNode start) {
this.start = start;
}
@Override
public void addOutgoing(IBasicBlock node) {
throw new UnsupportedOperationException();
}
}

View file

@ -1,47 +1,33 @@
package org.eclipse.cdt.codan.internal.core.cfg;
import java.util.Iterator;
import org.eclipse.cdt.codan.provisional.core.model.cfg.IBasicBlock;
import org.eclipse.cdt.codan.provisional.core.model.cfg.IConnectorNode;
import org.eclipse.cdt.codan.provisional.core.model.cfg.IJumpNode;
/**
* Plain node has one prev one jump
*
* Jump node is node that connects unusual control pass, such as goto, break and
* continue
*
*/
public class JumpNode extends AbstarctBasicBlock implements IJumpNode {
final private IBasicBlock entry;
private IBasicBlock jump;
public class JumpNode extends AbstractSingleIncomingNode implements IJumpNode {
private IConnectorNode jump;
private boolean backward;
public JumpNode(IBasicBlock entry, IBasicBlock jump, boolean backward) {
super();
this.entry = entry;
public JumpNode(IBasicBlock entry, IConnectorNode jump, boolean backward) {
super(entry);
this.jump = jump;
this.backward = backward;
}
public Iterator<IBasicBlock> getIncomingIterator() {
return new OneElementIterator<IBasicBlock>(entry);
}
public Iterator<IBasicBlock> getOutgoingIterator() {
return new OneElementIterator<IBasicBlock>(jump);
}
public int getIncomingSize() {
return 1;
}
public int getOutgoingSize() {
return 1;
}
public IBasicBlock getIncoming() {
return entry;
}
public IBasicBlock getOutgoing() {
return jump;
}
@ -50,9 +36,10 @@ public class JumpNode extends AbstarctBasicBlock implements IJumpNode {
return backward;
}
public void setJump(IBasicBlock jump) {
if (!(jump instanceof IConnectorNode))
throw new IllegalArgumentException("Jump target must be a connection node"); //$NON-NLS-1$
public void setJump(IConnectorNode jump) {
if (this.jump != null)
throw new IllegalArgumentException(
"Cannot modify exiting connector"); //$NON-NLS-1$
this.jump = jump;
}
@ -60,4 +47,8 @@ public class JumpNode extends AbstarctBasicBlock implements IJumpNode {
this.backward = backward;
}
@Override
public void addOutgoing(IBasicBlock node) {
throw new UnsupportedOperationException();
}
}

View file

@ -6,45 +6,45 @@ import org.eclipse.cdt.codan.provisional.core.model.cfg.IBasicBlock;
import org.eclipse.cdt.codan.provisional.core.model.cfg.IPlainNode;
/**
* Plain node has one prev one jump
*
* Plain node has one incoming arc and one outgoing arc
*
*/
public class PlainNode extends AbstarctBasicBlock implements IPlainNode {
final IBasicBlock prev;
public class PlainNode extends AbstractSingleIncomingNode implements IPlainNode {
IBasicBlock next;
public PlainNode(IBasicBlock entry, IBasicBlock exit) {
super();
this.prev = entry;
this.next = exit;
}
public Iterator<IBasicBlock> getIncomingIterator() {
return new OneElementIterator<IBasicBlock>(prev);
public PlainNode(IBasicBlock prev, IBasicBlock next) {
super(prev);
this.next = next;
}
public Iterator<IBasicBlock> getOutgoingIterator() {
return new OneElementIterator<IBasicBlock>(next);
}
public int getIncomingSize() {
return 1;
}
public int getOutgoingSize() {
return 1;
}
public IBasicBlock getIncoming() {
return prev;
}
public IBasicBlock getOutgoing() {
return next;
}
public void setOutgoing(IBasicBlock exit) {
if (this.next != null) throw new IllegalArgumentException("Cannot modify already exiting connector"); //$NON-NLS-1$
if (this.next != null)
throw new IllegalArgumentException(
"Cannot modify already exiting connector"); //$NON-NLS-1$
this.next = exit;
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.cdt.codan.internal.core.cfg.AbstractBasicBlock#addOutgoing
* (org.eclipse.cdt.codan.provisional.core.model.cfg.IBasicBlock)
*/
@Override
public void addOutgoing(IBasicBlock node) {
setOutgoing(node);
}
}

View file

@ -1,27 +1,17 @@
package org.eclipse.cdt.codan.internal.core.cfg;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import org.eclipse.cdt.codan.provisional.core.model.cfg.IBasicBlock;
import org.eclipse.cdt.codan.provisional.core.model.cfg.IStartNode;
/**
* Start node has no prev, one jump and it is connect to function exits
*
* Start node has no incoming, one outgoing and it is connect to function exits
*
*/
public class StartNode extends AbstarctBasicBlock implements IStartNode {
private IBasicBlock next;
private List<IBasicBlock> exitNodes;
public StartNode(IBasicBlock next, Collection<IBasicBlock> exitNodes) {
super();
this.next = next;
if (exitNodes != null) this.exitNodes = Collections.unmodifiableList(new ArrayList<IBasicBlock>(exitNodes));
else this.exitNodes = null; // incomplete node
public class StartNode extends AbstractSingleOutgoingNode implements IStartNode {
public StartNode(IBasicBlock next) {
super(next);
}
@SuppressWarnings("unchecked")
@ -29,37 +19,12 @@ public class StartNode extends AbstarctBasicBlock implements IStartNode {
return Collections.EMPTY_LIST.iterator();
}
public Iterator<IBasicBlock> getOutgoingIterator() {
return new OneElementIterator<IBasicBlock>(next);
}
public int getIncomingSize() {
return 0;
}
public int getOutgoingSize() {
return 1;
}
public IBasicBlock getOutgoing() {
return next;
}
public Iterator<IBasicBlock> getExitNodeIterator() {
return exitNodes.iterator();
}
public int getExitNodeSize() {
return exitNodes.size();
}
public void setOutgoing(IBasicBlock next) {
if (this.next != null) throw new IllegalArgumentException("Cannot modify already exiting connector"); //$NON-NLS-1$
this.next = next;
}
public void setExitNodes(Collection<IBasicBlock> exitNodes) {
if (this.exitNodes != null) throw new IllegalArgumentException("Cannot modify already exiting connector"); //$NON-NLS-1$
this.exitNodes = Collections.unmodifiableList(new ArrayList<IBasicBlock>(exitNodes));
@Override
public void addOutgoing(IBasicBlock node) {
setOutgoing(node);
}
}

View file

@ -2,6 +2,15 @@ package org.eclipse.cdt.codan.provisional.core.model.cfg;
import java.util.Iterator;
/**
*
* Control flow graph basic block node - superinterface of all nodes. Each node
* has iterator and size over incoming and outgoing arc
* <p/>
* The following are speciazed versions of the nodes:
* <li>{@link IStartNode} - start node of the graph
* <li>{@link I}
*/
public interface IBasicBlock {
Iterator<IBasicBlock> getIncomingIterator();
@ -10,5 +19,4 @@ public interface IBasicBlock {
int getIncomingSize();
int getOutgoingSize();
}

View file

@ -1,5 +1,5 @@
package org.eclipse.cdt.codan.provisional.core.model.cfg;
public interface IConnectorNode extends IBasicBlock {
public interface IConnectorNode extends IBasicBlock, ISingleOutgoing {
}

View file

@ -0,0 +1,30 @@
/*******************************************************************************
* Copyright (c) 2009 Alena Laskavaia
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Alena Laskavaia - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.codan.provisional.core.model.cfg;
import java.util.Iterator;
/**
* TODO: add description
*/
public interface IControlFlowGraph {
IStartNode getStartNode();
/**
*
* @return
*/
Iterator<IExitNode> getExitNodeIterator();
int getExitNodeSize();
Iterator<IBasicBlock> getUnconnectedNodeIterator();
}

View file

@ -1,5 +1,31 @@
package org.eclipse.cdt.codan.provisional.core.model.cfg;
public interface IDecisionArc {
/**
* Arc that has a condition upon it, for example if branches have true/false
* condition, and switch branches have case condition
*/
public interface IDecisionArc extends ISingleOutgoing {
/**
* Index represent branch index in decision node, as well semantics: <br>
* 0 - always a false (else) branch of if, and default branch for switch,
* even if no code exists <br>
* 1 - is true (then) branch for if
*
* @return
*/
int getIndex();
/**
* Basic block that is at the end of the arc
*
* @return
*/
IBasicBlock getOutgoing();
/**
* Return parent node (decision node) or the decision arc
*
* @return
*/
IDecisionNode getDecisionNode();
}

View file

@ -1,5 +1,17 @@
package org.eclipse.cdt.codan.provisional.core.model.cfg;
public interface IDecisionNode extends IBasicBlock {
import java.util.Iterator;
/**
*
* Interface for decision node. This node represent condition node in the graph,
* it has one incoming arc and many outgoing, each of them has a value of
* condition associated with it.
*/
public interface IDecisionNode extends IBasicBlock, ISingleIncoming {
Iterator<IDecisionArc> getDecisionArcs();
int getDecisionArcSize();
IConnectorNode getConnectionNode();
}

View file

@ -0,0 +1,20 @@
/*******************************************************************************
* Copyright (c) 2009 Alena Laskavaia
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Alena Laskavaia - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.codan.provisional.core.model.cfg;
/**
* Exit node of the graph. Usually return from the function, can also be throw
* or abort, such at exit(0) call.
*
*/
public interface IExitNode extends IBasicBlock, ISingleIncoming {
IStartNode getStartNode();
}

View file

@ -1,5 +1,5 @@
package org.eclipse.cdt.codan.provisional.core.model.cfg;
public interface IPlainNode extends IBasicBlock, ISingleOutgoing, ISingleIncoming {
public interface IPlainNode extends IBasicBlock, ISingleOutgoing,
ISingleIncoming {
}

View file

@ -1,9 +1,10 @@
package org.eclipse.cdt.codan.provisional.core.model.cfg;
import java.util.Iterator;
/**
* Start node of the control flow graph. Each graph has only one start node. It
* has no incoming arcs and one outgoing arc. It also contains iterator for
* function exit nodes.
*/
public interface IStartNode extends IBasicBlock, ISingleOutgoing {
Iterator<IBasicBlock> getExitNodeIterator();
int getExitNodeSize();
}