1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-22 22:22:11 +02:00

- added node factory and cfg for for statement

This commit is contained in:
Alena Laskavaia 2010-04-01 02:14:48 +00:00
parent 21d46e71ee
commit 0908dbf0cd
17 changed files with 318 additions and 119 deletions

View file

@ -17,10 +17,14 @@ import org.eclipse.cdt.codan.internal.core.cfg.ConnectorNode;
import org.eclipse.cdt.codan.internal.core.cfg.DecisionNode;
import org.eclipse.cdt.codan.internal.core.cfg.JumpNode;
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.IExitNode;
import org.eclipse.cdt.codan.provisional.core.model.cfg.IPlainNode;
import org.eclipse.cdt.codan.provisional.core.model.cfg.IStartNode;
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.IASTForStatement;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.IASTIfStatement;
import org.eclipse.cdt.core.dom.ast.IASTNode;
@ -36,6 +40,7 @@ public class ControlFlowGraphBuilder {
Collection<IExitNode> exits;
Collection<IBasicBlock> dead;
CxxExitNode returnExit;
CxxNodeFactory factory = new CxxNodeFactory();
/**
* @param def
@ -48,7 +53,8 @@ public class ControlFlowGraphBuilder {
dead = new ArrayList<IBasicBlock>();
IBasicBlock last = createSubGraph(start, body);
if (!(last instanceof IExitNode)) {
returnExit = new CxxExitNode(last, start, null);
returnExit = (CxxExitNode) factory.createExitNode(null);
returnExit.setStartNode(start);
addOutgoing(last, returnExit);
}
return new CxxControlFlowGraph(start, exits);
@ -69,11 +75,11 @@ public class ControlFlowGraphBuilder {
}
} else if (body instanceof IASTExpressionStatement
|| body instanceof IASTDeclarationStatement) {
CxxPlainNode node = new CxxPlainNode(prev, body);
CxxPlainNode node = factory.createPlainNode(body);
addOutgoing(prev, node);
return node;
} else if (body instanceof IASTIfStatement) {
DecisionNode node = new CxxDecisionNode(prev,
DecisionNode node = factory.createDecisionNode(
((IASTIfStatement) body).getConditionExpression());
addOutgoing(prev, node);
ConnectorNode conn = new ConnectorNode();
@ -89,26 +95,57 @@ public class ControlFlowGraphBuilder {
return conn;
} else if (body instanceof IASTWhileStatement) {
// add continue connector
ConnectorNode nContinue = new ConnectorNode(prev);
IConnectorNode nContinue = factory.createConnectorNode();
addOutgoing(prev, nContinue);
// decision node
CxxDecisionNode decision = new CxxDecisionNode(nContinue,
CxxDecisionNode decision = factory.createDecisionNode(
((IASTWhileStatement) body).getCondition());
addOutgoing(nContinue, decision);
// add break connector
ConnectorNode nBreak = new ConnectorNode(decision);
IConnectorNode nBreak = factory.createConnectorNode();
addOutgoing(decision, nBreak);
decision.setConnectorNode(nBreak);
// create body and jump to continue node
IBasicBlock nBody = createSubGraph(decision,
((IASTWhileStatement) body).getBody());
JumpNode jumpContinue = new JumpNode(nBody, nContinue, true);
JumpNode jumpContinue = new JumpNode();
addOutgoing(nBody, jumpContinue);
jumpContinue.setJump(nContinue, true);
// connect with backward link
nContinue.addIncoming(jumpContinue);
addOutgoing(jumpContinue, nContinue);
return nBreak;
} else if (body instanceof IASTForStatement) {
// add initializer
IPlainNode init = factory.createPlainNode(((IASTForStatement) body).getInitializerStatement());
addOutgoing(prev, init);
prev = init;
// add continue connector
IConnectorNode nContinue2 = factory.createConnectorNode();
addOutgoing(prev, nContinue2);
// decision node
CxxDecisionNode decision = factory.createDecisionNode(
((IASTForStatement) body).getConditionExpression());
addOutgoing(nContinue2, decision);
// add break connector
IConnectorNode nBreak = factory.createConnectorNode();
addOutgoing(decision, nBreak);
decision.setConnectorNode(nBreak);
// create body and jump to continue node
IBasicBlock nBody = createSubGraph(decision,
((IASTForStatement) body).getBody());
// inc
IPlainNode inc = factory.createPlainNode(((IASTForStatement) body).getIterationExpression());
addOutgoing(nBody, inc);
JumpNode jumpContinue = new JumpNode();
addOutgoing(inc, jumpContinue);
jumpContinue.setJump(nContinue2, true);
// connect with backward link
addOutgoing(jumpContinue, nContinue2);
return nBreak;
} else if (body instanceof IASTReturnStatement) {
CxxExitNode node = new CxxExitNode(prev, start, body);
CxxExitNode node = factory.createExitNode(body);
node.setStartNode(start);
addOutgoing(prev, node);
return node;
}
@ -120,6 +157,8 @@ public class ControlFlowGraphBuilder {
* @param node
*/
private void addOutgoing(IBasicBlock prev, IBasicBlock node) {
if (!(node instanceof IStartNode))
((AbstractBasicBlock) node).addIncoming(prev);
if (prev instanceof IExitNode) {
dead.add(node);
} else if (prev instanceof AbstractBasicBlock) {

View file

@ -11,34 +11,15 @@
package org.eclipse.cdt.codan.core.cxx.internal.model.cfg;
import org.eclipse.cdt.codan.internal.core.cfg.DecisionNode;
import org.eclipse.cdt.codan.provisional.core.model.cfg.IBasicBlock;
import org.eclipse.cdt.core.dom.ast.IASTNode;
/**
* TODO: add description
*/
public class CxxDecisionNode extends DecisionNode {
/**
* @param prev
* @param expression
*/
public CxxDecisionNode(IBasicBlock prev, IASTNode expression) {
super(prev);
this.setNode(expression);
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return getNode().getRawSignature();
}
/**
* @param node the node to set
* @param node
* the node to set
*/
public void setNode(IASTNode node) {
setData(node);
@ -50,6 +31,7 @@ public class CxxDecisionNode extends DecisionNode {
public IASTNode getNode() {
return (IASTNode) getData();
}
/**
* @return
*/

View file

@ -11,36 +11,13 @@
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
@ -55,12 +32,13 @@ public class CxxExitNode extends ExitNode implements IExitNode {
public IASTNode getNode() {
return (IASTNode) getData();
}
/**
* @return
*/
public String toStringData() {
if (getNode() == null)
return "";
return "return; // fake";
return getNode().getRawSignature();
}
}

View file

@ -0,0 +1,56 @@
/*******************************************************************************
* 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.AbstractBasicBlock;
import org.eclipse.cdt.codan.internal.core.model.NodeFactory;
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.INodeFactory;
import org.eclipse.cdt.codan.provisional.core.model.cfg.IPlainNode;
import org.eclipse.cdt.core.dom.ast.IASTNode;
/**
* TODO: add description
*/
public class CxxNodeFactory extends NodeFactory implements INodeFactory {
public CxxNodeFactory() {
super();
}
public IPlainNode createPlainNode() {
return new CxxPlainNode();
}
public IDecisionNode createDecisionNode() {
return new CxxDecisionNode();
}
public IExitNode createExitNode() {
return new CxxExitNode();
}
public CxxPlainNode createPlainNode(IASTNode ast) {
IPlainNode node = createPlainNode();
((AbstractBasicBlock) node).setData(ast);
return (CxxPlainNode) node;
}
public CxxDecisionNode createDecisionNode(IASTNode ast) {
IDecisionNode node = createDecisionNode();
((AbstractBasicBlock) node).setData(ast);
return (CxxDecisionNode) node;
}
public CxxExitNode createExitNode(IASTNode ast) {
IExitNode node = createExitNode();
((AbstractBasicBlock) node).setData(ast);
return (CxxExitNode) node;
}
}

View file

@ -11,7 +11,6 @@
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;
/**
@ -21,24 +20,8 @@ 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
* @param node
* the node to set
*/
public void setNode(IASTNode node) {
setData(node);
@ -50,6 +33,7 @@ public class CxxPlainNode extends PlainNode {
public IASTNode getNode() {
return (IASTNode) getData();
}
/**
* @return
*/

View file

@ -17,6 +17,7 @@ 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.codan.provisional.core.model.cfg.IBasicBlock;
import org.eclipse.cdt.codan.provisional.core.model.cfg.IDecisionNode;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
@ -105,10 +106,17 @@ public class ControlFlowGraphTest extends CodanTestCase {
for (Iterator<IBasicBlock> iterator = node.getIncomingIterator(); iterator.hasNext();) {
IBasicBlock b = iterator.next();
if (!contains(node, b.getOutgoingIterator()))
fail("Block "+node+" inc "+b);
fail("Block "+node+" inconsitent prev/next "+b);
}
for (Iterator<IBasicBlock> iterator = node.getOutgoingIterator(); iterator.hasNext();) {
IBasicBlock b = iterator.next();
if (!contains(node, b.getIncomingIterator()))
fail("Block "+node+" inconsitent next/prev "+b);
}
if (node instanceof IDecisionNode) {
assertTrue("decision node outgping size",node.getOutgoingSize()>1);
assertNotNull(((IDecisionNode) node).getConnectionNode());
}
// TODO Auto-generated method stub
}
/**
@ -140,5 +148,21 @@ public class ControlFlowGraphTest extends CodanTestCase {
}
/*-
<code file="test2.c">
main() {
int a=10;
while (a--) {
a=a-2;
}
}
</code>
*/
public void test_while() {
load("test2.c");
buildCfg();
checkCfg();
}
}

View file

@ -1,6 +1,7 @@
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 {
@ -46,4 +47,14 @@ public abstract class AbstractBasicBlock implements IBasicBlock {
return "";
return getData().toString();
}
@Override
public String toString() {
return getClass().getSimpleName() + ": " + toStringData();
}
/**
* @param node
*/
public abstract void addIncoming(IBasicBlock node);
}

View file

@ -10,11 +10,10 @@ import org.eclipse.cdt.codan.provisional.core.model.cfg.ISingleIncoming;
*/
public abstract class AbstractSingleIncomingNode extends AbstractBasicBlock
implements ISingleIncoming {
final IBasicBlock prev;
private IBasicBlock prev;
public AbstractSingleIncomingNode(IBasicBlock prev) {
public AbstractSingleIncomingNode() {
super();
this.prev = prev;
}
public Iterator<IBasicBlock> getIncomingIterator() {
@ -28,4 +27,13 @@ public abstract class AbstractSingleIncomingNode extends AbstractBasicBlock
public IBasicBlock getIncoming() {
return prev;
}
public void setIncoming(IBasicBlock prev) {
this.prev = prev;
}
@Override
public void addIncoming(IBasicBlock node) {
setIncoming(node);
}
}

View file

@ -12,7 +12,6 @@ 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;
import org.eclipse.cdt.codan.provisional.core.model.cfg.IJumpNode;
@ -28,11 +27,7 @@ public class ConnectorNode extends AbstractSingleOutgoingNode implements
super();
}
public ConnectorNode(IBasicBlock prev) {
super();
addIncoming(prev);
}
@Override
public void addIncoming(IBasicBlock node) {
incoming.add(node);
}

View file

@ -16,7 +16,6 @@ import java.util.Collections;
import java.util.Iterator;
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.IConnectorNode;
import org.eclipse.cdt.codan.provisional.core.model.cfg.IControlFlowGraph;

View file

@ -15,6 +15,7 @@ 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;
@ -63,8 +64,8 @@ public class DecisionNode extends AbstractSingleIncomingNode implements
/**
* @param prev
*/
public DecisionNode(IBasicBlock prev) {
super(prev);
public DecisionNode() {
super();
}
public void setDecisionArcs(Collection<IDecisionArc> next) {

View file

@ -10,18 +10,11 @@ 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;
public class ExitNode extends AbstractSingleIncomingNode implements IExitNode {
private IStartNode start;
public ExitNode(IBasicBlock prev, IStartNode start) {
public ExitNode() {
super();
this.prev = prev;
this.start = start;
}
public Iterator<IBasicBlock> getIncomingIterator() {
return new OneElementIterator<IBasicBlock>(prev);
}
@SuppressWarnings("unchecked")
@ -29,26 +22,14 @@ public class ExitNode extends AbstractBasicBlock implements IExitNode {
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;
}

View file

@ -15,10 +15,8 @@ public class JumpNode extends AbstractSingleIncomingNode implements IJumpNode {
private IConnectorNode jump;
private boolean backward;
public JumpNode(IBasicBlock entry, IConnectorNode jump, boolean backward) {
super(entry);
this.jump = jump;
this.backward = backward;
public JumpNode() {
super();
}
public Iterator<IBasicBlock> getOutgoingIterator() {
@ -47,11 +45,12 @@ public class JumpNode extends AbstractSingleIncomingNode implements IJumpNode {
return backward;
}
public void setJump(IConnectorNode jump) {
public void setJump(IConnectorNode jump, boolean backward) {
if (this.jump != null)
throw new IllegalArgumentException(
"Cannot modify exiting connector"); //$NON-NLS-1$
this.jump = jump;
this.backward = backward;
}
public void setBackward(boolean backward) {
@ -60,6 +59,8 @@ public class JumpNode extends AbstractSingleIncomingNode implements IJumpNode {
@Override
public void addOutgoing(IBasicBlock node) {
if (node == jump)
return;
throw new UnsupportedOperationException();
}
}

View file

@ -1,7 +1,6 @@
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.IPlainNode;
@ -12,9 +11,8 @@ import org.eclipse.cdt.codan.provisional.core.model.cfg.IPlainNode;
public class PlainNode extends AbstractSingleIncomingNode implements IPlainNode {
IBasicBlock next;
public PlainNode(IBasicBlock prev, IBasicBlock next) {
super(prev);
this.next = next;
public PlainNode() {
super();
}
public Iterator<IBasicBlock> getOutgoingIterator() {

View file

@ -2,7 +2,6 @@ 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.IStartNode;
@ -28,4 +27,9 @@ public class StartNode extends AbstractSingleOutgoingNode implements IStartNode
public void addOutgoing(IBasicBlock node) {
setOutgoing(node);
}
@Override
public void addIncoming(IBasicBlock node) {
throw new UnsupportedOperationException();
}
}

View file

@ -0,0 +1,110 @@
/*******************************************************************************
* 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.model;
import org.eclipse.cdt.codan.internal.core.cfg.ConnectorNode;
import org.eclipse.cdt.codan.internal.core.cfg.DecisionNode;
import org.eclipse.cdt.codan.internal.core.cfg.ExitNode;
import org.eclipse.cdt.codan.internal.core.cfg.JumpNode;
import org.eclipse.cdt.codan.internal.core.cfg.PlainNode;
import org.eclipse.cdt.codan.internal.core.cfg.StartNode;
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.IJumpNode;
import org.eclipse.cdt.codan.provisional.core.model.cfg.INodeFactory;
import org.eclipse.cdt.codan.provisional.core.model.cfg.IPlainNode;
import org.eclipse.cdt.codan.provisional.core.model.cfg.IStartNode;
/**
* TODO: add description
*/
public class NodeFactory implements INodeFactory {
IControlFlowGraph graph;
/*
* (non-Javadoc)
*
* @seeorg.eclipse.cdt.codan.provisional.core.model.cfg.INodeFactory#
* getControlFlowGraph()
*/
public IControlFlowGraph getControlFlowGraph() {
return graph;
}
public NodeFactory() {
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.cdt.codan.provisional.core.model.cfg.INodeFactory#createPlainNode
* ()
*/
public IPlainNode createPlainNode() {
return new PlainNode();
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.cdt.codan.provisional.core.model.cfg.INodeFactory#createJumpNode
* ()
*/
public IJumpNode createJumpNode() {
return new JumpNode();
}
/*
* (non-Javadoc)
*
* @seeorg.eclipse.cdt.codan.provisional.core.model.cfg.INodeFactory#
* createDecisionNode()
*/
public IDecisionNode createDecisionNode() {
return new DecisionNode();
}
/*
* (non-Javadoc)
*
* @seeorg.eclipse.cdt.codan.provisional.core.model.cfg.INodeFactory#
* createConnectiorNode()
*/
public IConnectorNode createConnectorNode() {
return new ConnectorNode();
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.cdt.codan.provisional.core.model.cfg.INodeFactory#createStartNode
* ()
*/
public IStartNode createStartNode() {
return new StartNode();
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.cdt.codan.provisional.core.model.cfg.INodeFactory#createExitNode
* ()
*/
public IExitNode createExitNode() {
return new ExitNode();
}
}

View file

@ -0,0 +1,28 @@
/*******************************************************************************
* 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;
/**
* Control Flow Graph Node factory
*/
public interface INodeFactory {
IPlainNode createPlainNode();
IJumpNode createJumpNode();
IDecisionNode createDecisionNode();
IConnectorNode createConnectorNode();
IStartNode createStartNode();
IExitNode createExitNode();
}