diff --git a/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/internal/model/cfg/ControlFlowGraphBuilder.java b/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/internal/model/cfg/ControlFlowGraphBuilder.java index b9c7608133e..1c2318c87d5 100644 --- a/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/internal/model/cfg/ControlFlowGraphBuilder.java +++ b/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/internal/model/cfg/ControlFlowGraphBuilder.java @@ -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.IConnectorNode; 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.IStartNode; 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.IASTDeclarationStatement; 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.IASTForStatement; import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition; @@ -89,6 +92,8 @@ public class ControlFlowGraphBuilder { return createWhile(prev, (IASTWhileStatement) body); } else if (body instanceof IASTForStatement) { return createFor(prev, (IASTForStatement) body); + } else if (body instanceof IASTDoStatement) { + return createDoWhile(prev, (IASTDoStatement) body); } else if (body instanceof IASTReturnStatement) { CxxExitNode node = factory.createExitNode(body); node.setStartNode(start); @@ -106,18 +111,20 @@ public class ControlFlowGraphBuilder { * @return */ protected IBasicBlock createIf(IBasicBlock prev, IASTIfStatement body) { - DecisionNode node = factory.createDecisionNode(body + DecisionNode ifNode = factory.createDecisionNode(body .getConditionExpression()); - addOutgoing(prev, node); - ConnectorNode conn = new ConnectorNode(); - node.setConnectorNode(conn); - IBasicBlock els = createSubGraph(node, body.getElseClause()); - conn.addIncoming(els); - addOutgoing(els, conn); - IBasicBlock then = createSubGraph(node, body.getThenClause()); - conn.addIncoming(then); - addOutgoing(then, conn); - return conn; + addOutgoing(prev, ifNode); + IConnectorNode mergeNode = factory.createConnectorNode(); + ifNode.setMergeNode(mergeNode); + ILabeledNode thenNode = factory.createLabeledNode(ILabeledNode.THEN); + addOutgoing(ifNode, thenNode); + IBasicBlock then = createSubGraph(thenNode, body.getThenClause()); + addOutgoing(then, mergeNode); + ILabeledNode elseNode = factory.createLabeledNode(ILabeledNode.ELSE); + addOutgoing(ifNode, elseNode); + IBasicBlock els = createSubGraph(elseNode, body.getElseClause()); + addOutgoing(els, mergeNode); + return mergeNode; } /** @@ -130,7 +137,7 @@ public class ControlFlowGraphBuilder { .getControllerExpression()); addOutgoing(prev, node); ConnectorNode conn = new ConnectorNode(); - node.setConnectorNode(conn); + node.setMergeNode(conn); createSwitchBody(node, conn, body.getBody()); return conn; } @@ -148,20 +155,15 @@ public class ControlFlowGraphBuilder { IASTCompoundStatement comp = (IASTCompoundStatement) body; IASTNode[] children = comp.getChildren(); IBasicBlock prev = switchNode; - int labelNum = 1; for (int i = 0; i < children.length; i++) { IASTNode elem = children[i]; if (elem instanceof IASTCaseStatement) { IASTCaseStatement caseSt = (IASTCaseStatement) elem; - IPlainNode nextSt = factory - .createPlainNode(); + ILabeledNode lbl = factory.createLabeledNode(caseSt); if (!(prev instanceof IExitNode) && prev != switchNode) - addOutgoing(prev, nextSt); - switchNode.addOutgoing(new CxxDecisionArc(switchNode, labelNum, - nextSt, caseSt)); - labelNum++; - ((AbstractBasicBlock)nextSt).addIncoming(switchNode); - prev = nextSt; + addOutgoing(prev, lbl); + addOutgoing(switchNode, lbl); + prev = lbl; continue; } if (elem instanceof IASTBreakStatement) { @@ -173,15 +175,12 @@ public class ControlFlowGraphBuilder { continue; } if (elem instanceof IASTDefaultStatement) { - IASTDefaultStatement caseSt = (IASTDefaultStatement) elem; - IPlainNode nextSt = factory - .createPlainNode(); + ILabeledNode lbl = factory + .createLabeledNode(ILabeledNode.DEFAULT); if (!(prev instanceof IExitNode) && prev != switchNode) - addOutgoing(prev, nextSt); - switchNode.addOutgoing(new CxxDecisionArc(switchNode, 0, - nextSt, caseSt)); - ((AbstractBasicBlock)nextSt).addIncoming(switchNode); - prev = nextSt; + addOutgoing(prev, lbl); + addOutgoing(switchNode, lbl); + prev = lbl; continue; } IBasicBlock last = createSubGraph(prev, elem); @@ -209,19 +208,24 @@ public class ControlFlowGraphBuilder { addOutgoing(nContinue2, decision); // add break connector IConnectorNode nBreak = factory.createConnectorNode(); - addOutgoing(decision, nBreak); - decision.setConnectorNode(nBreak); + decision.setMergeNode(nBreak); // 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 IPlainNode inc = factory.createPlainNode(forNode .getIterationExpression()); - addOutgoing(nBody, inc); + addOutgoing(endBody, inc); JumpNode jumpContinue = new JumpNode(); addOutgoing(inc, jumpContinue); jumpContinue.setJump(nContinue2, true); // connect with backward link addOutgoing(jumpContinue, nContinue2); + // add "else" branch + ILabeledNode loopEnd = factory.createLabeledNode(ILabeledNode.ELSE); + addOutgoing(decision, loopEnd); + addOutgoing(loopEnd, nBreak); return nBreak; } @@ -240,15 +244,50 @@ public class ControlFlowGraphBuilder { addOutgoing(nContinue, decision); // add break connector IConnectorNode nBreak = factory.createConnectorNode(); - addOutgoing(decision, nBreak); - decision.setConnectorNode(nBreak); + decision.setMergeNode(nBreak); // 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(); - addOutgoing(nBody, jumpContinue); + addOutgoing(endBody, jumpContinue); jumpContinue.setJump(nContinue, true); // connect with backward link 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; } diff --git a/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/internal/model/cfg/CxxDecisionArc.java b/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/internal/model/cfg/CxxLabeledNode.java similarity index 61% rename from codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/internal/model/cfg/CxxDecisionArc.java rename to codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/internal/model/cfg/CxxLabeledNode.java index d15a94e4dd3..b2237cbd7d2 100644 --- a/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/internal/model/cfg/CxxDecisionArc.java +++ b/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/internal/model/cfg/CxxLabeledNode.java @@ -10,26 +10,19 @@ *******************************************************************************/ 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.DecisionNode; -import org.eclipse.cdt.codan.provisional.core.model.cfg.IBasicBlock; +import org.eclipse.cdt.codan.internal.core.cfg.LabeledNode; import org.eclipse.cdt.core.dom.ast.IASTNode; /** * TODO: add description */ -public class CxxDecisionArc extends DecisionArc { - private IASTNode label; +public class CxxLabeledNode extends LabeledNode { + private IASTNode labelData; - /** - * @param decisionNode - * @param i - * @param node - */ - public CxxDecisionArc(DecisionNode decisionNode, int i, IBasicBlock node, - IASTNode label) { - super(decisionNode, i, node); - this.label = label; + + CxxLabeledNode(IASTNode label) { + super(label.getRawSignature()); + this.labelData = label; } /* @@ -39,6 +32,6 @@ public class CxxDecisionArc extends DecisionArc { */ @Override public String toString() { - return label.getRawSignature(); + return labelData.getRawSignature()+":"; } } diff --git a/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/internal/model/cfg/CxxNodeFactory.java b/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/internal/model/cfg/CxxNodeFactory.java index 44d26be2e1b..1bea3e1059c 100644 --- a/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/internal/model/cfg/CxxNodeFactory.java +++ b/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/internal/model/cfg/CxxNodeFactory.java @@ -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.provisional.core.model.cfg.IDecisionNode; 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.IPlainNode; import org.eclipse.cdt.codan.provisional.core.model.cfg.NodeFactory; @@ -37,6 +38,7 @@ public class CxxNodeFactory extends NodeFactory implements INodeFactory { public IExitNode createExitNode() { return new CxxExitNode(); } + public CxxPlainNode createPlainNode(IASTNode ast) { IPlainNode node = createPlainNode(); ((AbstractBasicBlock) node).setData(ast); @@ -48,9 +50,20 @@ public class CxxNodeFactory extends NodeFactory implements INodeFactory { ((AbstractBasicBlock) node).setData(ast); return (CxxDecisionNode) node; } + public CxxExitNode createExitNode(IASTNode ast) { IExitNode node = createExitNode(); ((AbstractBasicBlock) node).setData(ast); return (CxxExitNode) node; - } + } + + /** + * @param caseSt + * @return + */ + public ILabeledNode createLabeledNode(IASTNode caseSt) { + ILabeledNode node = createLabeledNode(caseSt.getRawSignature()); + ((AbstractBasicBlock) node).setData(caseSt); + return node; + } } diff --git a/codan/org.eclipse.cdt.codan.core.test/src/org/eclipse/cdt/codan/core/cfg/ControlFlowGraphTest.java b/codan/org.eclipse.cdt.codan.core.test/src/org/eclipse/cdt/codan/core/cfg/ControlFlowGraphTest.java index a1c0bbbe3ef..e5adb4bfb97 100644 --- a/codan/org.eclipse.cdt.codan.core.test/src/org/eclipse/cdt/codan/core/cfg/ControlFlowGraphTest.java +++ b/codan/org.eclipse.cdt.codan.core.test/src/org/eclipse/cdt/codan/core/cfg/ControlFlowGraphTest.java @@ -115,7 +115,7 @@ public class ControlFlowGraphTest extends CodanTestCase { } if (node instanceof IDecisionNode) { assertTrue("decision node outgping size",node.getOutgoingSize()>1); - assertNotNull(((IDecisionNode) node).getConnectionNode()); + assertNotNull(((IDecisionNode) node).getMergeNode()); } } diff --git a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/ControlFlowGraph.java b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/ControlFlowGraph.java index 8077938e32c..a310b642fdc 100644 --- a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/ControlFlowGraph.java +++ b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/ControlFlowGraph.java @@ -16,12 +16,13 @@ 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; -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.ILabeledNode; import org.eclipse.cdt.codan.provisional.core.model.cfg.ISingleOutgoing; import org.eclipse.cdt.codan.provisional.core.model.cfg.IStartNode; @@ -71,22 +72,21 @@ public class ControlFlowGraph implements IControlFlowGraph { public void print(IBasicBlock node) { System.out.println(node.getClass().getSimpleName() + ": " + ((AbstractBasicBlock) node).toStringData()); - if (node instanceof IConnectorNode) - if (((IConnectorNode) node).hasBackwardIncoming() == false) - return; if (node instanceof IDecisionNode) { // todo - Iterator decisionArcs = ((IDecisionNode) node) - .getDecisionArcs(); - for (; decisionArcs.hasNext();) { - IDecisionArc arc = decisionArcs.next(); - System.out.println("{" + arc.getIndex() + ":"); - print(arc.getOutgoing()); + Iterator branches = ((IDecisionNode) node) + .getOutgoingIterator(); + for (; branches.hasNext();) { + IBasicBlock brNode = branches.next(); + System.out.println("{"); + print(brNode); System.out.println("}"); } - print(((IDecisionNode) node).getConnectionNode()); + print(((IDecisionNode) node).getMergeNode()); } else if (node instanceof ISingleOutgoing) { - print(((ISingleOutgoing) node).getOutgoing()); + IBasicBlock next = ((ISingleOutgoing) node).getOutgoing(); + if (!(next instanceof IConnectorNode && !(next instanceof ILabeledNode))) + print(next); } } diff --git a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/DecisionArc.java b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/DecisionArc.java deleted file mode 100644 index ccd1dcc8621..00000000000 --- a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/DecisionArc.java +++ /dev/null @@ -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 + ""; - } -} \ No newline at end of file diff --git a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/DecisionNode.java b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/DecisionNode.java index 0b3621c46b4..facf2676fdb 100644 --- a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/DecisionNode.java +++ b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/DecisionNode.java @@ -11,14 +11,11 @@ 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; /** @@ -26,7 +23,7 @@ import org.eclipse.cdt.codan.provisional.core.model.cfg.IDecisionNode; */ public class DecisionNode extends AbstractSingleIncomingNode implements IDecisionNode { - private List next = new ArrayList(2); + private List next = new ArrayList(2); private IConnectorNode conn; /** @@ -36,39 +33,10 @@ public class DecisionNode extends AbstractSingleIncomingNode implements super(); } - public void setDecisionArcs(Collection next) { - this.next = Collections.unmodifiableList(new ArrayList( - next)); - } - @Override public void addOutgoing(IBasicBlock node) { - DecisionArc arc = new DecisionArc(this, getDecisionArcSize(), node); - next.add(arc); - } - - public void addOutgoing(IDecisionArc arc) { - next.add(arc); - } - - /* - * (non-Javadoc) - * - * @seeorg.eclipse.cdt.codan.provisional.core.model.cfg.IDecisionNode# - * getDecisionArcs() - */ - public Iterator getDecisionArcs() { - return next.iterator(); - } - - /* - * (non-Javadoc) - * - * @seeorg.eclipse.cdt.codan.provisional.core.model.cfg.IDecisionNode# - * getDecisionArcSize() - */ - public int getDecisionArcSize() { - return next.size(); + IConnectorNode cnode = (IConnectorNode) node; // cast to throw CCE + next.add(cnode); } /* @@ -78,25 +46,7 @@ public class DecisionNode extends AbstractSingleIncomingNode implements * getOutgoingIterator() */ public Iterator getOutgoingIterator() { - return new Iterator() { - private Iterator 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(); - } - }; + return next.iterator(); } /* @@ -116,11 +66,11 @@ public class DecisionNode extends AbstractSingleIncomingNode implements * @seeorg.eclipse.cdt.codan.provisional.core.model.cfg.IDecisionNode# * getConnectionNode() */ - public IConnectorNode getConnectionNode() { + public IConnectorNode getMergeNode() { return conn; } - public void setConnectorNode(IConnectorNode conn) { + public void setMergeNode(IConnectorNode conn) { this.conn = conn; } } diff --git a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/JumpNode.java b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/JumpNode.java index eddaf38bcd1..a322a0b0dec 100644 --- a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/JumpNode.java +++ b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/JumpNode.java @@ -46,7 +46,7 @@ public class JumpNode extends AbstractSingleIncomingNode implements IJumpNode { } public void setJump(IConnectorNode jump, boolean backward) { - if (this.jump != null) + if (this.jump != null && this.jump != jump) throw new IllegalArgumentException( "Cannot modify exiting connector"); //$NON-NLS-1$ this.jump = jump; @@ -59,8 +59,6 @@ public class JumpNode extends AbstractSingleIncomingNode implements IJumpNode { @Override public void addOutgoing(IBasicBlock node) { - if (node == jump) - return; - throw new UnsupportedOperationException(); + setJump((IConnectorNode) node, backward); } } diff --git a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/LabeledNode.java b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/LabeledNode.java new file mode 100644 index 00000000000..36eeee5180f --- /dev/null +++ b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/LabeledNode.java @@ -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(); + } +} diff --git a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/provisional/core/model/cfg/IDecisionArc.java b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/provisional/core/model/cfg/IDecisionArc.java deleted file mode 100644 index ed72b37c9d1..00000000000 --- a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/provisional/core/model/cfg/IDecisionArc.java +++ /dev/null @@ -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:
- * 0 - always a false (else) branch of if, and default branch for switch, - * even if no code exists
- * 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(); -} diff --git a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/provisional/core/model/cfg/IDecisionNode.java b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/provisional/core/model/cfg/IDecisionNode.java index 7329c528232..de3602f42a1 100644 --- a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/provisional/core/model/cfg/IDecisionNode.java +++ b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/provisional/core/model/cfg/IDecisionNode.java @@ -1,17 +1,16 @@ 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, - * it has one incoming arc and many outgoing, each of them has a value of - * condition associated with it. + * it has one incoming arc and many outgoing, each of outgoing node should be + * ILabeledNode */ public interface IDecisionNode extends IBasicBlock, ISingleIncoming { - Iterator getDecisionArcs(); - - int getDecisionArcSize(); - - IConnectorNode getConnectionNode(); + /** + * Node where branches of decision node merge + * + * @return + */ + IConnectorNode getMergeNode(); } diff --git a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/provisional/core/model/cfg/ILabeledNode.java b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/provisional/core/model/cfg/ILabeledNode.java new file mode 100644 index 00000000000..bae40b81e6b --- /dev/null +++ b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/provisional/core/model/cfg/ILabeledNode.java @@ -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(); +} diff --git a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/provisional/core/model/cfg/INodeFactory.java b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/provisional/core/model/cfg/INodeFactory.java index fa19b849982..b7ba30acb81 100644 --- a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/provisional/core/model/cfg/INodeFactory.java +++ b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/provisional/core/model/cfg/INodeFactory.java @@ -22,6 +22,8 @@ public interface INodeFactory { IConnectorNode createConnectorNode(); + ILabeledNode createLabeledNode(String label); + IStartNode createStartNode(); IExitNode createExitNode(); diff --git a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/provisional/core/model/cfg/NodeFactory.java b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/provisional/core/model/cfg/NodeFactory.java index b870c7acd4f..48b330aa2b4 100644 --- a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/provisional/core/model/cfg/NodeFactory.java +++ b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/provisional/core/model/cfg/NodeFactory.java @@ -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.ExitNode; 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.StartNode; @@ -99,4 +100,8 @@ public class NodeFactory implements INodeFactory { public IExitNode createExitNode() { return new ExitNode(); } + + public ILabeledNode createLabeledNode(String label) { + return new LabeledNode(label); + } } diff --git a/codan/org.eclipse.cdt.codan.ui.cfgview/icons/labeled.png b/codan/org.eclipse.cdt.codan.ui.cfgview/icons/labeled.png new file mode 100644 index 00000000000..dad4626a9e6 Binary files /dev/null and b/codan/org.eclipse.cdt.codan.ui.cfgview/icons/labeled.png differ diff --git a/codan/org.eclipse.cdt.codan.ui.cfgview/src/org/eclipse/cdt/codan/ui/cfgview/views/ControlFlowGraphView.java b/codan/org.eclipse.cdt.codan.ui.cfgview/src/org/eclipse/cdt/codan/ui/cfgview/views/ControlFlowGraphView.java index 76930c1e2b7..f3f05073bf8 100644 --- a/codan/org.eclipse.cdt.codan.ui.cfgview/src/org/eclipse/cdt/codan/ui/cfgview/views/ControlFlowGraphView.java +++ b/codan/org.eclipse.cdt.codan.ui.cfgview/src/org/eclipse/cdt/codan/ui/cfgview/views/ControlFlowGraphView.java @@ -3,16 +3,17 @@ package org.eclipse.cdt.codan.ui.cfgview.views; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; + import org.eclipse.cdt.codan.core.cxx.internal.model.cfg.ControlFlowGraphBuilder; import org.eclipse.cdt.codan.core.cxx.internal.model.cfg.CxxControlFlowGraph; 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.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.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.IStartNode; import org.eclipse.cdt.codan.ui.cfgview.ControlFlowGraphPlugin; @@ -120,22 +121,19 @@ public class ControlFlowGraphView extends ViewPart { return blocks.toArray(); } else if (parent instanceof IDecisionNode) { ArrayList blocks = new ArrayList(); - Iterator iter = ((IDecisionNode) parent) - .getDecisionArcs(); + Iterator iter = ((IDecisionNode) parent) + .getOutgoingIterator(); if (iter.hasNext()) { - IDecisionArc arc0 = iter.next(); for (; iter.hasNext();) { - IDecisionArc arc = iter.next(); + IBasicBlock arc = iter.next(); 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(); - } else if (parent instanceof IDecisionArc) { + } else if (parent instanceof ILabeledNode) { Collection blocks = getFlat( - ((IDecisionArc) parent).getOutgoing(), + ((ILabeledNode) parent).getOutgoing(), new ArrayList()); return blocks.toArray(); } @@ -156,23 +154,13 @@ public class ControlFlowGraphView extends ViewPart { strdata = ((AbstractBasicBlock) obj).toStringData(); } 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); } else if (obj instanceof IJumpNode) { 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; } @@ -196,6 +184,8 @@ public class ControlFlowGraphView extends ViewPart { imageKey = "start.png"; else if (obj instanceof IJumpNode) imageKey = "jump.png"; + else if (obj instanceof ILabeledNode) + imageKey = "labeled.png"; else if (obj instanceof IConnectorNode) imageKey = "connector.png"; return ControlFlowGraphPlugin.getDefault().getImage( @@ -210,26 +200,26 @@ public class ControlFlowGraphView extends ViewPart { } /** - * @param prev + * @param list * @param startNode * @return */ public Collection getFlat(IBasicBlock node, - Collection prev) { - prev.add(node); + Collection list) { + list.add(node); if (node instanceof IConnectorNode - && !((IConnectorNode) node).hasBackwardIncoming()) { - return prev; + && !((IConnectorNode) node).hasBackwardIncoming() && + !(node instanceof ILabeledNode)) { + return list; } if (node instanceof IJumpNode) - return prev; + return list; if (node instanceof ISingleOutgoing) { - getFlat(((ISingleOutgoing) node).getOutgoing(), prev); + getFlat(((ISingleOutgoing) node).getOutgoing(), list); } else if (node instanceof IDecisionNode) { - getFlat(((IDecisionNode) node).getConnectionNode().getOutgoing(), - prev); + getFlat(((IDecisionNode) node).getMergeNode().getOutgoing(), list); } - return prev; + return list; } /**