1
/*******************************************************************************
2
* Copyright (c) 2007, 2011 Wind River Systems, Inc. and others.
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
9
* Markus Schorn - initial API and implementation
10
*******************************************************************************/
11
package org.eclipse.cdt.internal.core.dom.parser;
13
import org.eclipse.cdt.core.dom.ast.IASTArrayModifier;
14
import org.eclipse.cdt.core.dom.ast.IASTArraySubscriptExpression;
15
import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression;
16
import org.eclipse.cdt.core.dom.ast.IASTCaseStatement;
17
import org.eclipse.cdt.core.dom.ast.IASTCastExpression;
18
import org.eclipse.cdt.core.dom.ast.IASTCompoundStatement;
19
import org.eclipse.cdt.core.dom.ast.IASTConditionalExpression;
20
import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
21
import org.eclipse.cdt.core.dom.ast.IASTDoStatement;
22
import org.eclipse.cdt.core.dom.ast.IASTEqualsInitializer;
23
import org.eclipse.cdt.core.dom.ast.IASTExpression;
24
import org.eclipse.cdt.core.dom.ast.IASTExpressionList;
25
import org.eclipse.cdt.core.dom.ast.IASTExpressionStatement;
26
import org.eclipse.cdt.core.dom.ast.IASTFieldReference;
27
import org.eclipse.cdt.core.dom.ast.IASTForStatement;
28
import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression;
29
import org.eclipse.cdt.core.dom.ast.IASTIdExpression;
30
import org.eclipse.cdt.core.dom.ast.IASTIfStatement;
31
import org.eclipse.cdt.core.dom.ast.IASTInitializerClause;
32
import org.eclipse.cdt.core.dom.ast.IASTInitializerList;
33
import org.eclipse.cdt.core.dom.ast.IASTNode;
34
import org.eclipse.cdt.core.dom.ast.IASTProblemExpression;
35
import org.eclipse.cdt.core.dom.ast.IASTProblemStatement;
36
import org.eclipse.cdt.core.dom.ast.IASTReturnStatement;
37
import org.eclipse.cdt.core.dom.ast.IASTStatement;
38
import org.eclipse.cdt.core.dom.ast.IASTSwitchStatement;
39
import org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression;
40
import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression;
41
import org.eclipse.cdt.core.dom.ast.IASTWhileStatement;
42
import org.eclipse.cdt.core.dom.ast.IArrayType;
43
import org.eclipse.cdt.core.dom.ast.IBinding;
44
import org.eclipse.cdt.core.dom.ast.IFunctionType;
45
import org.eclipse.cdt.core.dom.ast.IType;
46
import org.eclipse.cdt.core.dom.ast.IVariable;
47
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTRangeBasedForStatement;
48
import org.eclipse.cdt.core.dom.ast.gnu.IGNUASTCompoundStatementExpression;
49
import org.eclipse.cdt.internal.core.pdom.dom.PDOMName;
52
* Helper class to determine whether a variable is accessed for reading and/or writing.
53
* The algorithm works starting from the variable and looking upwards what's being done
54
* with the variable. C- and C++ specific things are handled in sub-classes.
56
public abstract class VariableReadWriteFlags {
57
protected static final int READ = PDOMName.READ_ACCESS;
58
protected static final int WRITE = PDOMName.WRITE_ACCESS;
60
protected VariableReadWriteFlags() {
63
protected int rwAnyNode(IASTNode node, int indirection) {
64
final IASTNode parent = node.getParent();
65
if (parent instanceof IASTExpression) {
66
return rwInExpression((IASTExpression) parent, node, indirection);
67
} else if (parent instanceof IASTStatement) {
68
return rwInStatement((IASTStatement) parent, node, indirection);
69
} else if (parent instanceof IASTEqualsInitializer) {
70
return rwInEqualsInitializer((IASTEqualsInitializer) parent, indirection);
71
} else if (parent instanceof IASTArrayModifier) {
72
return READ; // dimension
73
} else if (parent instanceof IASTInitializerList) {
74
return rwInInitializerList((IASTInitializerList) parent, indirection);
76
return READ | WRITE; // fallback
79
protected int rwInEqualsInitializer(IASTEqualsInitializer parent, int indirection) {
80
IASTNode grand= parent.getParent();
81
if (grand instanceof IASTDeclarator) {
82
IBinding binding= ((IASTDeclarator) grand).getName().getBinding();
83
if (binding instanceof IVariable) {
84
return rwAssignmentToType(((IVariable) binding).getType(), indirection);
87
return READ | WRITE; // fallback
90
protected int rwInInitializerList(IASTInitializerList parent, int indirection) {
91
IASTNode grand= parent.getParent();
92
if (grand instanceof IASTEqualsInitializer) {
93
IASTNode grandGrand= grand.getParent();
94
if (grandGrand instanceof IASTDeclarator) {
95
IBinding binding= ((IASTDeclarator) grandGrand).getName().resolveBinding();
96
if (binding instanceof IVariable) {
97
IType type= ((IVariable) binding).getType();
98
if (type instanceof IArrayType) {
99
return rwAssignmentToType(type, indirection);
104
return READ | WRITE; // fallback
107
protected int rwInExpression(IASTExpression expr, IASTNode node, int indirection) {
108
if (expr instanceof IASTBinaryExpression) {
109
return rwInBinaryExpression(node, (IASTBinaryExpression) expr, indirection);
111
if (expr instanceof IASTCastExpression) { // must be ahead of unary
112
return rwAnyNode(expr, indirection);
114
if (expr instanceof IASTUnaryExpression) {
115
return rwInUnaryExpression(node, (IASTUnaryExpression) expr, indirection);
117
if (expr instanceof IASTArraySubscriptExpression) {
118
if (indirection > 0 && node.getPropertyInParent() == IASTArraySubscriptExpression.ARRAY) {
119
return rwAnyNode(expr, indirection-1);
123
if (expr instanceof IASTConditionalExpression) {
124
if (node.getPropertyInParent() == IASTConditionalExpression.LOGICAL_CONDITION) {
127
return rwAnyNode(expr, indirection);
129
if (expr instanceof IASTExpressionList) {
130
// Only the first expression is passed on.
131
final IASTExpression[] expressions = ((IASTExpressionList) expr).getExpressions();
132
if (expressions.length > 0 && expressions[0] == node) {
133
return rwAnyNode(expr, indirection);
137
if (expr instanceof IASTFieldReference) {
138
if (node.getPropertyInParent() == IASTFieldReference.FIELD_NAME) {
139
return rwAnyNode(expr, indirection);
143
if (expr instanceof IASTFunctionCallExpression) {
144
if (node.getPropertyInParent() == IASTFunctionCallExpression.FUNCTION_NAME) {
147
return rwArgumentForFunctionCall((IASTFunctionCallExpression) expr, node, indirection);
149
if (expr instanceof IASTIdExpression) {
150
return rwAnyNode(expr, indirection);
152
if (expr instanceof IASTProblemExpression) {
155
if (expr instanceof IASTTypeIdExpression) {
159
return READ | WRITE; // fall back
162
protected int rwArgumentForFunctionCall(final IASTFunctionCallExpression funcCall, IASTNode argument, int indirection) {
163
final IASTInitializerClause[] args = funcCall.getArguments();
164
for (int i = 0; i < args.length; i++) {
165
if (args[i] == argument) {
166
final IASTExpression functionNameExpression = funcCall.getFunctionNameExpression();
167
if (functionNameExpression != null) {
168
final IType type= functionNameExpression.getExpressionType();
169
if (type instanceof IFunctionType) {
170
return rwArgumentForFunctionCall((IFunctionType) type, i, indirection);
176
return READ | WRITE; // fallback
180
protected int rwArgumentForFunctionCall(IFunctionType type, int parameterIdx, int indirection) {
181
IType[] ptypes= type.getParameterTypes();
182
if (ptypes != null && ptypes.length > parameterIdx) {
183
return rwAssignmentToType(ptypes[parameterIdx], indirection);
185
return READ | WRITE; // Fallback
188
protected abstract int rwAssignmentToType(IType type, int indirection);
190
protected int rwInStatement(IASTStatement stmt, IASTNode node, int indirection) {
191
if (stmt instanceof IASTCaseStatement) {
192
if (node.getPropertyInParent() == IASTCaseStatement.EXPRESSION) {
196
else if (stmt instanceof IASTDoStatement) {
197
if (node.getPropertyInParent() == IASTDoStatement.CONDITION) {
201
else if (stmt instanceof IASTExpressionStatement) {
202
IASTNode parent= stmt.getParent();
203
while (parent instanceof IASTCompoundStatement) {
204
IASTCompoundStatement compound= (IASTCompoundStatement) parent;
205
IASTStatement[] statements= compound.getStatements();
206
if (statements[statements.length-1] != stmt) {
210
parent= stmt.getParent();
212
if (parent instanceof IGNUASTCompoundStatementExpression) {
213
return rwAnyNode(parent, indirection);
215
} else if (stmt instanceof IASTForStatement) {
216
if (node.getPropertyInParent() == IASTForStatement.CONDITION) {
219
} else if (stmt instanceof ICPPASTRangeBasedForStatement) {
220
if (node.getPropertyInParent() == ICPPASTRangeBasedForStatement.INITIALIZER) {
224
else if (stmt instanceof IASTIfStatement) {
225
if (node.getPropertyInParent() == IASTIfStatement.CONDITION) {
229
else if (stmt instanceof IASTProblemStatement) {
232
else if (stmt instanceof IASTReturnStatement) {
233
return indirection == 0 ? READ : WRITE;
235
else if (stmt instanceof IASTSwitchStatement) {
236
if (node.getPropertyInParent() == IASTSwitchStatement.CONTROLLER_EXP) {
240
else if (stmt instanceof IASTWhileStatement) {
241
if (node.getPropertyInParent() == IASTWhileStatement.CONDITIONEXPRESSION) {
248
protected int rwInUnaryExpression(IASTNode node, IASTUnaryExpression expr, int indirection) {
249
switch(expr.getOperator()) {
250
case IASTUnaryExpression.op_bracketedPrimary:
251
return rwAnyNode(expr, indirection);
253
case IASTUnaryExpression.op_amper:
254
return rwAnyNode(expr, indirection+1);
256
case IASTUnaryExpression.op_star:
257
if (indirection > 0) {
258
return rwAnyNode(expr, indirection-1);
262
case IASTUnaryExpression.op_postFixDecr:
263
case IASTUnaryExpression.op_postFixIncr:
264
case IASTUnaryExpression.op_prefixDecr:
265
case IASTUnaryExpression.op_prefixIncr:
268
case IASTUnaryExpression.op_minus:
269
case IASTUnaryExpression.op_not:
270
case IASTUnaryExpression.op_plus:
271
case IASTUnaryExpression.op_tilde:
272
return PDOMName.READ_ACCESS;
274
case IASTUnaryExpression.op_sizeof:
275
case IASTUnaryExpression.op_sizeofParameterPack:
276
case IASTUnaryExpression.op_alignOf:
282
protected int rwInBinaryExpression(IASTNode node, IASTBinaryExpression expr, int indirection) {
283
switch(expr.getOperator()) {
284
case IASTBinaryExpression.op_assign:
285
if (node.getPropertyInParent() == IASTBinaryExpression.OPERAND_ONE) {
288
return rwAssignmentToType(expr.getOperand1().getExpressionType(), indirection);
290
case IASTBinaryExpression.op_binaryAndAssign:
291
case IASTBinaryExpression.op_binaryOrAssign:
292
case IASTBinaryExpression.op_binaryXorAssign:
293
case IASTBinaryExpression.op_divideAssign:
294
case IASTBinaryExpression.op_minusAssign:
295
case IASTBinaryExpression.op_moduloAssign:
296
case IASTBinaryExpression.op_multiplyAssign:
297
case IASTBinaryExpression.op_plusAssign:
298
case IASTBinaryExpression.op_shiftLeftAssign:
299
case IASTBinaryExpression.op_shiftRightAssign:
300
if (node.getPropertyInParent() == IASTBinaryExpression.OPERAND_ONE) {
305
case IASTBinaryExpression.op_binaryAnd:
306
case IASTBinaryExpression.op_binaryOr:
307
case IASTBinaryExpression.op_binaryXor:
308
case IASTBinaryExpression.op_divide:
309
case IASTBinaryExpression.op_equals:
310
case IASTBinaryExpression.op_greaterEqual:
311
case IASTBinaryExpression.op_greaterThan:
312
case IASTBinaryExpression.op_lessEqual:
313
case IASTBinaryExpression.op_lessThan:
314
case IASTBinaryExpression.op_logicalAnd:
315
case IASTBinaryExpression.op_logicalOr:
316
case IASTBinaryExpression.op_modulo:
317
case IASTBinaryExpression.op_multiply:
318
case IASTBinaryExpression.op_notequals:
319
case IASTBinaryExpression.op_shiftLeft:
320
case IASTBinaryExpression.op_shiftRight:
323
case IASTBinaryExpression.op_minus:
324
case IASTBinaryExpression.op_plus:
325
if (indirection > 0) {
326
// can be pointer arithmetics
327
return rwAnyNode(expr, indirection);
331
return READ; // fallback