mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-22 22:22:11 +02:00
-added switch to cfg
This commit is contained in:
parent
e15c6eccb9
commit
c7f45478a9
4 changed files with 260 additions and 95 deletions
|
@ -12,6 +12,7 @@ package org.eclipse.cdt.codan.core.cxx.internal.model.cfg;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
import org.eclipse.cdt.codan.internal.core.cfg.AbstractBasicBlock;
|
import org.eclipse.cdt.codan.internal.core.cfg.AbstractBasicBlock;
|
||||||
import org.eclipse.cdt.codan.internal.core.cfg.ConnectorNode;
|
import org.eclipse.cdt.codan.internal.core.cfg.ConnectorNode;
|
||||||
import org.eclipse.cdt.codan.internal.core.cfg.DecisionNode;
|
import org.eclipse.cdt.codan.internal.core.cfg.DecisionNode;
|
||||||
|
@ -21,8 +22,11 @@ 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.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.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.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;
|
||||||
|
@ -30,6 +34,7 @@ import org.eclipse.cdt.core.dom.ast.IASTIfStatement;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTReturnStatement;
|
import org.eclipse.cdt.core.dom.ast.IASTReturnStatement;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTStatement;
|
import org.eclipse.cdt.core.dom.ast.IASTStatement;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTSwitchStatement;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTWhileStatement;
|
import org.eclipse.cdt.core.dom.ast.IASTWhileStatement;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -79,63 +84,138 @@ public class ControlFlowGraphBuilder {
|
||||||
addOutgoing(prev, node);
|
addOutgoing(prev, node);
|
||||||
return node;
|
return node;
|
||||||
} else if (body instanceof IASTIfStatement) {
|
} else if (body instanceof IASTIfStatement) {
|
||||||
DecisionNode node = factory.createDecisionNode(
|
return createIf(prev, (IASTIfStatement) body);
|
||||||
((IASTIfStatement) body).getConditionExpression());
|
} else if (body instanceof IASTWhileStatement) {
|
||||||
|
return createWhile(prev, (IASTWhileStatement) body);
|
||||||
|
} else if (body instanceof IASTForStatement) {
|
||||||
|
return createFor(prev, (IASTForStatement) body);
|
||||||
|
} else if (body instanceof IASTReturnStatement) {
|
||||||
|
CxxExitNode node = factory.createExitNode(body);
|
||||||
|
node.setStartNode(start);
|
||||||
|
addOutgoing(prev, node);
|
||||||
|
return node;
|
||||||
|
} else if (body instanceof IASTSwitchStatement) {
|
||||||
|
return createSwitch(prev, (IASTSwitchStatement) body);
|
||||||
|
}
|
||||||
|
return prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param prev
|
||||||
|
* @param body
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
protected IBasicBlock createIf(IBasicBlock prev, IASTIfStatement body) {
|
||||||
|
DecisionNode node = factory.createDecisionNode(body
|
||||||
|
.getConditionExpression());
|
||||||
addOutgoing(prev, node);
|
addOutgoing(prev, node);
|
||||||
ConnectorNode conn = new ConnectorNode();
|
ConnectorNode conn = new ConnectorNode();
|
||||||
node.setConnectorNode(conn);
|
node.setConnectorNode(conn);
|
||||||
IBasicBlock els = createSubGraph(node, ((IASTIfStatement) body)
|
IBasicBlock els = createSubGraph(node, body.getElseClause());
|
||||||
.getElseClause());
|
|
||||||
conn.addIncoming(els);
|
conn.addIncoming(els);
|
||||||
addOutgoing(els, conn);
|
addOutgoing(els, conn);
|
||||||
IBasicBlock then = createSubGraph(node, ((IASTIfStatement) body)
|
IBasicBlock then = createSubGraph(node, body.getThenClause());
|
||||||
.getThenClause());
|
|
||||||
conn.addIncoming(then);
|
conn.addIncoming(then);
|
||||||
addOutgoing(then, conn);
|
addOutgoing(then, conn);
|
||||||
return conn;
|
return conn;
|
||||||
} else if (body instanceof IASTWhileStatement) {
|
}
|
||||||
// add continue connector
|
|
||||||
IConnectorNode nContinue = factory.createConnectorNode();
|
|
||||||
addOutgoing(prev, nContinue);
|
|
||||||
// decision node
|
|
||||||
CxxDecisionNode decision = factory.createDecisionNode(
|
|
||||||
((IASTWhileStatement) body).getCondition());
|
|
||||||
addOutgoing(nContinue, 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,
|
|
||||||
((IASTWhileStatement) body).getBody());
|
|
||||||
JumpNode jumpContinue = new JumpNode();
|
|
||||||
addOutgoing(nBody, jumpContinue);
|
|
||||||
jumpContinue.setJump(nContinue, true);
|
|
||||||
// connect with backward link
|
|
||||||
addOutgoing(jumpContinue, nContinue);
|
|
||||||
|
|
||||||
return nBreak;
|
/**
|
||||||
} else if (body instanceof IASTForStatement) {
|
* @param prev
|
||||||
|
* @param body
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private IBasicBlock createSwitch(IBasicBlock prev, IASTSwitchStatement body) {
|
||||||
|
DecisionNode node = factory.createDecisionNode(body
|
||||||
|
.getControllerExpression());
|
||||||
|
addOutgoing(prev, node);
|
||||||
|
ConnectorNode conn = new ConnectorNode();
|
||||||
|
node.setConnectorNode(conn);
|
||||||
|
createSwitchBody(node, conn, body.getBody());
|
||||||
|
return conn;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param switchNode
|
||||||
|
* @param conn
|
||||||
|
* @param def
|
||||||
|
* @param body
|
||||||
|
*/
|
||||||
|
private void createSwitchBody(DecisionNode switchNode, ConnectorNode conn,
|
||||||
|
IASTStatement body) {
|
||||||
|
if (!(body instanceof IASTCompoundStatement))
|
||||||
|
return; // bad
|
||||||
|
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();
|
||||||
|
if (!(prev instanceof IExitNode) && prev != switchNode)
|
||||||
|
addOutgoing(prev, nextSt);
|
||||||
|
switchNode.addOutgoing(new CxxDecisionArc(switchNode, labelNum,
|
||||||
|
nextSt, caseSt));
|
||||||
|
labelNum++;
|
||||||
|
((AbstractBasicBlock)nextSt).addIncoming(switchNode);
|
||||||
|
prev = nextSt;
|
||||||
|
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) {
|
||||||
|
IASTDefaultStatement caseSt = (IASTDefaultStatement) elem;
|
||||||
|
IPlainNode nextSt = factory
|
||||||
|
.createPlainNode();
|
||||||
|
if (!(prev instanceof IExitNode) && prev != switchNode)
|
||||||
|
addOutgoing(prev, nextSt);
|
||||||
|
switchNode.addOutgoing(new CxxDecisionArc(switchNode, 0,
|
||||||
|
nextSt, caseSt));
|
||||||
|
((AbstractBasicBlock)nextSt).addIncoming(switchNode);
|
||||||
|
prev = nextSt;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
IBasicBlock last = createSubGraph(prev, elem);
|
||||||
|
prev = last;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param prev
|
||||||
|
* @param forNode
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private IBasicBlock createFor(IBasicBlock prev, IASTForStatement forNode) {
|
||||||
// add initializer
|
// add initializer
|
||||||
IPlainNode init = factory.createPlainNode(((IASTForStatement) body).getInitializerStatement());
|
IPlainNode init = factory.createPlainNode(forNode
|
||||||
|
.getInitializerStatement());
|
||||||
addOutgoing(prev, init);
|
addOutgoing(prev, init);
|
||||||
prev = init;
|
prev = init;
|
||||||
// add continue connector
|
// add continue connector
|
||||||
IConnectorNode nContinue2 = factory.createConnectorNode();
|
IConnectorNode nContinue2 = factory.createConnectorNode();
|
||||||
addOutgoing(prev, nContinue2);
|
addOutgoing(prev, nContinue2);
|
||||||
// decision node
|
// decision node
|
||||||
CxxDecisionNode decision = factory.createDecisionNode(
|
CxxDecisionNode decision = factory.createDecisionNode(forNode
|
||||||
((IASTForStatement) body).getConditionExpression());
|
.getConditionExpression());
|
||||||
addOutgoing(nContinue2, decision);
|
addOutgoing(nContinue2, decision);
|
||||||
// add break connector
|
// add break connector
|
||||||
IConnectorNode nBreak = factory.createConnectorNode();
|
IConnectorNode nBreak = factory.createConnectorNode();
|
||||||
addOutgoing(decision, nBreak);
|
addOutgoing(decision, nBreak);
|
||||||
decision.setConnectorNode(nBreak);
|
decision.setConnectorNode(nBreak);
|
||||||
// create body and jump to continue node
|
// create body and jump to continue node
|
||||||
IBasicBlock nBody = createSubGraph(decision,
|
IBasicBlock nBody = createSubGraph(decision, forNode.getBody());
|
||||||
((IASTForStatement) body).getBody());
|
|
||||||
// inc
|
// inc
|
||||||
IPlainNode inc = factory.createPlainNode(((IASTForStatement) body).getIterationExpression());
|
IPlainNode inc = factory.createPlainNode(forNode
|
||||||
|
.getIterationExpression());
|
||||||
addOutgoing(nBody, inc);
|
addOutgoing(nBody, inc);
|
||||||
JumpNode jumpContinue = new JumpNode();
|
JumpNode jumpContinue = new JumpNode();
|
||||||
addOutgoing(inc, jumpContinue);
|
addOutgoing(inc, jumpContinue);
|
||||||
|
@ -143,13 +223,33 @@ public class ControlFlowGraphBuilder {
|
||||||
// connect with backward link
|
// connect with backward link
|
||||||
addOutgoing(jumpContinue, nContinue2);
|
addOutgoing(jumpContinue, nContinue2);
|
||||||
return nBreak;
|
return nBreak;
|
||||||
} else if (body instanceof IASTReturnStatement) {
|
|
||||||
CxxExitNode node = factory.createExitNode(body);
|
|
||||||
node.setStartNode(start);
|
|
||||||
addOutgoing(prev, node);
|
|
||||||
return node;
|
|
||||||
}
|
}
|
||||||
return prev;
|
|
||||||
|
/**
|
||||||
|
* @param prev
|
||||||
|
* @param body
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
protected IBasicBlock createWhile(IBasicBlock prev, IASTWhileStatement body) {
|
||||||
|
// add continue connector
|
||||||
|
IConnectorNode nContinue = factory.createConnectorNode();
|
||||||
|
addOutgoing(prev, nContinue);
|
||||||
|
// decision node
|
||||||
|
CxxDecisionNode decision = factory.createDecisionNode(body
|
||||||
|
.getCondition());
|
||||||
|
addOutgoing(nContinue, 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, body.getBody());
|
||||||
|
JumpNode jumpContinue = new JumpNode();
|
||||||
|
addOutgoing(nBody, jumpContinue);
|
||||||
|
jumpContinue.setJump(nContinue, true);
|
||||||
|
// connect with backward link
|
||||||
|
addOutgoing(jumpContinue, nContinue);
|
||||||
|
return nBreak;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* 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.DecisionArc;
|
||||||
|
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 CxxDecisionArc extends DecisionArc {
|
||||||
|
private IASTNode label;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param decisionNode
|
||||||
|
* @param i
|
||||||
|
* @param node
|
||||||
|
*/
|
||||||
|
public CxxDecisionArc(DecisionNode decisionNode, int i, IBasicBlock node,
|
||||||
|
IASTNode label) {
|
||||||
|
super(decisionNode, i, node);
|
||||||
|
this.label = label;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
*
|
||||||
|
* @see org.eclipse.cdt.codan.internal.core.cfg.DecisionArc#toString()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return label.getRawSignature();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* 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 + "";
|
||||||
|
}
|
||||||
|
}
|
|
@ -29,38 +29,6 @@ public class DecisionNode extends AbstractSingleIncomingNode implements
|
||||||
private List<IDecisionArc> next = new ArrayList<IDecisionArc>(2);
|
private List<IDecisionArc> next = new ArrayList<IDecisionArc>(2);
|
||||||
private IConnectorNode conn;
|
private IConnectorNode conn;
|
||||||
|
|
||||||
class DecisionArc implements IDecisionArc {
|
|
||||||
int index;
|
|
||||||
IBasicBlock node;
|
|
||||||
|
|
||||||
DecisionArc(int i, IBasicBlock node) {
|
|
||||||
this.index = i;
|
|
||||||
this.node = node;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getIndex() {
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IBasicBlock getOutgoing() {
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IDecisionNode getDecisionNode() {
|
|
||||||
return DecisionNode.this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
*
|
|
||||||
* @see java.lang.Object#toString()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return index + "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param prev
|
* @param prev
|
||||||
*/
|
*/
|
||||||
|
@ -75,7 +43,11 @@ public class DecisionNode extends AbstractSingleIncomingNode implements
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addOutgoing(IBasicBlock node) {
|
public void addOutgoing(IBasicBlock node) {
|
||||||
DecisionArc arc = new DecisionArc(getDecisionArcSize(), node);
|
DecisionArc arc = new DecisionArc(this, getDecisionArcSize(), node);
|
||||||
|
next.add(arc);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addOutgoing(IDecisionArc arc) {
|
||||||
next.add(arc);
|
next.add(arc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue