summaryrefslogtreecommitdiffstats
path: root/org.eclipse.cdt.codan.extension
diff options
context:
space:
mode:
authorElliott Baron <ebaron@fedoraproject.org>2009-10-12 20:37:13 -0400
committerElliott Baron <ebaron@fedoraproject.org>2009-10-12 20:37:13 -0400
commit306422deda74c5a120771f42e70422f77efcd640 (patch)
tree6ad062db01d908c314d8824b3afeb8567c4c68da /org.eclipse.cdt.codan.extension
parent18360ea0c9cd1fce259ba7cf6824b48736334c4f (diff)
downloadcodan-306422deda74c5a120771f42e70422f77efcd640.tar.gz
codan-306422deda74c5a120771f42e70422f77efcd640.tar.xz
codan-306422deda74c5a120771f42e70422f77efcd640.zip
Transition for branching complete; execution state made of CNF clauses of variable assignments & branch conditions; errors reported.
* org.eclipse.cdt.codan.extension/src/org/eclipse/cdt/codan/extension/ExecutionState.java: Use Clause class. * org.eclipse.cdt.codan.extension/src/org/eclipse/cdt/codan/extension/ExecutionStateClause.java: New file. * org.eclipse.cdt.codan.extension/src/org/eclipse/cdt/codan/extension/PropertyState.java: Take optional name arg. * org.eclipse.cdt.codan.extension/src/org/eclipse/cdt/codan/extension/SymbolicState.java: New copy method. * org.eclipse.cdt.codan.extension/src/org/eclipse/cdt/codan/extension/VariableAssignmentVisitor.java: New file. * org.eclipse.cdt.codan.extension/src/org/eclipse/cdt/codan/extension/checkers/CloseOpenedFilesChecker.java: See commit message. * org.eclipse.cdt.codan.extension/src/org/eclipse/cdt/codan/extension/checkers/FunctionNameParser.java: Use IASTNode.
Diffstat (limited to 'org.eclipse.cdt.codan.extension')
-rw-r--r--org.eclipse.cdt.codan.extension/src/org/eclipse/cdt/codan/extension/ExecutionState.java46
-rw-r--r--org.eclipse.cdt.codan.extension/src/org/eclipse/cdt/codan/extension/ExecutionStateClause.java47
-rw-r--r--org.eclipse.cdt.codan.extension/src/org/eclipse/cdt/codan/extension/PropertyState.java28
-rw-r--r--org.eclipse.cdt.codan.extension/src/org/eclipse/cdt/codan/extension/SymbolicState.java21
-rw-r--r--org.eclipse.cdt.codan.extension/src/org/eclipse/cdt/codan/extension/VariableAssignmentVisitor.java56
-rw-r--r--org.eclipse.cdt.codan.extension/src/org/eclipse/cdt/codan/extension/checkers/CloseOpenedFilesChecker.java256
-rw-r--r--org.eclipse.cdt.codan.extension/src/org/eclipse/cdt/codan/extension/checkers/FunctionNameParser.java10
7 files changed, 270 insertions, 194 deletions
diff --git a/org.eclipse.cdt.codan.extension/src/org/eclipse/cdt/codan/extension/ExecutionState.java b/org.eclipse.cdt.codan.extension/src/org/eclipse/cdt/codan/extension/ExecutionState.java
index ffefec7..6f4f496 100644
--- a/org.eclipse.cdt.codan.extension/src/org/eclipse/cdt/codan/extension/ExecutionState.java
+++ b/org.eclipse.cdt.codan.extension/src/org/eclipse/cdt/codan/extension/ExecutionState.java
@@ -13,33 +13,31 @@ package org.eclipse.cdt.codan.extension;
import java.util.ArrayList;
import java.util.List;
-import org.eclipse.cdt.core.dom.ast.IASTNode;
-
public class ExecutionState {
- private List<IASTNode> nodes;
+ private List<ExecutionStateClause> clauses;
private boolean top;
private boolean bottom;
public ExecutionState() {
- nodes = new ArrayList<IASTNode>();
+ clauses = new ArrayList<ExecutionStateClause>();
}
- public void addClause(IASTNode node) {
+ public void addClause(ExecutionStateClause node) {
setTop(false);
setBottom(false);
- nodes.add(node);
+ clauses.add(node);
}
- public void removeClause(IASTNode node) {
- nodes.remove(node);
- if (nodes.size() == 0) {
+ public void removeClause(ExecutionStateClause node) {
+ clauses.remove(node);
+ if (clauses.size() == 0) {
setTop(true);
setBottom(false);
}
}
- public IASTNode[] getClauses() {
- return nodes.toArray(new IASTNode[nodes.size()]);
+ public ExecutionStateClause[] getClauses() {
+ return clauses.toArray(new ExecutionStateClause[clauses.size()]);
}
public boolean isTop() {
@@ -57,5 +55,31 @@ public class ExecutionState {
public void setBottom(boolean bottom) {
this.bottom = bottom;
}
+
+ @Override
+ public String toString() {
+ String ret;
+ if (top) {
+ ret = "[TOP]";
+ }
+ else if (bottom) {
+ ret = "[BOTTOM]";
+ }
+ else {
+ StringBuffer buf = new StringBuffer();
+ if (clauses.size() > 0) {
+ for (ExecutionStateClause c : clauses) {
+ if (!c.isTrue()) {
+ buf.append("NOT ");
+ }
+ buf.append(c.getNode().getRawSignature());
+ buf.append(" AND ");
+ }
+ buf.delete(buf.length() - 5 /* " AND ".length() */, buf.length());
+ }
+ ret = buf.toString();
+ }
+ return ret;
+ }
}
diff --git a/org.eclipse.cdt.codan.extension/src/org/eclipse/cdt/codan/extension/ExecutionStateClause.java b/org.eclipse.cdt.codan.extension/src/org/eclipse/cdt/codan/extension/ExecutionStateClause.java
new file mode 100644
index 0000000..adb4e62
--- /dev/null
+++ b/org.eclipse.cdt.codan.extension/src/org/eclipse/cdt/codan/extension/ExecutionStateClause.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Elliott Baron
+ * 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:
+ * Elliott Baron - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.codan.extension;
+
+import org.eclipse.cdt.core.dom.ast.IASTNode;
+
+public class ExecutionStateClause {
+
+ private IASTNode node;
+ private boolean truthValue;
+
+ public ExecutionStateClause(IASTNode node) {
+ this(node, true);
+ }
+
+ public ExecutionStateClause(IASTNode node, boolean truthValue) {
+ this.node = node;
+ this.truthValue = truthValue;
+ }
+
+ public IASTNode getNode() {
+ return node;
+ }
+
+ public boolean isTrue() {
+ return truthValue;
+ }
+
+ @Override
+ public String toString() {
+ StringBuffer buf = new StringBuffer();
+ if (!truthValue) {
+ buf.append("NOT ");
+ }
+ buf.append(node.getRawSignature());
+ return buf.toString();
+ }
+
+}
diff --git a/org.eclipse.cdt.codan.extension/src/org/eclipse/cdt/codan/extension/PropertyState.java b/org.eclipse.cdt.codan.extension/src/org/eclipse/cdt/codan/extension/PropertyState.java
index 0b02211..95e334f 100644
--- a/org.eclipse.cdt.codan.extension/src/org/eclipse/cdt/codan/extension/PropertyState.java
+++ b/org.eclipse.cdt.codan.extension/src/org/eclipse/cdt/codan/extension/PropertyState.java
@@ -10,10 +10,32 @@
*******************************************************************************/
package org.eclipse.cdt.codan.extension;
-import org.eclipse.cdt.core.dom.ast.IASTStatement;
+import org.eclipse.cdt.core.dom.ast.IASTNode;
-public abstract class PropertyState {
+public abstract class PropertyState {
- public abstract PropertyState transition(IASTStatement stmt);
+ private String name;
+
+ public PropertyState() {
+ this(null);
+ }
+
+ public PropertyState(String name) {
+ this.name = name;
+ }
+
+ public abstract PropertyState transition(IASTNode node);
+
+ @Override
+ public String toString() {
+ String ret;
+ if (name != null) {
+ ret = name;
+ }
+ else {
+ ret = super.toString();
+ }
+ return ret;
+ }
}
diff --git a/org.eclipse.cdt.codan.extension/src/org/eclipse/cdt/codan/extension/SymbolicState.java b/org.eclipse.cdt.codan.extension/src/org/eclipse/cdt/codan/extension/SymbolicState.java
index 0907ce5..ad932ac 100644
--- a/org.eclipse.cdt.codan.extension/src/org/eclipse/cdt/codan/extension/SymbolicState.java
+++ b/org.eclipse.cdt.codan.extension/src/org/eclipse/cdt/codan/extension/SymbolicState.java
@@ -11,6 +11,7 @@
package org.eclipse.cdt.codan.extension;
import java.util.Collections;
+import java.util.HashSet;
import java.util.Set;
public class SymbolicState {
@@ -37,4 +38,24 @@ public class SymbolicState {
public void setPropertyStates(Set<PropertyState> ps) {
propertyStates = ps;
}
+
+ public SymbolicState copy() {
+ Set<PropertyState> ps = new HashSet<PropertyState>(propertyStates);
+ ExecutionState es = new ExecutionState();
+ for (ExecutionStateClause cl : executionState.getClauses()) {
+ es.addClause(cl);
+ }
+ return new SymbolicState(ps, es);
+ }
+
+ @Override
+ public String toString() {
+ StringBuffer buf = new StringBuffer();
+ buf.append("[");
+ buf.append(propertyStates);
+ buf.append(", ");
+ buf.append(executionState);
+ buf.append("]");
+ return buf.toString();
+ }
}
diff --git a/org.eclipse.cdt.codan.extension/src/org/eclipse/cdt/codan/extension/VariableAssignmentVisitor.java b/org.eclipse.cdt.codan.extension/src/org/eclipse/cdt/codan/extension/VariableAssignmentVisitor.java
new file mode 100644
index 0000000..ebe4ce4
--- /dev/null
+++ b/org.eclipse.cdt.codan.extension/src/org/eclipse/cdt/codan/extension/VariableAssignmentVisitor.java
@@ -0,0 +1,56 @@
+package org.eclipse.cdt.codan.extension;
+
+import org.eclipse.cdt.core.dom.ast.ASTVisitor;
+import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression;
+import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
+import org.eclipse.cdt.core.dom.ast.IASTExpression;
+import org.eclipse.cdt.core.dom.ast.IASTInitializer;
+import org.eclipse.cdt.core.dom.ast.IASTNode;
+
+/*******************************************************************************
+ * Copyright (c) 2009 Elliott Baron
+ * 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:
+ * Elliott Baron - initial API and implementation
+ *******************************************************************************/
+public class VariableAssignmentVisitor extends ASTVisitor {
+
+ private ExecutionState es;
+
+ public VariableAssignmentVisitor(ExecutionState es) {
+ this.es = es;
+ shouldVisitInitializers = true;
+ shouldVisitExpressions = true;
+ }
+
+ @Override
+ public int visit(IASTInitializer initializer) {
+ IASTNode parent = initializer.getParent();
+ if (parent instanceof IASTDeclarator) {
+ es.addClause(new ExecutionStateClause(parent));
+ return PROCESS_SKIP;
+ }
+ return PROCESS_CONTINUE;
+ }
+
+ @Override
+ public int visit(IASTExpression expression) {
+ if (expression instanceof IASTBinaryExpression) {
+ IASTBinaryExpression binExpr = (IASTBinaryExpression) expression;
+ int op = binExpr.getOperator();
+
+ // Check operator is an assignment operator
+ if (op >= IASTBinaryExpression.op_assign
+ && op <= IASTBinaryExpression.op_binaryOrAssign) {
+ es.addClause(new ExecutionStateClause(binExpr));
+ return PROCESS_SKIP;
+ }
+ }
+ return PROCESS_CONTINUE;
+ }
+
+}
diff --git a/org.eclipse.cdt.codan.extension/src/org/eclipse/cdt/codan/extension/checkers/CloseOpenedFilesChecker.java b/org.eclipse.cdt.codan.extension/src/org/eclipse/cdt/codan/extension/checkers/CloseOpenedFilesChecker.java
index 5ed04cc..04348ab 100644
--- a/org.eclipse.cdt.codan.extension/src/org/eclipse/cdt/codan/extension/checkers/CloseOpenedFilesChecker.java
+++ b/org.eclipse.cdt.codan.extension/src/org/eclipse/cdt/codan/extension/checkers/CloseOpenedFilesChecker.java
@@ -13,32 +13,23 @@ package org.eclipse.cdt.codan.extension.checkers;
import java.io.File;
import java.net.URI;
import java.text.MessageFormat;
-import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
-import java.util.List;
+import java.util.LinkedList;
import java.util.Map;
+import java.util.Queue;
import java.util.Set;
-import java.util.Stack;
import org.eclipse.cdt.codan.core.model.AbstractIndexAstChecker;
import org.eclipse.cdt.codan.extension.Activator;
import org.eclipse.cdt.codan.extension.ExecutionState;
+import org.eclipse.cdt.codan.extension.ExecutionStateClause;
import org.eclipse.cdt.codan.extension.PropertyState;
import org.eclipse.cdt.codan.extension.SymbolicState;
-import org.eclipse.cdt.core.dom.ast.ASTVisitor;
-import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression;
-import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
-import org.eclipse.cdt.core.dom.ast.IASTExpression;
-import org.eclipse.cdt.core.dom.ast.IASTExpressionStatement;
-import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression;
-import org.eclipse.cdt.core.dom.ast.IASTIdExpression;
-import org.eclipse.cdt.core.dom.ast.IASTInitializerExpression;
-import org.eclipse.cdt.core.dom.ast.IASTName;
+import org.eclipse.cdt.codan.extension.VariableAssignmentVisitor;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTStatement;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
-import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
@@ -56,7 +47,7 @@ public class CloseOpenedFilesChecker extends AbstractIndexAstChecker {
private static final String OPEN = "open";
private static final String CLOSE = "close";
- private Stack<IBlock> worklist;
+ private Queue<IBlock> worklist;
// Property simulation state info for CFG's edges
private Map<IControlFlowEdge, Set<SymbolicState>> edgeInfo;
@@ -65,17 +56,17 @@ public class CloseOpenedFilesChecker extends AbstractIndexAstChecker {
private PropertyState uninit;
private PropertyState error;
private PropertyState opened;
+
+ // Most recent node to cause transition to error state
+ private IASTNode errorNode;
public CloseOpenedFilesChecker() {
- worklist = new Stack<IBlock>();
+ worklist = new LinkedList<IBlock>();
edgeInfo = new HashMap<IControlFlowEdge, Set<SymbolicState>>();
initFSM();
}
public void processAst(IASTTranslationUnit ast) {
- // traverse the AST using the visitor pattern
- CloseOpenedFilesVisitor visitor = new CloseOpenedFilesVisitor();
-
GraphCreator creator = new GraphCreator();
// Retrieve resource corresponding to this translation unit
@@ -95,21 +86,22 @@ public class CloseOpenedFilesChecker extends AbstractIndexAstChecker {
IASTStatement fnBody = cgRoot.getFuncDef().getBody();
IControlFlowGraph cfg = new ControlFlowGraph(fnBody);
cfg.buildCFG();
- //cfg.print();
solve(cfg);
-
- // ast.accept(visitor);
+
+ IControlFlowEdge exitEdge = cfg.getExit().getInEdges()[0];
+ for (SymbolicState s : edgeInfo.get(exitEdge)) {
+ if (s.getPropertyStates().contains(error)) {
+ // Report problem
+ reportProblem(errorNode, s.getExecutionState());
+ }
+ }
}
}
private void solve(IControlFlowGraph cfg) {
for (IControlFlowEdge edge : cfg.getEdges()) {
- IASTNode from = edge.getFrom().getContent();
- IASTNode to = edge.getTo().getContent();
- System.out.println((from != null ? from.getRawSignature() : from) + " -> " + (to != null ? to.getRawSignature() : to));
-
// Initialize edgeInfo for each edge
Set<SymbolicState> set = new HashSet<SymbolicState>();
edgeInfo.put(edge, set);
@@ -124,14 +116,19 @@ public class CloseOpenedFilesChecker extends AbstractIndexAstChecker {
es.setTop(true);
symStates.add(new SymbolicState(propStates, es));
- worklist.push(entryEdge.getTo());
+ worklist.add(entryEdge.getTo());
+ // XXX Debug
+ printStates(entryEdge, symStates);
while (!worklist.isEmpty()) {
- IBlock blk = worklist.pop();
+ IBlock blk = worklist.remove();
if (isMerge(blk)) {
// Apply flow function for a merge block
Set<SymbolicState> newStates = flowMerge(blk, edgeInfo.get(blk.getInEdges()[0]), edgeInfo.get(blk.getInEdges()[1]));
add(blk.getOutEdges()[0], newStates);
+
+ // XXX Debug
+ System.out.println("MRG: " + printStates(blk.getOutEdges()[0], newStates));
}
else if (isBranch(blk)) {
// Apply flow function for a branch block
@@ -142,58 +139,37 @@ public class CloseOpenedFilesChecker extends AbstractIndexAstChecker {
// Assumes 0th out-edge is true branch, 1st out-edge is false branch
add(blk.getOutEdges()[0], newStatesTrue);
add(blk.getOutEdges()[1], newStatesFalse);
+
+ // XXX Debug
+ System.out.println("BR (T): " + printStates(blk.getOutEdges()[0], newStatesTrue));
+ System.out.println("BR (F): " + printStates(blk.getOutEdges()[1], newStatesFalse));
}
else {
// Apply flow function for a normal block
Set<SymbolicState> newStates = flowOther(blk, edgeInfo.get(blk.getInEdges()[0]));
- printStates(newStates);
// Don't process the null exit block
if (!blk.equals(cfg.getExit())) {
add(blk.getOutEdges()[0], newStates);
+ // XXX Debug
+ System.out.println("OTH: " + printStates(blk.getOutEdges()[0], newStates));
}
}
}
}
- private void printStates(Set<SymbolicState> states) {
+ private String printStates(IControlFlowEdge edge, Set<SymbolicState> states) {
StringBuffer buf = new StringBuffer();
- for (SymbolicState s : states) {
- buf.append("{");
- for (PropertyState ps : s.getPropertyStates()) {
- buf.append("{");
- if (ps.equals(uninit)) {
- buf.append("$u");
- }
- else if (ps.equals(opened)) {
- buf.append("o");
- }
- else /* error */ {
- buf.append("$e");
- }
- buf.append(", ");
- }
- buf.replace(buf.length() - 2, buf.length(), "}, ");
- if (s.getExecutionState().isTop()) {
- buf.append("[TOP]");
- }
- else if (s.getExecutionState().isBottom()) {
- buf.append("[BOT]");
- }
- else {
- buf.append("[");
- ExecutionState es = s.getExecutionState();
- IASTNode[] nodes = es.getClauses();
- for (IASTNode n : nodes) {
- buf.append(n.getRawSignature());
- buf.append(" ");
- }
- buf.replace(buf.length() - 1, buf.length(), "]");
- }
- buf.append("}");
- }
- System.out.println(buf.toString());
+ IASTNode from = edge.getFrom().getContent();
+ IASTNode to = edge.getTo().getContent();
+ buf.append("{");
+ buf.append(from == null ? from : from.getRawSignature());
+ buf.append(" -> ");
+ buf.append(to == null ? to : to.getRawSignature());
+ buf.append("} = ");
+ buf.append(states);
+ return buf.toString();
}
private Set<SymbolicState> flowMerge(IBlock blk, Set<SymbolicState> ss1,
@@ -228,37 +204,34 @@ public class CloseOpenedFilesChecker extends AbstractIndexAstChecker {
}
private SymbolicState transferBranch(IBlock blk, SymbolicState s, boolean value) {
- // TODO Auto-generated method stub
- return s;
+ IASTNode node = blk.getContent();
+
+ SymbolicState ret = s.copy();
+ if (node != null) {
+ // TODO Theorem Prover goes here! / Determine if branch is feasible
+
+ // Modify execution state according to branch condition
+ // *N.B.* content for condition IBlock is condition expression itself
+ ret.getExecutionState().addClause(new ExecutionStateClause(node, value));
+ }
+
+ return ret;
}
private SymbolicState transferOther(IBlock blk, SymbolicState s) {
IASTNode node = blk.getContent();
- if (node instanceof IASTExpressionStatement) {
+ if (node != null) {
// Process property state transition
Set<PropertyState> oldStates = s.getPropertyStates();
Set<PropertyState> newStates = new HashSet<PropertyState>();
for (PropertyState state : oldStates) {
- newStates.add(state.transition((IASTStatement) node));
+ newStates.add(state.transition(node));
}
s.setPropertyStates(newStates);
- // Check if we have an assignment statement
- IASTExpression expr = ((IASTExpressionStatement) node).getExpression();
- if (expr instanceof IASTBinaryExpression) {
- IASTBinaryExpression binExpr = (IASTBinaryExpression) expr;
- int op = binExpr.getOperator();
-
- // Check operator is an assignment operator
- if (op >= IASTBinaryExpression.op_assign
- && op <= IASTBinaryExpression.op_binaryOrAssign) {
- IASTExpression o1 = binExpr.getOperand1();
- if (o1 instanceof IASTIdExpression) {
- s.getExecutionState().addClause(((IASTIdExpression) o1).getName());
- }
- }
- }
+ // Modify execution state according to variable assignments
+ node.accept(new VariableAssignmentVisitor(s.getExecutionState()));
}
return s;
}
@@ -267,57 +240,64 @@ public class CloseOpenedFilesChecker extends AbstractIndexAstChecker {
Set<SymbolicState> ss) {
if (!edgeInfo.get(edge).equals(ss)) {
edgeInfo.put(edge, ss);
- worklist.push(edge.getTo());
+
+ // No duplicates
+ IBlock next = edge.getTo();
+ if (!worklist.contains(next)) {
+ worklist.add(next);
+ }
}
}
private void initFSM() {
- uninit = new PropertyState() {
+ uninit = new PropertyState("$u") {
@Override
- public PropertyState transition(IASTStatement stmt) {
+ public PropertyState transition(IASTNode node) {
PropertyState dest = uninit;
- if (containsOpen(stmt)) {
+ if (containsOpen(node)) {
dest = opened;
}
- else if (containsClose(stmt)) {
+ else if (containsClose(node)) {
dest = error;
+ errorNode = node;
}
return dest;
}
};
- opened = new PropertyState() {
+ opened = new PropertyState("o") {
@Override
- public PropertyState transition(IASTStatement stmt) {
+ public PropertyState transition(IASTNode node) {
PropertyState dest = opened;
- if (containsOpen(stmt)) {
+ if (containsOpen(node)) {
dest = error;
+ errorNode = node;
}
- if (containsClose(stmt)) {
+ if (containsClose(node)) {
dest = uninit;
}
return dest;
}
};
- error = new PropertyState() {
+ error = new PropertyState("$e") {
@Override
- public PropertyState transition(IASTStatement stmt) {
+ public PropertyState transition(IASTNode node) {
return error;
}
};
}
- protected boolean containsOpen(IASTStatement stmt) {
+ protected boolean containsOpen(IASTNode node) {
// TODO Examine more than just name
- FunctionNameParser parser = new FunctionNameParser(stmt, OPEN);
+ FunctionNameParser parser = new FunctionNameParser(node, OPEN);
return parser.matches();
}
- protected boolean containsClose(IASTStatement stmt) {
+ protected boolean containsClose(IASTNode node) {
// TODO Examine more than just name
- FunctionNameParser parser = new FunctionNameParser(stmt, CLOSE);
+ FunctionNameParser parser = new FunctionNameParser(node, CLOSE);
return parser.matches();
}
@@ -329,82 +309,8 @@ public class CloseOpenedFilesChecker extends AbstractIndexAstChecker {
return blk.getInEdges().length > 1;
}
- private void reportProblem(IASTName closeFD) {
- String message = MessageFormat.format("File descriptor \"{0}\" has not been opened", closeFD.toString());
- reportProblem(ERR_ID, closeFD, message);
+ private void reportProblem(IASTNode node, ExecutionState condition) {
+ String message = MessageFormat.format("Improper use of open/close given {0}.", condition);
+ reportProblem(ERR_ID, node, message);
}
-
-
- class CloseOpenedFilesVisitor extends ASTVisitor {
-
- private List<IASTName> openedFDs;
-
- public CloseOpenedFilesVisitor() {
- openedFDs = new ArrayList<IASTName>();
- shouldVisitExpressions = true;
- }
-
- @Override
- public int visit(IASTExpression expression) {
- if (expression instanceof IASTFunctionCallExpression) {
- IASTFunctionCallExpression callExpression = (IASTFunctionCallExpression) expression;
- IASTExpression funcName = callExpression.getFunctionNameExpression();
- if (funcName instanceof IASTIdExpression) {
- IASTName name = ((IASTIdExpression) funcName).getName();
- String simpleName = String.valueOf(name.getSimpleID());
- if (simpleName.equals(OPEN)) {
- IASTNode parent = callExpression.getParent();
- // Handle initialization in declaration
- if (parent instanceof IASTInitializerExpression) {
- parent = parent.getParent();
- if (parent instanceof IASTDeclarator) {
- openedFDs.add(((IASTDeclarator) parent).getName());
- }
- }
- // Assignment after declaration
- else if (parent instanceof IASTBinaryExpression) {
- IASTExpression op2 = ((IASTBinaryExpression) parent).getOperand2();
- int operator = ((IASTBinaryExpression) parent).getOperator();
- if (callExpression.equals(op2) && operator == IASTBinaryExpression.op_assign) {
- IASTExpression op1 = ((IASTBinaryExpression) parent).getOperand1();
- if (op1 instanceof IASTIdExpression) {
- openedFDs.add(((IASTIdExpression) op1).getName());
- }
- }
- }
- }
- else if (simpleName.equals(CLOSE)) {
- IASTExpression paramExpression = callExpression.getParameterExpression();
- if (paramExpression instanceof IASTIdExpression) {
- IASTName fd = ((IASTIdExpression) paramExpression).getName();
- // Add only if no matching opened FD
- boolean match = false;
- for (int i = 0; !match && i < openedFDs.size(); i++) {
- IASTName opened = openedFDs.get(i);
- match = matchingFileDescriptors(fd, opened);
- }
-
- if (!match) {
- reportProblem(fd);
- }
- }
- }
- }
-
- return PROCESS_SKIP;
- }
- else {
- return PROCESS_CONTINUE;
- }
- }
-
- private boolean matchingFileDescriptors(IASTName closeFD, IASTName openFD) {
- // FIXME elaborate
- IBinding closeBinding = closeFD.getBinding();
- IBinding openBinding = openFD.getBinding();
-
- return openBinding != null && closeBinding != null && openBinding.equals(closeBinding);
- }
- }
-
}
diff --git a/org.eclipse.cdt.codan.extension/src/org/eclipse/cdt/codan/extension/checkers/FunctionNameParser.java b/org.eclipse.cdt.codan.extension/src/org/eclipse/cdt/codan/extension/checkers/FunctionNameParser.java
index ae287f1..bf87ec1 100644
--- a/org.eclipse.cdt.codan.extension/src/org/eclipse/cdt/codan/extension/checkers/FunctionNameParser.java
+++ b/org.eclipse.cdt.codan.extension/src/org/eclipse/cdt/codan/extension/checkers/FunctionNameParser.java
@@ -15,20 +15,20 @@ import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression;
import org.eclipse.cdt.core.dom.ast.IASTIdExpression;
import org.eclipse.cdt.core.dom.ast.IASTName;
-import org.eclipse.cdt.core.dom.ast.IASTStatement;
+import org.eclipse.cdt.core.dom.ast.IASTNode;
public class FunctionNameParser {
- private IASTStatement stmt;
+ private IASTNode node;
private String funcName;
- public FunctionNameParser(IASTStatement stmt, String funcName) {
- this.stmt = stmt;
+ public FunctionNameParser(IASTNode node, String funcName) {
+ this.node = node;
this.funcName = funcName;
}
public boolean matches() {
FunctionNameVisitor visitor = new FunctionNameVisitor();
- stmt.accept(visitor);
+ node.accept(visitor);
return visitor.getResult();
}