~ubuntu-branches/debian/sid/eclipse-cdt/sid

« back to all changes in this revision

Viewing changes to codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/StatementHasNoEffectChecker.java

  • Committer: Package Import Robot
  • Author(s): Jakub Adam
  • Date: 2011-10-06 21:15:04 UTC
  • mfrom: (1.1.4)
  • Revision ID: package-import@ubuntu.com-20111006211504-8dutmljjih0zikfv
Tags: 8.0.1-1
* New upstream release.
* Split the JNI packages into a separate architecture dependent
  package and made eclipse-cdt architecture independent.
* Install JNI libraries into multiarch aware location
* Bumped Standards-Version to 3.9.2.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*******************************************************************************
 
2
 * Copyright (c) 2009, 2010 Alena Laskavaia 
 
3
 * All rights reserved. This program and the accompanying materials
 
4
 * are made available under the terms of the Eclipse Public License v1.0
 
5
 * which accompanies this distribution, and is available at
 
6
 * http://www.eclipse.org/legal/epl-v10.html
 
7
 *
 
8
 * Contributors:
 
9
 *    Alena Laskavaia  - initial API and implementation
 
10
 *******************************************************************************/
 
11
package org.eclipse.cdt.codan.internal.checkers;
 
12
 
 
13
import org.eclipse.cdt.codan.core.cxx.CxxAstUtils;
 
14
import org.eclipse.cdt.codan.core.cxx.model.AbstractIndexAstChecker;
 
15
import org.eclipse.cdt.codan.core.model.IProblemWorkingCopy;
 
16
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
 
17
import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression;
 
18
import org.eclipse.cdt.core.dom.ast.IASTCompoundStatement;
 
19
import org.eclipse.cdt.core.dom.ast.IASTExpression;
 
20
import org.eclipse.cdt.core.dom.ast.IASTExpressionStatement;
 
21
import org.eclipse.cdt.core.dom.ast.IASTIdExpression;
 
22
import org.eclipse.cdt.core.dom.ast.IASTImplicitName;
 
23
import org.eclipse.cdt.core.dom.ast.IASTImplicitNameOwner;
 
24
import org.eclipse.cdt.core.dom.ast.IASTNode;
 
25
import org.eclipse.cdt.core.dom.ast.IASTStatement;
 
26
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
 
27
import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression;
 
28
import org.eclipse.cdt.core.dom.ast.IBasicType;
 
29
import org.eclipse.cdt.core.dom.ast.IType;
 
30
import org.eclipse.cdt.core.dom.ast.gnu.IGNUASTCompoundStatementExpression;
 
31
 
 
32
/**
 
33
 * Checker that detects statements without effect such as
 
34
 * 
 
35
 * a+b;
 
36
 * or
 
37
 * +b;
 
38
 * 
 
39
 * 
 
40
 */
 
41
public class StatementHasNoEffectChecker extends AbstractIndexAstChecker {
 
42
        public static final String ER_ID = "org.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem"; //$NON-NLS-1$
 
43
        public static final String PARAM_MACRO_ID = "macro"; //$NON-NLS-1$
 
44
        public static final String PARAM_EXCEPT_ARG_LIST = "exceptions"; //$NON-NLS-1$
 
45
 
 
46
        public void processAst(IASTTranslationUnit ast) {
 
47
                ast.accept(new CheckStmpVisitor());
 
48
        }
 
49
 
 
50
        class CheckStmpVisitor extends ASTVisitor {
 
51
                CheckStmpVisitor() {
 
52
                        shouldVisitStatements = true;
 
53
                }
 
54
 
 
55
                @Override
 
56
                public int visit(IASTStatement stmt) {
 
57
                        if (stmt instanceof IASTExpressionStatement) {
 
58
                                IASTExpression expression = ((IASTExpressionStatement) stmt).getExpression();
 
59
                                if (hasNoEffect(expression)) {
 
60
                                        if (!shouldReportInMacro() && CxxAstUtils.isInMacro(expression))
 
61
                                                return PROCESS_SKIP;
 
62
                                        String arg = expression.getRawSignature();
 
63
                                        if (!isFilteredArg(arg))
 
64
                                                reportProblem(ER_ID, stmt, arg);
 
65
                                }
 
66
                                return PROCESS_SKIP;
 
67
                        }
 
68
                        return PROCESS_CONTINUE;
 
69
                }
 
70
 
 
71
                /**
 
72
                 * We consider has not effect binary statements without assignment and
 
73
                 * unary statement which is not dec and inc. If operator is overloaded
 
74
                 * we not going to bother.
 
75
                 * 
 
76
                 * @param e
 
77
                 * @return
 
78
                 */
 
79
                private boolean hasNoEffect(IASTExpression e) {
 
80
                        if (e instanceof IASTBinaryExpression) {
 
81
                                IASTBinaryExpression binExpr = (IASTBinaryExpression) e;
 
82
                                if (isPossibleAssignment(binExpr))
 
83
                                        return false;
 
84
                                switch (binExpr.getOperator()) {
 
85
                                        case IASTBinaryExpression.op_logicalOr:
 
86
                                        case IASTBinaryExpression.op_logicalAnd:
 
87
                                                return hasNoEffect(binExpr.getOperand1()) && hasNoEffect(binExpr.getOperand2());
 
88
                                }
 
89
                                return true;
 
90
                        }
 
91
                        if (e instanceof IASTUnaryExpression) {
 
92
                                IASTUnaryExpression unaryExpr = (IASTUnaryExpression) e;
 
93
                                int operator = unaryExpr.getOperator();
 
94
                                switch (operator) {
 
95
                                        case IASTUnaryExpression.op_postFixDecr:
 
96
                                        case IASTUnaryExpression.op_prefixDecr:
 
97
                                        case IASTUnaryExpression.op_postFixIncr:
 
98
                                        case IASTUnaryExpression.op_prefixIncr:
 
99
                                        case IASTUnaryExpression.op_throw:
 
100
                                                return false;
 
101
                                        case IASTUnaryExpression.op_bracketedPrimary:
 
102
                                                return hasNoEffect(unaryExpr.getOperand());
 
103
                                }
 
104
                                return true;
 
105
                        }
 
106
                        // simply a;
 
107
                        if (e instanceof IASTIdExpression) {
 
108
                                // check if it is part of GNU comp stmt expression i.e. ({foo();a;})
 
109
                                IASTNode parent = e.getParent();
 
110
                                if (parent instanceof IASTExpressionStatement) {
 
111
                                        IASTNode parent2 = parent.getParent();
 
112
                                        if (parent2 instanceof IASTCompoundStatement) {
 
113
                                                IASTNode parent3 = parent2.getParent();
 
114
                                                if (parent3 instanceof IGNUASTCompoundStatementExpression) {
 
115
                                                        return false;
 
116
                                                }
 
117
                                        }
 
118
                                }
 
119
                                return true;
 
120
                        }
 
121
                        return false;
 
122
                }
 
123
        }
 
124
 
 
125
        @Override
 
126
        public void initPreferences(IProblemWorkingCopy problem) {
 
127
                super.initPreferences(problem);
 
128
                addPreference(problem, PARAM_MACRO_ID, CheckersMessages.StatementHasNoEffectChecker_ParameterMacro, Boolean.TRUE);
 
129
                addListPreference(problem, PARAM_EXCEPT_ARG_LIST, CheckersMessages.GenericParameter_ParameterExceptions,
 
130
                                CheckersMessages.GenericParameter_ParameterExceptionsItem);
 
131
        }
 
132
 
 
133
        public boolean isFilteredArg(String arg) {
 
134
                return isFilteredArg(arg, getProblemById(ER_ID, getFile()), PARAM_EXCEPT_ARG_LIST);
 
135
        }
 
136
 
 
137
        /**
 
138
         * @return
 
139
         */
 
140
        public boolean shouldReportInMacro() {
 
141
                return (Boolean) getPreference(getProblemById(ER_ID, getFile()), PARAM_MACRO_ID);
 
142
        }
 
143
 
 
144
        public boolean isPossibleAssignment(IASTBinaryExpression expr) {
 
145
                switch (expr.getOperator()) {
 
146
                        case IASTBinaryExpression.op_assign:
 
147
                        case IASTBinaryExpression.op_binaryAndAssign:
 
148
                        case IASTBinaryExpression.op_binaryOrAssign:
 
149
                        case IASTBinaryExpression.op_binaryXorAssign:
 
150
                        case IASTBinaryExpression.op_divideAssign:
 
151
                        case IASTBinaryExpression.op_minusAssign:
 
152
                        case IASTBinaryExpression.op_moduloAssign:
 
153
                        case IASTBinaryExpression.op_multiplyAssign:
 
154
                        case IASTBinaryExpression.op_plusAssign:
 
155
                        case IASTBinaryExpression.op_shiftLeftAssign:
 
156
                        case IASTBinaryExpression.op_shiftRightAssign:
 
157
                                return true;
 
158
                }
 
159
                if (expr instanceof IASTImplicitNameOwner) {
 
160
                        // Check whether the operator is overloaded
 
161
                        IASTImplicitName[] implicitNames = ((IASTImplicitNameOwner) expr).getImplicitNames();
 
162
                        if (implicitNames.length > 0)
 
163
                                return true;
 
164
                        IType expressionType = expr.getOperand1().getExpressionType();
 
165
                        if (!(expressionType instanceof IBasicType)) {
 
166
                                return true; // must be overloaded but parser could not
 
167
                                // find it
 
168
                        }
 
169
                }
 
170
                return false;
 
171
        }
 
172
}