1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-08-10 17:55:39 +02:00

- added support for break and continue

This commit is contained in:
Alena Laskavaia 2010-04-15 02:22:56 +00:00
parent 697b118ca5
commit 234a20224a
12 changed files with 154 additions and 108 deletions

View file

@ -21,12 +21,13 @@ 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.IBranchNode;
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;
import org.eclipse.cdt.core.dom.ast.IASTCaseStatement;
import org.eclipse.cdt.core.dom.ast.IASTCompoundStatement;
import org.eclipse.cdt.core.dom.ast.IASTContinueStatement;
import org.eclipse.cdt.core.dom.ast.IASTDeclarationStatement;
import org.eclipse.cdt.core.dom.ast.IASTDefaultStatement;
import org.eclipse.cdt.core.dom.ast.IASTDoStatement;
@ -49,6 +50,8 @@ public class ControlFlowGraphBuilder {
Collection<IBasicBlock> dead;
CxxExitNode returnExit;
CxxNodeFactory factory = new CxxNodeFactory();
IConnectorNode outerBreak;
IConnectorNode outerContinue;
/**
* @param def
@ -99,6 +102,14 @@ public class ControlFlowGraphBuilder {
node.setStartNode(start);
addOutgoing(prev, node);
return node;
} else if (body instanceof IASTBreakStatement) {
if (outerBreak != null)
return addJump(prev, outerBreak);
return prev;
} else if (body instanceof IASTContinueStatement) {
if (outerContinue != null)
return addJump(prev, outerContinue);
return prev;
} else if (body instanceof IASTSwitchStatement) {
return createSwitch(prev, (IASTSwitchStatement) body);
}
@ -116,14 +127,14 @@ public class ControlFlowGraphBuilder {
addOutgoing(prev, ifNode);
IConnectorNode mergeNode = factory.createConnectorNode();
ifNode.setMergeNode(mergeNode);
ILabeledNode thenNode = factory.createLabeledNode(ILabeledNode.THEN);
IBranchNode thenNode = factory.createLabeledNode(IBranchNode.THEN);
addOutgoing(ifNode, thenNode);
IBasicBlock then = createSubGraph(thenNode, body.getThenClause());
addOutgoing(then, mergeNode);
ILabeledNode elseNode = factory.createLabeledNode(ILabeledNode.ELSE);
addJump(then, mergeNode);
IBranchNode elseNode = factory.createLabeledNode(IBranchNode.ELSE);
addOutgoing(ifNode, elseNode);
IBasicBlock els = createSubGraph(elseNode, body.getElseClause());
addOutgoing(els, mergeNode);
addJump(els, mergeNode);
return mergeNode;
}
@ -144,12 +155,12 @@ public class ControlFlowGraphBuilder {
/**
* @param switchNode
* @param conn
* @param mergeNode
* @param def
* @param body
*/
private void createSwitchBody(DecisionNode switchNode, ConnectorNode conn,
IASTStatement body) {
private void createSwitchBody(DecisionNode switchNode,
ConnectorNode mergeNode, IASTStatement body) {
if (!(body instanceof IASTCompoundStatement))
return; // bad
IASTCompoundStatement comp = (IASTCompoundStatement) body;
@ -159,28 +170,38 @@ public class ControlFlowGraphBuilder {
IASTNode elem = children[i];
if (elem instanceof IASTCaseStatement) {
IASTCaseStatement caseSt = (IASTCaseStatement) elem;
ILabeledNode lbl = factory.createLabeledNode(caseSt);
}
if (elem instanceof IASTDefaultStatement) {
IBranchNode lbl = factory
.createLabeledNode(IBranchNode.DEFAULT);
if (!(prev instanceof IExitNode) && prev != switchNode)
addOutgoing(prev, lbl);
addOutgoing(switchNode, lbl);
prev = lbl;
continue;
}
if (elem instanceof IASTCaseStatement
|| elem instanceof IASTDefaultStatement) {
IBranchNode lbl = null;
if (elem instanceof IASTCaseStatement) {
IASTCaseStatement caseSt = (IASTCaseStatement) elem;
lbl = factory.createLabeledNode(caseSt);
} else if (elem instanceof IASTDefaultStatement) {
lbl = factory.createLabeledNode(IBranchNode.DEFAULT);
}
if (!(prev instanceof IExitNode) && prev != switchNode) {
IConnectorNode here = factory.createConnectorNode();
addJump(prev, here);
addOutgoing(lbl, here);
prev = here;
} else {
prev = lbl;
}
addOutgoing(switchNode, lbl);
continue;
}
if (elem instanceof IASTBreakStatement) {
JumpNode nBreak = (JumpNode) factory.createJumpNode();
addOutgoing(prev, nBreak);
nBreak.setJump(conn, false);
conn.addIncoming(nBreak);
prev = nBreak;
continue;
}
if (elem instanceof IASTDefaultStatement) {
ILabeledNode lbl = factory
.createLabeledNode(ILabeledNode.DEFAULT);
if (!(prev instanceof IExitNode) && prev != switchNode)
addOutgoing(prev, lbl);
addOutgoing(switchNode, lbl);
prev = lbl;
prev = addJump(prev, mergeNode);
continue;
}
IBasicBlock last = createSubGraph(prev, elem);
@ -200,32 +221,38 @@ public class ControlFlowGraphBuilder {
addOutgoing(prev, init);
prev = init;
// add continue connector
IConnectorNode nContinue2 = factory.createConnectorNode();
addOutgoing(prev, nContinue2);
IConnectorNode beforeCheck = factory.createConnectorNode();
addOutgoing(prev, beforeCheck);
// decision node
CxxDecisionNode decision = factory.createDecisionNode(forNode
.getConditionExpression());
addOutgoing(nContinue2, decision);
addOutgoing(beforeCheck, decision);
// add break connector
IConnectorNode nBreak = factory.createConnectorNode();
decision.setMergeNode(nBreak);
// create body and jump to continue node
ILabeledNode loopStart = factory.createLabeledNode(ILabeledNode.THEN);
IBranchNode loopStart = factory.createLabeledNode(IBranchNode.THEN);
addOutgoing(decision, loopStart);
// set break/continue
IConnectorNode nContinue = factory.createConnectorNode();
IConnectorNode savedContinue = outerContinue;
IConnectorNode savedBreak = outerBreak;
outerContinue = nContinue;
outerBreak = nBreak;
IBasicBlock endBody = createSubGraph(loopStart, forNode.getBody());
outerContinue = savedContinue;
outerBreak = savedBreak;
// inc
IPlainNode inc = factory.createPlainNode(forNode
.getIterationExpression());
addOutgoing(endBody, inc);
JumpNode jumpContinue = new JumpNode();
addOutgoing(inc, jumpContinue);
jumpContinue.setJump(nContinue2, true);
addOutgoing(endBody, nContinue);
addOutgoing(nContinue, inc);
// connect with backward link
addOutgoing(jumpContinue, nContinue2);
addJump(inc, beforeCheck, true);
// add "else" branch
ILabeledNode loopEnd = factory.createLabeledNode(ILabeledNode.ELSE);
IBranchNode loopEnd = factory.createLabeledNode(IBranchNode.ELSE);
addOutgoing(decision, loopEnd);
addOutgoing(loopEnd, nBreak);
addJump(loopEnd, nBreak);
return nBreak;
}
@ -246,18 +273,23 @@ public class ControlFlowGraphBuilder {
IConnectorNode nBreak = factory.createConnectorNode();
decision.setMergeNode(nBreak);
// create body and jump to continue node
ILabeledNode loopStart = factory.createLabeledNode(ILabeledNode.THEN);
IBranchNode loopStart = factory.createLabeledNode(IBranchNode.THEN);
addOutgoing(decision, loopStart);
// set break/continue
IConnectorNode savedContinue = outerContinue;
IConnectorNode savedBreak = outerBreak;
outerContinue = nContinue;
outerBreak = nBreak;
IBasicBlock endBody = createSubGraph(loopStart, body.getBody());
JumpNode jumpContinue = new JumpNode();
addOutgoing(endBody, jumpContinue);
jumpContinue.setJump(nContinue, true);
// connect with backward link
addOutgoing(jumpContinue, nContinue);
// restore
outerContinue = savedContinue;
outerBreak = savedBreak;
// backward jump
addJump(endBody, nContinue, true);
// connect with else branch
ILabeledNode loopEnd = factory.createLabeledNode(ILabeledNode.ELSE);
IBranchNode loopEnd = factory.createLabeledNode(IBranchNode.ELSE);
addOutgoing(decision, loopEnd);
addOutgoing(loopEnd, nBreak);
addJump(loopEnd, nBreak);
return nBreak;
}
@ -265,16 +297,25 @@ public class ControlFlowGraphBuilder {
// create body and jump to continue node
IConnectorNode loopStart = factory.createConnectorNode();
addOutgoing(prev, loopStart);
// continue/break
IConnectorNode nContinue = factory.createConnectorNode();
IConnectorNode nBreak = factory.createConnectorNode();
IConnectorNode savedContinue = outerContinue;
IConnectorNode savedBreak = outerBreak;
outerContinue = nContinue;
outerBreak = nBreak;
IBasicBlock endBody = createSubGraph(loopStart, body.getBody());
// restore
outerContinue = savedContinue;
outerBreak = savedBreak;
// 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);
IBranchNode thenNode = factory.createLabeledNode(IBranchNode.THEN);
addOutgoing(decision, thenNode);
IJumpNode jumpToStart = factory.createJumpNode();
addOutgoing(thenNode, jumpToStart);
@ -282,15 +323,29 @@ public class ControlFlowGraphBuilder {
// connect with backward link
addOutgoing(jumpToStart, loopStart);
// connect with else branch
ILabeledNode loopEnd = factory.createLabeledNode(ILabeledNode.ELSE);
IBranchNode loopEnd = factory.createLabeledNode(IBranchNode.ELSE);
addOutgoing(decision, loopEnd);
// add break connector
IConnectorNode nBreak = factory.createConnectorNode();
decision.setMergeNode(nBreak);
addOutgoing(loopEnd, nBreak);
addJump(loopEnd, nBreak);
return nBreak;
}
private IJumpNode addJump(IBasicBlock prev, IConnectorNode conn) {
return addJump(prev, conn, false);
}
private IJumpNode addJump(IBasicBlock prev, IConnectorNode conn,
boolean backward) {
if (prev instanceof IJumpNode)
return (IJumpNode) prev;
IJumpNode jump = factory.createJumpNode();
addOutgoing(prev, jump);
addOutgoing(jump, conn);
((JumpNode) jump).setBackward(backward);
return jump;
}
/**
* @param prev
* @param node

View file

@ -10,17 +10,17 @@
*******************************************************************************/
package org.eclipse.cdt.codan.core.cxx.internal.model.cfg;
import org.eclipse.cdt.codan.internal.core.cfg.LabeledNode;
import org.eclipse.cdt.codan.internal.core.cfg.BranchNode;
import org.eclipse.cdt.core.dom.ast.IASTNode;
/**
* TODO: add description
*/
public class CxxLabeledNode extends LabeledNode {
public class CxxBranchNode extends BranchNode {
private IASTNode labelData;
CxxLabeledNode(IASTNode label) {
CxxBranchNode(IASTNode label) {
super(label.getRawSignature());
this.labelData = label;
}

View file

@ -13,7 +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.IBranchNode;
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;
@ -61,8 +61,8 @@ public class CxxNodeFactory extends NodeFactory implements INodeFactory {
* @param caseSt
* @return
*/
public ILabeledNode createLabeledNode(IASTNode caseSt) {
ILabeledNode node = createLabeledNode(caseSt.getRawSignature());
public IBranchNode createLabeledNode(IASTNode caseSt) {
IBranchNode node = createLabeledNode(caseSt.getRawSignature());
((AbstractBasicBlock) node).setData(caseSt);
return node;
}

View file

@ -10,15 +10,15 @@
*******************************************************************************/
package org.eclipse.cdt.codan.internal.core.cfg;
import org.eclipse.cdt.codan.provisional.core.model.cfg.ILabeledNode;
import org.eclipse.cdt.codan.provisional.core.model.cfg.IBranchNode;
/**
* TODO: add description
*/
public class LabeledNode extends ConnectorNode implements ILabeledNode {
private String label;
public class BranchNode extends PlainNode implements IBranchNode {
protected String label;
public LabeledNode(String label) {
public BranchNode(String label) {
super();
this.label = label;
}
@ -27,7 +27,7 @@ public class LabeledNode extends ConnectorNode implements ILabeledNode {
* (non-Javadoc)
*
* @see
* org.eclipse.cdt.codan.provisional.core.model.cfg.ILabeledNode#getLabel()
* org.eclipse.cdt.codan.provisional.core.model.cfg.IBranchNode#getLabel()
*/
public String getLabel() {
return label;
@ -35,8 +35,6 @@ public class LabeledNode extends ConnectorNode implements ILabeledNode {
@Override
public String toStringData() {
if (getData() == null)
return label + ":";
return getData().toString();
return label;
}
}

View file

@ -22,7 +22,7 @@ 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.ILabeledNode;
import org.eclipse.cdt.codan.provisional.core.model.cfg.IBranchNode;
import org.eclipse.cdt.codan.provisional.core.model.cfg.ISingleOutgoing;
import org.eclipse.cdt.codan.provisional.core.model.cfg.IStartNode;
@ -85,7 +85,7 @@ public class ControlFlowGraph implements IControlFlowGraph {
print(((IDecisionNode) node).getMergeNode());
} else if (node instanceof ISingleOutgoing) {
IBasicBlock next = ((ISingleOutgoing) node).getOutgoing();
if (!(next instanceof IConnectorNode && !(next instanceof ILabeledNode)))
if (!(next instanceof IConnectorNode && !(next instanceof IBranchNode)))
print(next);
}
}

View file

@ -15,6 +15,7 @@ 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.IBranchNode;
import org.eclipse.cdt.codan.provisional.core.model.cfg.IConnectorNode;
import org.eclipse.cdt.codan.provisional.core.model.cfg.IDecisionNode;
@ -35,7 +36,7 @@ public class DecisionNode extends AbstractSingleIncomingNode implements
@Override
public void addOutgoing(IBasicBlock node) {
IConnectorNode cnode = (IConnectorNode) node; // cast to throw CCE
IBranchNode cnode = (IBranchNode) node; // cast to throw CCE
next.add(cnode);
}

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;
import org.eclipse.cdt.codan.provisional.core.model.cfg.IPlainNode;
@ -9,7 +10,7 @@ import org.eclipse.cdt.codan.provisional.core.model.cfg.IPlainNode;
*
*/
public class PlainNode extends AbstractSingleIncomingNode implements IPlainNode {
IBasicBlock next;
protected IBasicBlock next;
public PlainNode() {
super();
@ -28,9 +29,6 @@ public class PlainNode extends AbstractSingleIncomingNode implements IPlainNode
}
public void setOutgoing(IBasicBlock exit) {
if (this.next != null)
throw new IllegalArgumentException(
"Cannot modify already exiting connector"); //$NON-NLS-1$
this.next = exit;
}

View file

@ -13,7 +13,8 @@ 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 interface IBranchNode extends IBasicBlock, ISingleIncoming,
ISingleOutgoing {
public static String THEN = "then"; //$NON-NLS-1$
public static String ELSE = "else"; //$NON-NLS-1$
public static String DEFAULT = "default"; //$NON-NLS-1$

View file

@ -4,7 +4,7 @@ package org.eclipse.cdt.codan.provisional.core.model.cfg;
*
* Interface for decision node. This node represent condition node in the graph,
* it has one incoming arc and many outgoing, each of outgoing node should be
* ILabeledNode
* IBranchNode
*/
public interface IDecisionNode extends IBasicBlock, ISingleIncoming {
/**

View file

@ -22,7 +22,7 @@ public interface INodeFactory {
IConnectorNode createConnectorNode();
ILabeledNode createLabeledNode(String label);
IBranchNode createLabeledNode(String label);
IStartNode createStartNode();

View file

@ -14,7 +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.BranchNode;
import org.eclipse.cdt.codan.internal.core.cfg.PlainNode;
import org.eclipse.cdt.codan.internal.core.cfg.StartNode;
@ -101,7 +101,7 @@ public class NodeFactory implements INodeFactory {
return new ExitNode();
}
public ILabeledNode createLabeledNode(String label) {
return new LabeledNode(label);
public IBranchNode createLabeledNode(String label) {
return new BranchNode(label);
}
}

View file

@ -13,7 +13,7 @@ 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.ILabeledNode;
import org.eclipse.cdt.codan.provisional.core.model.cfg.IBranchNode;
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;
@ -131,10 +131,9 @@ public class ControlFlowGraphView extends ViewPart {
}
blocks.add(((IDecisionNode) parent).getMergeNode());
return blocks.toArray();
} else if (parent instanceof ILabeledNode) {
Collection<IBasicBlock> blocks = getFlat(
((ILabeledNode) parent).getOutgoing(),
new ArrayList<IBasicBlock>());
} else if (parent instanceof IBranchNode) {
Collection<IBasicBlock> blocks = getFlat(((IBranchNode) parent)
.getOutgoing(), new ArrayList<IBasicBlock>());
return blocks.toArray();
}
return new Object[0];
@ -143,6 +142,25 @@ public class ControlFlowGraphView extends ViewPart {
public boolean hasChildren(Object parent) {
return getChildren(parent).length > 0;
}
/**
* @param list
* @param startNode
* @return
*/
public Collection<IBasicBlock> getFlat(IBasicBlock node,
Collection<IBasicBlock> list) {
list.add(node);
if (node instanceof IJumpNode)
return list;
if (node instanceof ISingleOutgoing) {
getFlat(((ISingleOutgoing) node).getOutgoing(), list);
} else if (node instanceof IDecisionNode) {
getFlat(((IDecisionNode) node).getMergeNode().getOutgoing(),
list);
}
return list;
}
}
class ViewLabelProvider extends LabelProvider {
@ -154,9 +172,7 @@ public class ControlFlowGraphView extends ViewPart {
strdata = ((AbstractBasicBlock) obj).toStringData();
}
if (strdata == null || strdata.length() == 0) {
if (obj instanceof ILabeledNode) {
strdata = strdata+blockHexLabel(obj);
} else if (obj instanceof IConnectorNode) {
if (obj instanceof IConnectorNode) {
strdata = blockHexLabel(obj);
} else if (obj instanceof IJumpNode) {
strdata = blockHexLabel(((IJumpNode) obj).getJumpNode());
@ -184,7 +200,7 @@ public class ControlFlowGraphView extends ViewPart {
imageKey = "start.png";
else if (obj instanceof IJumpNode)
imageKey = "jump.png";
else if (obj instanceof ILabeledNode)
else if (obj instanceof IBranchNode)
imageKey = "labeled.png";
else if (obj instanceof IConnectorNode)
imageKey = "connector.png";
@ -199,29 +215,6 @@ public class ControlFlowGraphView extends ViewPart {
public ControlFlowGraphView() {
}
/**
* @param list
* @param startNode
* @return
*/
public Collection<IBasicBlock> getFlat(IBasicBlock node,
Collection<IBasicBlock> list) {
list.add(node);
if (node instanceof IConnectorNode
&& !((IConnectorNode) node).hasBackwardIncoming() &&
!(node instanceof ILabeledNode)) {
return list;
}
if (node instanceof IJumpNode)
return list;
if (node instanceof ISingleOutgoing) {
getFlat(((ISingleOutgoing) node).getOutgoing(), list);
} else if (node instanceof IDecisionNode) {
getFlat(((IDecisionNode) node).getMergeNode().getOutgoing(), list);
}
return list;
}
/**
* This is a callback that will allow us to create the viewer and initialize
* it.