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

- re-wrote to use labeled node instead of decisionArc

This commit is contained in:
Alena Laskavaia 2010-04-14 02:55:44 +00:00
parent d346fcd041
commit ee3a2444d1
16 changed files with 222 additions and 249 deletions

View file

@ -20,6 +20,8 @@ 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.IBasicBlock;
import org.eclipse.cdt.codan.provisional.core.model.cfg.IConnectorNode; 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.IExitNode;
import org.eclipse.cdt.codan.provisional.core.model.cfg.IJumpNode;
import org.eclipse.cdt.codan.provisional.core.model.cfg.ILabeledNode;
import org.eclipse.cdt.codan.provisional.core.model.cfg.IPlainNode; import org.eclipse.cdt.codan.provisional.core.model.cfg.IPlainNode;
import org.eclipse.cdt.codan.provisional.core.model.cfg.IStartNode; import org.eclipse.cdt.codan.provisional.core.model.cfg.IStartNode;
import org.eclipse.cdt.core.dom.ast.IASTBreakStatement; import org.eclipse.cdt.core.dom.ast.IASTBreakStatement;
@ -27,6 +29,7 @@ import org.eclipse.cdt.core.dom.ast.IASTCaseStatement;
import org.eclipse.cdt.core.dom.ast.IASTCompoundStatement; import org.eclipse.cdt.core.dom.ast.IASTCompoundStatement;
import org.eclipse.cdt.core.dom.ast.IASTDeclarationStatement; import org.eclipse.cdt.core.dom.ast.IASTDeclarationStatement;
import org.eclipse.cdt.core.dom.ast.IASTDefaultStatement; import org.eclipse.cdt.core.dom.ast.IASTDefaultStatement;
import org.eclipse.cdt.core.dom.ast.IASTDoStatement;
import org.eclipse.cdt.core.dom.ast.IASTExpressionStatement; import org.eclipse.cdt.core.dom.ast.IASTExpressionStatement;
import org.eclipse.cdt.core.dom.ast.IASTForStatement; import org.eclipse.cdt.core.dom.ast.IASTForStatement;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition; import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
@ -89,6 +92,8 @@ public class ControlFlowGraphBuilder {
return createWhile(prev, (IASTWhileStatement) body); return createWhile(prev, (IASTWhileStatement) body);
} else if (body instanceof IASTForStatement) { } else if (body instanceof IASTForStatement) {
return createFor(prev, (IASTForStatement) body); return createFor(prev, (IASTForStatement) body);
} else if (body instanceof IASTDoStatement) {
return createDoWhile(prev, (IASTDoStatement) body);
} else if (body instanceof IASTReturnStatement) { } else if (body instanceof IASTReturnStatement) {
CxxExitNode node = factory.createExitNode(body); CxxExitNode node = factory.createExitNode(body);
node.setStartNode(start); node.setStartNode(start);
@ -106,18 +111,20 @@ public class ControlFlowGraphBuilder {
* @return * @return
*/ */
protected IBasicBlock createIf(IBasicBlock prev, IASTIfStatement body) { protected IBasicBlock createIf(IBasicBlock prev, IASTIfStatement body) {
DecisionNode node = factory.createDecisionNode(body DecisionNode ifNode = factory.createDecisionNode(body
.getConditionExpression()); .getConditionExpression());
addOutgoing(prev, node); addOutgoing(prev, ifNode);
ConnectorNode conn = new ConnectorNode(); IConnectorNode mergeNode = factory.createConnectorNode();
node.setConnectorNode(conn); ifNode.setMergeNode(mergeNode);
IBasicBlock els = createSubGraph(node, body.getElseClause()); ILabeledNode thenNode = factory.createLabeledNode(ILabeledNode.THEN);
conn.addIncoming(els); addOutgoing(ifNode, thenNode);
addOutgoing(els, conn); IBasicBlock then = createSubGraph(thenNode, body.getThenClause());
IBasicBlock then = createSubGraph(node, body.getThenClause()); addOutgoing(then, mergeNode);
conn.addIncoming(then); ILabeledNode elseNode = factory.createLabeledNode(ILabeledNode.ELSE);
addOutgoing(then, conn); addOutgoing(ifNode, elseNode);
return conn; IBasicBlock els = createSubGraph(elseNode, body.getElseClause());
addOutgoing(els, mergeNode);
return mergeNode;
} }
/** /**
@ -130,7 +137,7 @@ public class ControlFlowGraphBuilder {
.getControllerExpression()); .getControllerExpression());
addOutgoing(prev, node); addOutgoing(prev, node);
ConnectorNode conn = new ConnectorNode(); ConnectorNode conn = new ConnectorNode();
node.setConnectorNode(conn); node.setMergeNode(conn);
createSwitchBody(node, conn, body.getBody()); createSwitchBody(node, conn, body.getBody());
return conn; return conn;
} }
@ -148,20 +155,15 @@ public class ControlFlowGraphBuilder {
IASTCompoundStatement comp = (IASTCompoundStatement) body; IASTCompoundStatement comp = (IASTCompoundStatement) body;
IASTNode[] children = comp.getChildren(); IASTNode[] children = comp.getChildren();
IBasicBlock prev = switchNode; IBasicBlock prev = switchNode;
int labelNum = 1;
for (int i = 0; i < children.length; i++) { for (int i = 0; i < children.length; i++) {
IASTNode elem = children[i]; IASTNode elem = children[i];
if (elem instanceof IASTCaseStatement) { if (elem instanceof IASTCaseStatement) {
IASTCaseStatement caseSt = (IASTCaseStatement) elem; IASTCaseStatement caseSt = (IASTCaseStatement) elem;
IPlainNode nextSt = factory ILabeledNode lbl = factory.createLabeledNode(caseSt);
.createPlainNode();
if (!(prev instanceof IExitNode) && prev != switchNode) if (!(prev instanceof IExitNode) && prev != switchNode)
addOutgoing(prev, nextSt); addOutgoing(prev, lbl);
switchNode.addOutgoing(new CxxDecisionArc(switchNode, labelNum, addOutgoing(switchNode, lbl);
nextSt, caseSt)); prev = lbl;
labelNum++;
((AbstractBasicBlock)nextSt).addIncoming(switchNode);
prev = nextSt;
continue; continue;
} }
if (elem instanceof IASTBreakStatement) { if (elem instanceof IASTBreakStatement) {
@ -173,15 +175,12 @@ public class ControlFlowGraphBuilder {
continue; continue;
} }
if (elem instanceof IASTDefaultStatement) { if (elem instanceof IASTDefaultStatement) {
IASTDefaultStatement caseSt = (IASTDefaultStatement) elem; ILabeledNode lbl = factory
IPlainNode nextSt = factory .createLabeledNode(ILabeledNode.DEFAULT);
.createPlainNode();
if (!(prev instanceof IExitNode) && prev != switchNode) if (!(prev instanceof IExitNode) && prev != switchNode)
addOutgoing(prev, nextSt); addOutgoing(prev, lbl);
switchNode.addOutgoing(new CxxDecisionArc(switchNode, 0, addOutgoing(switchNode, lbl);
nextSt, caseSt)); prev = lbl;
((AbstractBasicBlock)nextSt).addIncoming(switchNode);
prev = nextSt;
continue; continue;
} }
IBasicBlock last = createSubGraph(prev, elem); IBasicBlock last = createSubGraph(prev, elem);
@ -209,19 +208,24 @@ public class ControlFlowGraphBuilder {
addOutgoing(nContinue2, decision); addOutgoing(nContinue2, decision);
// add break connector // add break connector
IConnectorNode nBreak = factory.createConnectorNode(); IConnectorNode nBreak = factory.createConnectorNode();
addOutgoing(decision, nBreak); decision.setMergeNode(nBreak);
decision.setConnectorNode(nBreak);
// create body and jump to continue node // create body and jump to continue node
IBasicBlock nBody = createSubGraph(decision, forNode.getBody()); ILabeledNode loopStart = factory.createLabeledNode(ILabeledNode.THEN);
addOutgoing(decision, loopStart);
IBasicBlock endBody = createSubGraph(loopStart, forNode.getBody());
// inc // inc
IPlainNode inc = factory.createPlainNode(forNode IPlainNode inc = factory.createPlainNode(forNode
.getIterationExpression()); .getIterationExpression());
addOutgoing(nBody, inc); addOutgoing(endBody, inc);
JumpNode jumpContinue = new JumpNode(); JumpNode jumpContinue = new JumpNode();
addOutgoing(inc, jumpContinue); addOutgoing(inc, jumpContinue);
jumpContinue.setJump(nContinue2, true); jumpContinue.setJump(nContinue2, true);
// connect with backward link // connect with backward link
addOutgoing(jumpContinue, nContinue2); addOutgoing(jumpContinue, nContinue2);
// add "else" branch
ILabeledNode loopEnd = factory.createLabeledNode(ILabeledNode.ELSE);
addOutgoing(decision, loopEnd);
addOutgoing(loopEnd, nBreak);
return nBreak; return nBreak;
} }
@ -240,15 +244,50 @@ public class ControlFlowGraphBuilder {
addOutgoing(nContinue, decision); addOutgoing(nContinue, decision);
// add break connector // add break connector
IConnectorNode nBreak = factory.createConnectorNode(); IConnectorNode nBreak = factory.createConnectorNode();
addOutgoing(decision, nBreak); decision.setMergeNode(nBreak);
decision.setConnectorNode(nBreak);
// create body and jump to continue node // create body and jump to continue node
IBasicBlock nBody = createSubGraph(decision, body.getBody()); ILabeledNode loopStart = factory.createLabeledNode(ILabeledNode.THEN);
addOutgoing(decision, loopStart);
IBasicBlock endBody = createSubGraph(loopStart, body.getBody());
JumpNode jumpContinue = new JumpNode(); JumpNode jumpContinue = new JumpNode();
addOutgoing(nBody, jumpContinue); addOutgoing(endBody, jumpContinue);
jumpContinue.setJump(nContinue, true); jumpContinue.setJump(nContinue, true);
// connect with backward link // connect with backward link
addOutgoing(jumpContinue, nContinue); addOutgoing(jumpContinue, nContinue);
// connect with else branch
ILabeledNode loopEnd = factory.createLabeledNode(ILabeledNode.ELSE);
addOutgoing(decision, loopEnd);
addOutgoing(loopEnd, nBreak);
return nBreak;
}
protected IBasicBlock createDoWhile(IBasicBlock prev, IASTDoStatement body) {
// create body and jump to continue node
IConnectorNode loopStart = factory.createConnectorNode();
addOutgoing(prev, loopStart);
IBasicBlock endBody = createSubGraph(loopStart, body.getBody());
// add continue connector
IConnectorNode nContinue = factory.createLabeledNode("continue");
addOutgoing(endBody, nContinue);
// decision node
CxxDecisionNode decision = factory.createDecisionNode(body
.getCondition());
addOutgoing(nContinue, decision);
// then branch
ILabeledNode thenNode = factory.createLabeledNode(ILabeledNode.THEN);
addOutgoing(decision, thenNode);
IJumpNode jumpToStart = factory.createJumpNode();
addOutgoing(thenNode, jumpToStart);
((JumpNode)jumpToStart).setBackward(true);
// connect with backward link
addOutgoing(jumpToStart, loopStart);
// connect with else branch
ILabeledNode loopEnd = factory.createLabeledNode(ILabeledNode.ELSE);
addOutgoing(decision, loopEnd);
// add break connector
IConnectorNode nBreak = factory.createConnectorNode();
decision.setMergeNode(nBreak);
addOutgoing(loopEnd, nBreak);
return nBreak; return nBreak;
} }

View file

@ -10,26 +10,19 @@
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.codan.core.cxx.internal.model.cfg; package org.eclipse.cdt.codan.core.cxx.internal.model.cfg;
import org.eclipse.cdt.codan.internal.core.cfg.DecisionArc; import org.eclipse.cdt.codan.internal.core.cfg.LabeledNode;
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; import org.eclipse.cdt.core.dom.ast.IASTNode;
/** /**
* TODO: add description * TODO: add description
*/ */
public class CxxDecisionArc extends DecisionArc { public class CxxLabeledNode extends LabeledNode {
private IASTNode label; private IASTNode labelData;
/**
* @param decisionNode CxxLabeledNode(IASTNode label) {
* @param i super(label.getRawSignature());
* @param node this.labelData = label;
*/
public CxxDecisionArc(DecisionNode decisionNode, int i, IBasicBlock node,
IASTNode label) {
super(decisionNode, i, node);
this.label = label;
} }
/* /*
@ -39,6 +32,6 @@ public class CxxDecisionArc extends DecisionArc {
*/ */
@Override @Override
public String toString() { public String toString() {
return label.getRawSignature(); return labelData.getRawSignature()+":";
} }
} }

View file

@ -13,6 +13,7 @@ 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.cfg.AbstractBasicBlock;
import org.eclipse.cdt.codan.provisional.core.model.cfg.IDecisionNode; 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.IExitNode;
import org.eclipse.cdt.codan.provisional.core.model.cfg.ILabeledNode;
import org.eclipse.cdt.codan.provisional.core.model.cfg.INodeFactory; 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.IPlainNode;
import org.eclipse.cdt.codan.provisional.core.model.cfg.NodeFactory; import org.eclipse.cdt.codan.provisional.core.model.cfg.NodeFactory;
@ -37,6 +38,7 @@ public class CxxNodeFactory extends NodeFactory implements INodeFactory {
public IExitNode createExitNode() { public IExitNode createExitNode() {
return new CxxExitNode(); return new CxxExitNode();
} }
public CxxPlainNode createPlainNode(IASTNode ast) { public CxxPlainNode createPlainNode(IASTNode ast) {
IPlainNode node = createPlainNode(); IPlainNode node = createPlainNode();
((AbstractBasicBlock) node).setData(ast); ((AbstractBasicBlock) node).setData(ast);
@ -48,9 +50,20 @@ public class CxxNodeFactory extends NodeFactory implements INodeFactory {
((AbstractBasicBlock) node).setData(ast); ((AbstractBasicBlock) node).setData(ast);
return (CxxDecisionNode) node; return (CxxDecisionNode) node;
} }
public CxxExitNode createExitNode(IASTNode ast) { public CxxExitNode createExitNode(IASTNode ast) {
IExitNode node = createExitNode(); IExitNode node = createExitNode();
((AbstractBasicBlock) node).setData(ast); ((AbstractBasicBlock) node).setData(ast);
return (CxxExitNode) node; return (CxxExitNode) node;
} }
/**
* @param caseSt
* @return
*/
public ILabeledNode createLabeledNode(IASTNode caseSt) {
ILabeledNode node = createLabeledNode(caseSt.getRawSignature());
((AbstractBasicBlock) node).setData(caseSt);
return node;
}
} }

View file

@ -115,7 +115,7 @@ public class ControlFlowGraphTest extends CodanTestCase {
} }
if (node instanceof IDecisionNode) { if (node instanceof IDecisionNode) {
assertTrue("decision node outgping size",node.getOutgoingSize()>1); assertTrue("decision node outgping size",node.getOutgoingSize()>1);
assertNotNull(((IDecisionNode) node).getConnectionNode()); assertNotNull(((IDecisionNode) node).getMergeNode());
} }
} }

View file

@ -16,12 +16,13 @@ import java.util.Collections;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import org.eclipse.cdt.codan.provisional.core.model.cfg.IBasicBlock; 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.IConnectorNode;
import org.eclipse.cdt.codan.provisional.core.model.cfg.IControlFlowGraph; 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.IDecisionNode;
import org.eclipse.cdt.codan.provisional.core.model.cfg.IExitNode; import org.eclipse.cdt.codan.provisional.core.model.cfg.IExitNode;
import org.eclipse.cdt.codan.provisional.core.model.cfg.ILabeledNode;
import org.eclipse.cdt.codan.provisional.core.model.cfg.ISingleOutgoing; import org.eclipse.cdt.codan.provisional.core.model.cfg.ISingleOutgoing;
import org.eclipse.cdt.codan.provisional.core.model.cfg.IStartNode; import org.eclipse.cdt.codan.provisional.core.model.cfg.IStartNode;
@ -71,22 +72,21 @@ public class ControlFlowGraph implements IControlFlowGraph {
public void print(IBasicBlock node) { public void print(IBasicBlock node) {
System.out.println(node.getClass().getSimpleName() + ": " System.out.println(node.getClass().getSimpleName() + ": "
+ ((AbstractBasicBlock) node).toStringData()); + ((AbstractBasicBlock) node).toStringData());
if (node instanceof IConnectorNode)
if (((IConnectorNode) node).hasBackwardIncoming() == false)
return;
if (node instanceof IDecisionNode) { if (node instanceof IDecisionNode) {
// todo // todo
Iterator<IDecisionArc> decisionArcs = ((IDecisionNode) node) Iterator<IBasicBlock> branches = ((IDecisionNode) node)
.getDecisionArcs(); .getOutgoingIterator();
for (; decisionArcs.hasNext();) { for (; branches.hasNext();) {
IDecisionArc arc = decisionArcs.next(); IBasicBlock brNode = branches.next();
System.out.println("{" + arc.getIndex() + ":"); System.out.println("{");
print(arc.getOutgoing()); print(brNode);
System.out.println("}"); System.out.println("}");
} }
print(((IDecisionNode) node).getConnectionNode()); print(((IDecisionNode) node).getMergeNode());
} else if (node instanceof ISingleOutgoing) { } else if (node instanceof ISingleOutgoing) {
print(((ISingleOutgoing) node).getOutgoing()); IBasicBlock next = ((ISingleOutgoing) node).getOutgoing();
if (!(next instanceof IConnectorNode && !(next instanceof ILabeledNode)))
print(next);
} }
} }

View file

@ -1,49 +0,0 @@
/*******************************************************************************
* 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 org.eclipse.cdt.codan.provisional.core.model.cfg.IBasicBlock;
import org.eclipse.cdt.codan.provisional.core.model.cfg.IDecisionArc;
import org.eclipse.cdt.codan.provisional.core.model.cfg.IDecisionNode;
public class DecisionArc implements IDecisionArc {
private final DecisionNode decisionNode;
protected int index;
protected IBasicBlock node;
public DecisionArc(DecisionNode decisionNode, int i, IBasicBlock node) {
this.decisionNode = decisionNode;
this.index = i;
this.node = node;
}
public int getIndex() {
return index;
}
public IBasicBlock getOutgoing() {
return node;
}
public IDecisionNode getDecisionNode() {
return this.decisionNode;
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return index + "";
}
}

View file

@ -11,14 +11,11 @@
package org.eclipse.cdt.codan.internal.core.cfg; package org.eclipse.cdt.codan.internal.core.cfg;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import org.eclipse.cdt.codan.provisional.core.model.cfg.IBasicBlock; 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.IConnectorNode;
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.IDecisionNode;
/** /**
@ -26,7 +23,7 @@ import org.eclipse.cdt.codan.provisional.core.model.cfg.IDecisionNode;
*/ */
public class DecisionNode extends AbstractSingleIncomingNode implements public class DecisionNode extends AbstractSingleIncomingNode implements
IDecisionNode { IDecisionNode {
private List<IDecisionArc> next = new ArrayList<IDecisionArc>(2); private List<IBasicBlock> next = new ArrayList<IBasicBlock>(2);
private IConnectorNode conn; private IConnectorNode conn;
/** /**
@ -36,39 +33,10 @@ public class DecisionNode extends AbstractSingleIncomingNode implements
super(); super();
} }
public void setDecisionArcs(Collection<IDecisionArc> next) {
this.next = Collections.unmodifiableList(new ArrayList<IDecisionArc>(
next));
}
@Override @Override
public void addOutgoing(IBasicBlock node) { public void addOutgoing(IBasicBlock node) {
DecisionArc arc = new DecisionArc(this, getDecisionArcSize(), node); IConnectorNode cnode = (IConnectorNode) node; // cast to throw CCE
next.add(arc); next.add(cnode);
}
public void addOutgoing(IDecisionArc arc) {
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();
} }
/* /*
@ -78,25 +46,7 @@ public class DecisionNode extends AbstractSingleIncomingNode implements
* getOutgoingIterator() * getOutgoingIterator()
*/ */
public Iterator<IBasicBlock> getOutgoingIterator() { public Iterator<IBasicBlock> getOutgoingIterator() {
return new Iterator<IBasicBlock>() { return next.iterator();
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();
}
};
} }
/* /*
@ -116,11 +66,11 @@ public class DecisionNode extends AbstractSingleIncomingNode implements
* @seeorg.eclipse.cdt.codan.provisional.core.model.cfg.IDecisionNode# * @seeorg.eclipse.cdt.codan.provisional.core.model.cfg.IDecisionNode#
* getConnectionNode() * getConnectionNode()
*/ */
public IConnectorNode getConnectionNode() { public IConnectorNode getMergeNode() {
return conn; return conn;
} }
public void setConnectorNode(IConnectorNode conn) { public void setMergeNode(IConnectorNode conn) {
this.conn = conn; this.conn = conn;
} }
} }

View file

@ -46,7 +46,7 @@ public class JumpNode extends AbstractSingleIncomingNode implements IJumpNode {
} }
public void setJump(IConnectorNode jump, boolean backward) { public void setJump(IConnectorNode jump, boolean backward) {
if (this.jump != null) if (this.jump != null && this.jump != jump)
throw new IllegalArgumentException( throw new IllegalArgumentException(
"Cannot modify exiting connector"); //$NON-NLS-1$ "Cannot modify exiting connector"); //$NON-NLS-1$
this.jump = jump; this.jump = jump;
@ -59,8 +59,6 @@ public class JumpNode extends AbstractSingleIncomingNode implements IJumpNode {
@Override @Override
public void addOutgoing(IBasicBlock node) { public void addOutgoing(IBasicBlock node) {
if (node == jump) setJump((IConnectorNode) node, backward);
return;
throw new UnsupportedOperationException();
} }
} }

View file

@ -0,0 +1,42 @@
/*******************************************************************************
* 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 org.eclipse.cdt.codan.provisional.core.model.cfg.ILabeledNode;
/**
* TODO: add description
*/
public class LabeledNode extends ConnectorNode implements ILabeledNode {
private String label;
public LabeledNode(String label) {
super();
this.label = label;
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.cdt.codan.provisional.core.model.cfg.ILabeledNode#getLabel()
*/
public String getLabel() {
return label;
}
@Override
public String toStringData() {
if (getData() == null)
return label + ":";
return getData().toString();
}
}

View file

@ -1,31 +0,0 @@
package org.eclipse.cdt.codan.provisional.core.model.cfg;
/**
* 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,17 +1,16 @@
package org.eclipse.cdt.codan.provisional.core.model.cfg; package org.eclipse.cdt.codan.provisional.core.model.cfg;
import java.util.Iterator;
/** /**
* *
* Interface for decision node. This node represent condition node in the graph, * 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 * it has one incoming arc and many outgoing, each of outgoing node should be
* condition associated with it. * ILabeledNode
*/ */
public interface IDecisionNode extends IBasicBlock, ISingleIncoming { public interface IDecisionNode extends IBasicBlock, ISingleIncoming {
Iterator<IDecisionArc> getDecisionArcs(); /**
* Node where branches of decision node merge
int getDecisionArcSize(); *
* @return
IConnectorNode getConnectionNode(); */
IConnectorNode getMergeNode();
} }

View file

@ -0,0 +1,22 @@
/*******************************************************************************
* 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;
/**
* Node that represent empty operator with label, such as case branch or label
*/
public interface ILabeledNode extends IConnectorNode {
public static String THEN = "then"; //$NON-NLS-1$
public static String ELSE = "else"; //$NON-NLS-1$
public static String DEFAULT = "default"; //$NON-NLS-1$
String getLabel();
}

View file

@ -22,6 +22,8 @@ public interface INodeFactory {
IConnectorNode createConnectorNode(); IConnectorNode createConnectorNode();
ILabeledNode createLabeledNode(String label);
IStartNode createStartNode(); IStartNode createStartNode();
IExitNode createExitNode(); IExitNode createExitNode();

View file

@ -14,6 +14,7 @@ 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.DecisionNode;
import org.eclipse.cdt.codan.internal.core.cfg.ExitNode; 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.JumpNode;
import org.eclipse.cdt.codan.internal.core.cfg.LabeledNode;
import org.eclipse.cdt.codan.internal.core.cfg.PlainNode; import org.eclipse.cdt.codan.internal.core.cfg.PlainNode;
import org.eclipse.cdt.codan.internal.core.cfg.StartNode; import org.eclipse.cdt.codan.internal.core.cfg.StartNode;
@ -99,4 +100,8 @@ public class NodeFactory implements INodeFactory {
public IExitNode createExitNode() { public IExitNode createExitNode() {
return new ExitNode(); return new ExitNode();
} }
public ILabeledNode createLabeledNode(String label) {
return new LabeledNode(label);
}
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 320 B

View file

@ -3,16 +3,17 @@ package org.eclipse.cdt.codan.ui.cfgview.views;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Iterator; 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.ControlFlowGraphBuilder;
import org.eclipse.cdt.codan.core.cxx.internal.model.cfg.CxxControlFlowGraph; import org.eclipse.cdt.codan.core.cxx.internal.model.cfg.CxxControlFlowGraph;
import org.eclipse.cdt.codan.internal.core.cfg.AbstractBasicBlock; import org.eclipse.cdt.codan.internal.core.cfg.AbstractBasicBlock;
import org.eclipse.cdt.codan.provisional.core.model.cfg.IBasicBlock; 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.IConnectorNode;
import org.eclipse.cdt.codan.provisional.core.model.cfg.IControlFlowGraph; 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.IDecisionNode;
import org.eclipse.cdt.codan.provisional.core.model.cfg.IExitNode; 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.IJumpNode;
import org.eclipse.cdt.codan.provisional.core.model.cfg.ILabeledNode;
import org.eclipse.cdt.codan.provisional.core.model.cfg.ISingleOutgoing; import org.eclipse.cdt.codan.provisional.core.model.cfg.ISingleOutgoing;
import org.eclipse.cdt.codan.provisional.core.model.cfg.IStartNode; import org.eclipse.cdt.codan.provisional.core.model.cfg.IStartNode;
import org.eclipse.cdt.codan.ui.cfgview.ControlFlowGraphPlugin; import org.eclipse.cdt.codan.ui.cfgview.ControlFlowGraphPlugin;
@ -120,22 +121,19 @@ public class ControlFlowGraphView extends ViewPart {
return blocks.toArray(); return blocks.toArray();
} else if (parent instanceof IDecisionNode) { } else if (parent instanceof IDecisionNode) {
ArrayList blocks = new ArrayList(); ArrayList blocks = new ArrayList();
Iterator<IDecisionArc> iter = ((IDecisionNode) parent) Iterator<IBasicBlock> iter = ((IDecisionNode) parent)
.getDecisionArcs(); .getOutgoingIterator();
if (iter.hasNext()) { if (iter.hasNext()) {
IDecisionArc arc0 = iter.next();
for (; iter.hasNext();) { for (; iter.hasNext();) {
IDecisionArc arc = iter.next(); IBasicBlock arc = iter.next();
blocks.add(arc); blocks.add(arc);
} }
blocks.add(arc0);// people naturally expect false branch
// after true
} }
blocks.add(((IDecisionNode) parent).getConnectionNode()); blocks.add(((IDecisionNode) parent).getMergeNode());
return blocks.toArray(); return blocks.toArray();
} else if (parent instanceof IDecisionArc) { } else if (parent instanceof ILabeledNode) {
Collection<IBasicBlock> blocks = getFlat( Collection<IBasicBlock> blocks = getFlat(
((IDecisionArc) parent).getOutgoing(), ((ILabeledNode) parent).getOutgoing(),
new ArrayList<IBasicBlock>()); new ArrayList<IBasicBlock>());
return blocks.toArray(); return blocks.toArray();
} }
@ -156,23 +154,13 @@ public class ControlFlowGraphView extends ViewPart {
strdata = ((AbstractBasicBlock) obj).toStringData(); strdata = ((AbstractBasicBlock) obj).toStringData();
} }
if (strdata == null || strdata.length() == 0) { if (strdata == null || strdata.length() == 0) {
if (obj instanceof IConnectorNode) { if (obj instanceof ILabeledNode) {
strdata = strdata+blockHexLabel(obj);
} else if (obj instanceof IConnectorNode) {
strdata = blockHexLabel(obj); strdata = blockHexLabel(obj);
} else if (obj instanceof IJumpNode) { } else if (obj instanceof IJumpNode) {
strdata = blockHexLabel(((IJumpNode) obj).getJumpNode()); strdata = blockHexLabel(((IJumpNode) obj).getJumpNode());
} else if (obj instanceof IDecisionArc) { }
IDecisionArc arc = (IDecisionArc) obj;
int index = arc.getIndex();
if (arc.getDecisionNode().getDecisionArcSize() == 2) {
if (index == 0)
strdata = "false";
else
strdata = "true";
} else if (index == 0)
strdata = "default";
else
strdata = "" + index;
}
} }
return obj.getClass().getSimpleName() + ": " + strdata; return obj.getClass().getSimpleName() + ": " + strdata;
} }
@ -196,6 +184,8 @@ public class ControlFlowGraphView extends ViewPart {
imageKey = "start.png"; imageKey = "start.png";
else if (obj instanceof IJumpNode) else if (obj instanceof IJumpNode)
imageKey = "jump.png"; imageKey = "jump.png";
else if (obj instanceof ILabeledNode)
imageKey = "labeled.png";
else if (obj instanceof IConnectorNode) else if (obj instanceof IConnectorNode)
imageKey = "connector.png"; imageKey = "connector.png";
return ControlFlowGraphPlugin.getDefault().getImage( return ControlFlowGraphPlugin.getDefault().getImage(
@ -210,26 +200,26 @@ public class ControlFlowGraphView extends ViewPart {
} }
/** /**
* @param prev * @param list
* @param startNode * @param startNode
* @return * @return
*/ */
public Collection<IBasicBlock> getFlat(IBasicBlock node, public Collection<IBasicBlock> getFlat(IBasicBlock node,
Collection<IBasicBlock> prev) { Collection<IBasicBlock> list) {
prev.add(node); list.add(node);
if (node instanceof IConnectorNode if (node instanceof IConnectorNode
&& !((IConnectorNode) node).hasBackwardIncoming()) { && !((IConnectorNode) node).hasBackwardIncoming() &&
return prev; !(node instanceof ILabeledNode)) {
return list;
} }
if (node instanceof IJumpNode) if (node instanceof IJumpNode)
return prev; return list;
if (node instanceof ISingleOutgoing) { if (node instanceof ISingleOutgoing) {
getFlat(((ISingleOutgoing) node).getOutgoing(), prev); getFlat(((ISingleOutgoing) node).getOutgoing(), list);
} else if (node instanceof IDecisionNode) { } else if (node instanceof IDecisionNode) {
getFlat(((IDecisionNode) node).getConnectionNode().getOutgoing(), getFlat(((IDecisionNode) node).getMergeNode().getOutgoing(), list);
prev);
} }
return prev; return list;
} }
/** /**