mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-08-04 14:55:41 +02:00
Store information about read/write access of variables in index, bug 156692.
This commit is contained in:
parent
a54c25f473
commit
ff426e5841
9 changed files with 667 additions and 7 deletions
|
@ -279,4 +279,117 @@ public class IndexNamesTests extends BaseTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// int _i, ri, wi, rwi;
|
||||
// int* rp; int* wp; int* rwp;
|
||||
// const int* cip= &ri;
|
||||
// int* bla= &rwi;
|
||||
// void fi(int);
|
||||
// void fp(int*);
|
||||
// void fcp(const int*);
|
||||
// void fpp(int**);
|
||||
// void fcpp(int const**);
|
||||
// void fpcp(int *const*);
|
||||
// void fcpcp(int const *const*);
|
||||
//
|
||||
// void test() {
|
||||
// _i;
|
||||
// wi= ri, _i, _i;
|
||||
// rwi %= ri;
|
||||
// ri ? _i : _i;
|
||||
// (ri ? wi : wi)= ri;
|
||||
// if (ri) _i;
|
||||
// for(wi=1; ri>ri; rwi++) _i;
|
||||
// do {_i;} while (ri);
|
||||
// while(ri) {_i;};
|
||||
// switch(ri) {case ri: _i;};
|
||||
// fi(ri); fp(&rwi); fcp(&ri);
|
||||
// fi(*rp); fp(rp); fcp(rp); fpp(&rwp); fcpp(&rwp); fpcp(&rp); fcpcp(&rp);
|
||||
// return ri;
|
||||
// }
|
||||
public void testReadWriteFlagsC() throws Exception {
|
||||
waitForIndexer();
|
||||
String content= getContentsForTest(1)[0].toString();
|
||||
IFile file= createFile(getProject().getProject(), "test.c", content);
|
||||
waitUntilFileIsIndexed(file, 4000);
|
||||
|
||||
checkReadWriteFlags(file, ILinkage.C_LINKAGE_ID, 41);
|
||||
}
|
||||
|
||||
private void checkReadWriteFlags(IFile file, int linkageID, int count) throws InterruptedException,
|
||||
CoreException {
|
||||
fIndex.acquireReadLock();
|
||||
try {
|
||||
IIndexFile ifile= fIndex.getFile(linkageID, IndexLocationFactory.getWorkspaceIFL(file));
|
||||
IIndexName[] names= ifile.findNames(0, Integer.MAX_VALUE);
|
||||
int j= 0;
|
||||
for (int i = 0; i < names.length; i++) {
|
||||
IIndexName indexName = names[i];
|
||||
final String name = indexName.toString();
|
||||
final char c0= name.length() > 0 ? name.charAt(0) : 0;
|
||||
if ((c0 == '_' || c0 == 'r' || c0 == 'w') && indexName.isReference()) {
|
||||
boolean isRead= name.charAt(0) == 'r';
|
||||
boolean isWrite= name.charAt(isRead ? 1 : 0) == 'w';
|
||||
String msg= "i=" + i + ", " + name + ":";
|
||||
assertEquals(msg, isRead, indexName.isReadAccess());
|
||||
assertEquals(msg, isWrite, indexName.isWriteAccess());
|
||||
j++;
|
||||
}
|
||||
else {
|
||||
assertEquals(false, indexName.couldBePolymorphicMethodCall());
|
||||
}
|
||||
}
|
||||
assertEquals(count, j);
|
||||
}
|
||||
finally {
|
||||
fIndex.releaseReadLock();
|
||||
}
|
||||
}
|
||||
|
||||
// int _i, ri, wi, rwi, rfind, ridebug;
|
||||
// int* rp; int* wp; int* rwp;
|
||||
// int* const rpc= 0;
|
||||
// const int * const rcpc= 0;
|
||||
// const int* cip= &ri;
|
||||
// int* bla= &rwi;
|
||||
// void fi(int);
|
||||
// void fp(int*);
|
||||
// void fr(int&);
|
||||
// void fcp(const int*);
|
||||
// void fcr(const int&);
|
||||
// void fpp(int**);
|
||||
// void fpr(int*&);
|
||||
// void fcpp(int const**);
|
||||
// void fcpr(int const*&);
|
||||
// void fpcp(int *const*);
|
||||
// void fpcr(int *const&);
|
||||
// void fcpcp(int const *const*);
|
||||
// void fcpcr(int const *const&);
|
||||
//
|
||||
// void test() {
|
||||
// _i;
|
||||
// wi= ri, _i, _i; // expr-list
|
||||
// rwi %= ri; // assignment
|
||||
// ri ? _i : _i; // conditional
|
||||
// (ri ? wi : wi)= ri; // conditional
|
||||
// if (ri) _i;
|
||||
// for(wi=1; ri>ri; rwi++) _i;
|
||||
// do {_i;} while (ri);
|
||||
// while(ri) {_i;};
|
||||
// switch(ri) {case ri: _i;};
|
||||
// fi(ri); fp(&rwi); fcp(&ri);
|
||||
// fi(*rp); fp(rp); fcp(rp); fpp(&rwp); fcpp(&rwp); fpcp(&rpc); fcpcp(&rcpc);
|
||||
// fr(rwi); fcr(ri); fpr(&rwi);
|
||||
// fcpr(&ridebug); fpcr(&rwi); fcpcr(&ri);
|
||||
// fpr(rwp); fcpr(rwp); fpcr(rp); fcpcr(rp);
|
||||
// return ri;
|
||||
// }
|
||||
public void testReadWriteFlagsCpp() throws Exception {
|
||||
waitForIndexer();
|
||||
String content= getContentsForTest(1)[0].toString();
|
||||
IFile file= createFile(getProject().getProject(), "test.cpp", content);
|
||||
waitUntilFileIsIndexed(file, 4000);
|
||||
|
||||
checkReadWriteFlags(file, ILinkage.CPP_LINKAGE_ID, 51);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -75,4 +75,22 @@ public interface IIndexName extends IName {
|
|||
* No checks are performed whether the method is actually virtual or not.
|
||||
*/
|
||||
public boolean couldBePolymorphicMethodCall() throws CoreException;
|
||||
|
||||
/**
|
||||
* Returns whether this name is a read-reference to a variable or field.
|
||||
* The notion of a read-reference may not strictly reflect what your compiler generates,
|
||||
* heuristics may be used. <p>
|
||||
* For pointers and arrays the access to the pointer itself is tracked, rather than considering
|
||||
* the target of the pointer.
|
||||
*/
|
||||
public boolean isReadAccess() throws CoreException;
|
||||
|
||||
/**
|
||||
* Returns whether this name is a write-reference to a variable or field.
|
||||
* The notion of a write-reference may not strictly reflect what your compiler generates,
|
||||
* heuristics may be used. <p>
|
||||
* For pointers and arrays the access to the pointer itself is tracked, rather than considering
|
||||
* the target of the pointer.
|
||||
*/
|
||||
public boolean isWriteAccess() throws CoreException;
|
||||
}
|
||||
|
|
|
@ -646,6 +646,9 @@ public class CVisitor {
|
|||
if( binding instanceof IVariable ){
|
||||
return ((IVariable)binding).getType();
|
||||
}
|
||||
else if (binding instanceof IFunction) {
|
||||
return ((IFunction)binding).getType();
|
||||
}
|
||||
} else if( expression instanceof IASTCastExpression ){
|
||||
IASTTypeId id = ((IASTCastExpression)expression).getTypeId();
|
||||
return createType( id.getAbstractDeclarator() );
|
||||
|
|
|
@ -47,12 +47,14 @@ public final class PDOMName implements IIndexFragmentName, IASTFileLocation {
|
|||
|
||||
private static final int RECORD_SIZE = 30; // 30 yields a 32-byte block. (31 would trigger a 40-byte block)
|
||||
|
||||
public static final int IS_DECLARATION = 1;
|
||||
public static final int IS_DEFINITION = 2;
|
||||
public static final int IS_REFERENCE = 3;
|
||||
public static final int DECL_DEF_REF_MASK= 3;
|
||||
public static final int IS_INHERITANCE_SPEC = 4;
|
||||
public static final int COULD_BE_POLYMORPHIC_METHOD_CALL= 8;
|
||||
public static final int IS_DECLARATION = 0x01;
|
||||
public static final int IS_DEFINITION = 0x02;
|
||||
public static final int IS_REFERENCE = IS_DECLARATION | IS_DEFINITION;
|
||||
public static final int DECL_DEF_REF_MASK = IS_DECLARATION | IS_DEFINITION | IS_REFERENCE;
|
||||
public static final int IS_INHERITANCE_SPEC = 0x04;
|
||||
public static final int COULD_BE_POLYMORPHIC_METHOD_CALL = 0x08;
|
||||
public static final int READ_ACCESS = 0x10;
|
||||
public static final int WRITE_ACCESS = 0x20;
|
||||
|
||||
|
||||
|
||||
|
@ -221,6 +223,14 @@ public final class PDOMName implements IIndexFragmentName, IASTFileLocation {
|
|||
return getFlags(COULD_BE_POLYMORPHIC_METHOD_CALL) == COULD_BE_POLYMORPHIC_METHOD_CALL;
|
||||
}
|
||||
|
||||
public boolean isReadAccess() throws CoreException {
|
||||
return getFlags(READ_ACCESS) == READ_ACCESS;
|
||||
}
|
||||
|
||||
public boolean isWriteAccess() throws CoreException {
|
||||
return getFlags(WRITE_ACCESS) == WRITE_ACCESS;
|
||||
}
|
||||
|
||||
public boolean isDeclaration() {
|
||||
try {
|
||||
int flags = getFlags(DECL_DEF_REF_MASK);
|
||||
|
|
|
@ -0,0 +1,323 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2007 Wind River Systems, Inc. and others.
|
||||
* 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:
|
||||
* Markus Schorn - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.internal.core.pdom.dom;
|
||||
|
||||
import org.eclipse.cdt.core.dom.ast.DOMException;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTArrayModifier;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTArraySubscriptExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTCaseStatement;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTCastExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTCompoundStatement;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTConditionalExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTDoStatement;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTExpressionList;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTExpressionStatement;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTFieldReference;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTForStatement;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTIdExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTIfStatement;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTInitializerExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTProblemExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTProblemStatement;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTReturnStatement;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTStatement;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTSwitchStatement;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTWhileStatement;
|
||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||
import org.eclipse.cdt.core.dom.ast.IFunctionType;
|
||||
import org.eclipse.cdt.core.dom.ast.IType;
|
||||
import org.eclipse.cdt.core.dom.ast.IVariable;
|
||||
import org.eclipse.cdt.core.dom.ast.gnu.IGNUASTCompoundStatementExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.gnu.IGNUASTUnaryExpression;
|
||||
|
||||
/**
|
||||
* Helper class to determine whether a variable is accessed for reading and/or writing.
|
||||
* The algorithm works starting from the variable and looking upwards what's being done
|
||||
* with the variable. C- and C++ specific things are handled in sub-classes.
|
||||
*/
|
||||
public abstract class VariableReadWriteFlags {
|
||||
protected static final int READ = PDOMName.READ_ACCESS;
|
||||
protected static final int WRITE = PDOMName.WRITE_ACCESS;
|
||||
|
||||
protected VariableReadWriteFlags() {
|
||||
}
|
||||
|
||||
protected int rwAnyNode(IASTNode node, int indirection) {
|
||||
final IASTNode parent= node.getParent();
|
||||
if (parent instanceof IASTExpression) {
|
||||
return rwInExpression(node, (IASTExpression) parent, indirection);
|
||||
}
|
||||
else if (parent instanceof IASTStatement) {
|
||||
return rwInStatement(node, (IASTStatement) parent, indirection);
|
||||
}
|
||||
else if (parent instanceof IASTInitializerExpression) {
|
||||
return rwInInitializerExpression(indirection, parent);
|
||||
}
|
||||
else if (parent instanceof IASTArrayModifier) {
|
||||
return READ; // dimension
|
||||
}
|
||||
return READ | WRITE; // fallback
|
||||
}
|
||||
|
||||
protected int rwInInitializerExpression(int indirection, IASTNode parent) {
|
||||
try {
|
||||
IASTNode grand= parent.getParent();
|
||||
if (grand instanceof IASTDeclarator) {
|
||||
IBinding binding= ((IASTDeclarator) grand).getName().getBinding();
|
||||
if (binding instanceof IVariable) {
|
||||
return rwAssignmentToType(((IVariable) binding).getType(), indirection);
|
||||
}
|
||||
}
|
||||
} catch (DOMException e) {
|
||||
}
|
||||
return READ | WRITE; // fallback
|
||||
}
|
||||
|
||||
protected int rwInExpression(IASTNode node, IASTExpression expr, int indirection) {
|
||||
if (expr instanceof IASTBinaryExpression) {
|
||||
return rwInBinaryExpression(node, (IASTBinaryExpression) expr, indirection);
|
||||
}
|
||||
if (expr instanceof IASTUnaryExpression) {
|
||||
return rwInUnaryExpression(node, (IASTUnaryExpression) expr, indirection);
|
||||
}
|
||||
if (expr instanceof IASTArraySubscriptExpression) {
|
||||
if (indirection > 0 && node.getPropertyInParent() == IASTArraySubscriptExpression.ARRAY) {
|
||||
return rwAnyNode(expr, indirection-1);
|
||||
}
|
||||
return READ;
|
||||
}
|
||||
if (expr instanceof IASTCastExpression) {
|
||||
return rwAnyNode(expr, indirection);
|
||||
}
|
||||
if (expr instanceof IASTConditionalExpression) {
|
||||
if (node.getPropertyInParent() == IASTConditionalExpression.LOGICAL_CONDITION) {
|
||||
return READ;
|
||||
}
|
||||
return rwAnyNode(expr, indirection);
|
||||
}
|
||||
if (expr instanceof IASTExpressionList) {
|
||||
final IASTExpressionList exprList = (IASTExpressionList)expr;
|
||||
final IASTNode grand= expr.getParent();
|
||||
if (grand instanceof IASTFunctionCallExpression && expr.getPropertyInParent() == IASTFunctionCallExpression.PARAMETERS) {
|
||||
final IASTFunctionCallExpression funcCall = (IASTFunctionCallExpression) grand;
|
||||
return rwArgumentForFunctionCall(node, exprList, funcCall, indirection);
|
||||
}
|
||||
// only the first expression is passed on.
|
||||
final IASTExpression[] expressions = exprList.getExpressions();
|
||||
if (expressions.length > 0 && expressions[0] == node) {
|
||||
return rwAnyNode(expr, indirection);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (expr instanceof IASTFieldReference) {
|
||||
if (node.getPropertyInParent() == IASTFieldReference.FIELD_NAME) {
|
||||
return rwAnyNode(expr, indirection);
|
||||
}
|
||||
return READ;
|
||||
}
|
||||
if (expr instanceof IASTFunctionCallExpression) {
|
||||
if (node.getPropertyInParent() == IASTFunctionCallExpression.FUNCTION_NAME) {
|
||||
return READ;
|
||||
}
|
||||
return rwArgumentForFunctionCall((IASTFunctionCallExpression) expr, 0, indirection);
|
||||
}
|
||||
if (expr instanceof IASTIdExpression) {
|
||||
return rwAnyNode(expr, indirection);
|
||||
}
|
||||
if (expr instanceof IASTProblemExpression) {
|
||||
return READ | WRITE;
|
||||
}
|
||||
if (expr instanceof IASTTypeIdExpression) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return READ | WRITE; // fall back
|
||||
}
|
||||
|
||||
protected int rwArgumentForFunctionCall(IASTNode node, final IASTExpressionList exprList,
|
||||
final IASTFunctionCallExpression funcCall, int indirection) {
|
||||
final IASTExpression[] expressions = exprList.getExpressions();
|
||||
for (int i = 0; i < expressions.length; i++) {
|
||||
if (expressions[i] == node) {
|
||||
return rwArgumentForFunctionCall(funcCall, i, indirection);
|
||||
}
|
||||
}
|
||||
return READ | WRITE;// fallback
|
||||
}
|
||||
|
||||
protected int rwArgumentForFunctionCall(final IASTFunctionCallExpression func, int parameterIdx, int indirection) {
|
||||
try {
|
||||
final IASTExpression functionNameExpression = func.getFunctionNameExpression();
|
||||
if (functionNameExpression != null) {
|
||||
final IType type= functionNameExpression.getExpressionType();
|
||||
if (type instanceof IFunctionType) {
|
||||
IType[] ptypes= ((IFunctionType) type).getParameterTypes();
|
||||
if (ptypes != null && ptypes.length > parameterIdx) {
|
||||
return rwAssignmentToType(ptypes[parameterIdx], indirection);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (DOMException e) {
|
||||
}
|
||||
return READ | WRITE; // fallback
|
||||
}
|
||||
|
||||
protected abstract int rwAssignmentToType(IType type, int indirection);
|
||||
|
||||
protected int rwInStatement(IASTNode node, IASTStatement stmt, int indirection) {
|
||||
if (stmt instanceof IASTCaseStatement) {
|
||||
if (node.getPropertyInParent() == IASTCaseStatement.EXPRESSION) {
|
||||
return READ;
|
||||
}
|
||||
}
|
||||
else if (stmt instanceof IASTDoStatement) {
|
||||
if (node.getPropertyInParent() == IASTDoStatement.CONDITION) {
|
||||
return READ;
|
||||
}
|
||||
}
|
||||
else if (stmt instanceof IASTExpressionStatement) {
|
||||
IASTNode parent= stmt.getParent();
|
||||
while (parent instanceof IASTCompoundStatement) {
|
||||
IASTCompoundStatement compound= (IASTCompoundStatement) parent;
|
||||
IASTStatement[] statements= compound.getStatements();
|
||||
if (statements[statements.length-1] != stmt) {
|
||||
return 0;
|
||||
}
|
||||
stmt= compound;
|
||||
parent= stmt.getParent();
|
||||
}
|
||||
if (parent instanceof IGNUASTCompoundStatementExpression) {
|
||||
return rwAnyNode(parent, indirection);
|
||||
}
|
||||
}
|
||||
else if (stmt instanceof IASTForStatement) {
|
||||
if (node.getPropertyInParent() == IASTForStatement.CONDITION) {
|
||||
return READ;
|
||||
}
|
||||
}
|
||||
else if (stmt instanceof IASTIfStatement) {
|
||||
if (node.getPropertyInParent() == IASTIfStatement.CONDITION) {
|
||||
return READ;
|
||||
}
|
||||
}
|
||||
else if (stmt instanceof IASTProblemStatement) {
|
||||
return READ | WRITE;
|
||||
}
|
||||
else if (stmt instanceof IASTReturnStatement) {
|
||||
return indirection == 0 ? READ : WRITE;
|
||||
}
|
||||
else if (stmt instanceof IASTSwitchStatement) {
|
||||
if (node.getPropertyInParent() == IASTSwitchStatement.CONTROLLER_EXP) {
|
||||
return READ;
|
||||
}
|
||||
}
|
||||
else if (stmt instanceof IASTWhileStatement) {
|
||||
if (node.getPropertyInParent() == IASTWhileStatement.CONDITIONEXPRESSION) {
|
||||
return READ;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected int rwInUnaryExpression(IASTNode node, IASTUnaryExpression expr, int indirection) {
|
||||
switch(expr.getOperator()) {
|
||||
case IASTUnaryExpression.op_bracketedPrimary:
|
||||
return rwAnyNode(expr, indirection);
|
||||
|
||||
case IASTUnaryExpression.op_amper:
|
||||
return rwAnyNode(expr, indirection+1);
|
||||
|
||||
case IASTUnaryExpression.op_star:
|
||||
if (indirection > 0) {
|
||||
return rwAnyNode(expr, indirection-1);
|
||||
}
|
||||
return READ;
|
||||
|
||||
case IASTUnaryExpression.op_postFixDecr:
|
||||
case IASTUnaryExpression.op_postFixIncr:
|
||||
case IASTUnaryExpression.op_prefixDecr:
|
||||
case IASTUnaryExpression.op_prefixIncr:
|
||||
return READ | WRITE;
|
||||
|
||||
case IASTUnaryExpression.op_minus:
|
||||
case IASTUnaryExpression.op_not:
|
||||
case IASTUnaryExpression.op_plus:
|
||||
case IASTUnaryExpression.op_tilde:
|
||||
return PDOMName.READ_ACCESS;
|
||||
|
||||
case IASTUnaryExpression.op_sizeof:
|
||||
case IGNUASTUnaryExpression.op_alignOf:
|
||||
case IGNUASTUnaryExpression.op_typeof:
|
||||
return 0;
|
||||
}
|
||||
return READ;
|
||||
}
|
||||
|
||||
protected int rwInBinaryExpression(IASTNode node, IASTBinaryExpression expr, int indirection) {
|
||||
switch(expr.getOperator()) {
|
||||
case IASTBinaryExpression.op_assign:
|
||||
if (node.getPropertyInParent() == IASTBinaryExpression.OPERAND_ONE) {
|
||||
return WRITE;
|
||||
}
|
||||
return rwAssignmentToType(expr.getOperand1().getExpressionType(), indirection);
|
||||
|
||||
case IASTBinaryExpression.op_binaryAndAssign:
|
||||
case IASTBinaryExpression.op_binaryOrAssign:
|
||||
case IASTBinaryExpression.op_binaryXorAssign:
|
||||
case IASTBinaryExpression.op_divideAssign:
|
||||
case IASTBinaryExpression.op_minusAssign:
|
||||
case IASTBinaryExpression.op_moduloAssign:
|
||||
case IASTBinaryExpression.op_multiplyAssign:
|
||||
case IASTBinaryExpression.op_plusAssign:
|
||||
case IASTBinaryExpression.op_shiftLeftAssign:
|
||||
case IASTBinaryExpression.op_shiftRightAssign:
|
||||
if (node.getPropertyInParent() == IASTBinaryExpression.OPERAND_ONE) {
|
||||
return READ | WRITE;
|
||||
}
|
||||
return READ;
|
||||
|
||||
case IASTBinaryExpression.op_binaryAnd:
|
||||
case IASTBinaryExpression.op_binaryOr:
|
||||
case IASTBinaryExpression.op_binaryXor:
|
||||
case IASTBinaryExpression.op_divide:
|
||||
case IASTBinaryExpression.op_equals:
|
||||
case IASTBinaryExpression.op_greaterEqual:
|
||||
case IASTBinaryExpression.op_greaterThan:
|
||||
case IASTBinaryExpression.op_lessEqual:
|
||||
case IASTBinaryExpression.op_lessThan:
|
||||
case IASTBinaryExpression.op_logicalAnd:
|
||||
case IASTBinaryExpression.op_logicalOr:
|
||||
case IASTBinaryExpression.op_modulo:
|
||||
case IASTBinaryExpression.op_multiply:
|
||||
case IASTBinaryExpression.op_notequals:
|
||||
case IASTBinaryExpression.op_shiftLeft:
|
||||
case IASTBinaryExpression.op_shiftRight:
|
||||
return READ;
|
||||
|
||||
case IASTBinaryExpression.op_minus:
|
||||
case IASTBinaryExpression.op_plus:
|
||||
if (indirection > 0) {
|
||||
// can be pointer arithmetics
|
||||
return rwAnyNode(expr, indirection);
|
||||
}
|
||||
return READ;
|
||||
}
|
||||
return READ; // fallback
|
||||
}
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2007 Wind River Systems, Inc. and others.
|
||||
* 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:
|
||||
* Markus Schorn - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.internal.core.pdom.dom.c;
|
||||
|
||||
import org.eclipse.cdt.core.dom.ast.DOMException;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTExpressionList;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTName;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||
import org.eclipse.cdt.core.dom.ast.IPointerType;
|
||||
import org.eclipse.cdt.core.dom.ast.IQualifierType;
|
||||
import org.eclipse.cdt.core.dom.ast.IType;
|
||||
import org.eclipse.cdt.core.dom.ast.c.ICASTFieldDesignator;
|
||||
import org.eclipse.cdt.core.dom.ast.c.ICASTTypeIdInitializerExpression;
|
||||
import org.eclipse.cdt.internal.core.pdom.dom.VariableReadWriteFlags;
|
||||
|
||||
/**
|
||||
* Helper class to determine whether a variable is accessed for reading and/or writing.
|
||||
* The algorithm works starting from the variable and looking upwards what's being done
|
||||
* with the variable.
|
||||
*/
|
||||
final class CVariableReadWriteFlags extends VariableReadWriteFlags {
|
||||
|
||||
private static CVariableReadWriteFlags INSTANCE= new CVariableReadWriteFlags();
|
||||
|
||||
public static int getReadWriteFlags(IASTName variable) {
|
||||
return INSTANCE.rwAnyNode(variable, 0);
|
||||
}
|
||||
|
||||
protected int rwAnyNode(IASTNode node, int indirection) {
|
||||
final IASTNode parent= node.getParent();
|
||||
if (parent instanceof ICASTFieldDesignator) {
|
||||
return WRITE; // node is initialized via designated initializer
|
||||
}
|
||||
return super.rwAnyNode(node, indirection);
|
||||
}
|
||||
|
||||
protected int rwInExpression(IASTNode node, IASTExpression expr, int indirection) {
|
||||
if (expr instanceof ICASTTypeIdInitializerExpression) {
|
||||
return 0;
|
||||
}
|
||||
return super.rwInExpression(node, expr, indirection);
|
||||
}
|
||||
|
||||
protected int rwInInitializerExpression(int indirection, IASTNode parent) {
|
||||
if (indirection == 0) {
|
||||
return READ;
|
||||
}
|
||||
return super.rwInInitializerExpression(indirection, parent);
|
||||
}
|
||||
|
||||
protected int rwArgumentForFunctionCall(IASTFunctionCallExpression func, int parameterIdx,int indirection) {
|
||||
if (indirection == 0) {
|
||||
return READ;
|
||||
}
|
||||
return super.rwArgumentForFunctionCall(func, parameterIdx, indirection);
|
||||
}
|
||||
|
||||
protected int rwArgumentForFunctionCall(IASTNode node, IASTExpressionList exprList, IASTFunctionCallExpression funcCall, int indirection) {
|
||||
if (indirection == 0) {
|
||||
return READ;
|
||||
}
|
||||
return super.rwArgumentForFunctionCall(node, exprList, funcCall, indirection);
|
||||
}
|
||||
|
||||
protected int rwAssignmentToType(IType type, int indirection) {
|
||||
if (indirection == 0) {
|
||||
return READ;
|
||||
}
|
||||
try {
|
||||
while(indirection > 0 && (type instanceof IPointerType)) {
|
||||
type= ((IPointerType) type).getType();
|
||||
indirection--;
|
||||
}
|
||||
if (indirection == 0) {
|
||||
if (type instanceof IQualifierType) {
|
||||
return ((IQualifierType) type).isConst() ? READ : READ | WRITE;
|
||||
}
|
||||
else if (type instanceof IPointerType) {
|
||||
return ((IPointerType) type).isConst() ? READ : READ | WRITE;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (DOMException e) {
|
||||
}
|
||||
return READ | WRITE; // fallback
|
||||
}
|
||||
}
|
|
@ -15,13 +15,16 @@ package org.eclipse.cdt.internal.core.pdom.dom.c;
|
|||
|
||||
import org.eclipse.cdt.core.CCorePlugin;
|
||||
import org.eclipse.cdt.core.dom.ast.DOMException;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTName;
|
||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||
import org.eclipse.cdt.core.dom.ast.IType;
|
||||
import org.eclipse.cdt.core.dom.ast.IVariable;
|
||||
import org.eclipse.cdt.internal.core.Util;
|
||||
import org.eclipse.cdt.internal.core.index.IIndexCBindingConstants;
|
||||
import org.eclipse.cdt.internal.core.pdom.PDOM;
|
||||
import org.eclipse.cdt.internal.core.pdom.dom.PDOMBinding;
|
||||
import org.eclipse.cdt.internal.core.pdom.dom.PDOMLinkage;
|
||||
import org.eclipse.cdt.internal.core.pdom.dom.PDOMName;
|
||||
import org.eclipse.cdt.internal.core.pdom.dom.PDOMNode;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
|
||||
|
@ -90,7 +93,7 @@ class PDOMCVariable extends PDOMBinding implements IVariable {
|
|||
}
|
||||
|
||||
public int getNodeType() {
|
||||
return PDOMCLinkage.CVARIABLE;
|
||||
return IIndexCBindingConstants.CVARIABLE;
|
||||
}
|
||||
|
||||
public IType getType() {
|
||||
|
@ -118,4 +121,11 @@ class PDOMCVariable extends PDOMBinding implements IVariable {
|
|||
public boolean isRegister() throws DOMException {
|
||||
return getBit(getByte(record + ANNOTATIONS), PDOMCAnnotation.REGISTER_OFFSET);
|
||||
}
|
||||
|
||||
public int getAdditionalNameFlags(int standardFlags, IASTName name) {
|
||||
if ((standardFlags & PDOMName.IS_REFERENCE) == PDOMName.IS_REFERENCE) {
|
||||
return CVariableReadWriteFlags.getReadWriteFlags(name);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2007 Wind River Systems, Inc. and others.
|
||||
* 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:
|
||||
* Markus Schorn - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.internal.core.pdom.dom.cpp;
|
||||
|
||||
import org.eclipse.cdt.core.dom.ast.DOMException;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTName;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IPointerType;
|
||||
import org.eclipse.cdt.core.dom.ast.IQualifierType;
|
||||
import org.eclipse.cdt.core.dom.ast.IType;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUnaryExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.ITypeContainer;
|
||||
import org.eclipse.cdt.internal.core.pdom.dom.VariableReadWriteFlags;
|
||||
|
||||
/**
|
||||
* Helper class to determine whether a variable is accessed for reading and/or writing.
|
||||
* The algorithm works starting from the variable and looking upwards what's being done
|
||||
* with the variable.
|
||||
*/
|
||||
final class CPPVariableReadWriteFlags extends VariableReadWriteFlags {
|
||||
|
||||
private static CPPVariableReadWriteFlags INSTANCE= new CPPVariableReadWriteFlags();
|
||||
|
||||
public static int getReadWriteFlags(IASTName variable) {
|
||||
return INSTANCE.rwAnyNode(variable, 0);
|
||||
}
|
||||
|
||||
protected int rwInUnaryExpression(IASTNode node, IASTUnaryExpression expr, int indirection) {
|
||||
switch (expr.getOperator()) {
|
||||
case ICPPASTUnaryExpression.op_typeid:
|
||||
return 0;
|
||||
}
|
||||
return super.rwInUnaryExpression(node, expr, indirection);
|
||||
}
|
||||
|
||||
protected int rwAssignmentToType(IType type, int indirection) {
|
||||
if (indirection == 0) {
|
||||
if (!(type instanceof ICPPReferenceType)) {
|
||||
return READ;
|
||||
}
|
||||
try {
|
||||
type= ((ICPPReferenceType) type).getType();
|
||||
}
|
||||
catch (DOMException e) {
|
||||
return READ; // fallback
|
||||
}
|
||||
}
|
||||
try {
|
||||
while(indirection > 0 && (type instanceof ITypeContainer)) {
|
||||
if (type instanceof IPointerType) {
|
||||
indirection--;
|
||||
}
|
||||
type= ((ITypeContainer) type).getType();
|
||||
}
|
||||
if (indirection == 0) {
|
||||
if (type instanceof IQualifierType) {
|
||||
return ((IQualifierType) type).isConst() ? READ : READ | WRITE;
|
||||
}
|
||||
else if (type instanceof IPointerType) {
|
||||
return ((IPointerType) type).isConst() ? READ : READ | WRITE;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (DOMException e) {
|
||||
}
|
||||
return READ | WRITE; // fallback
|
||||
}
|
||||
}
|
|
@ -28,6 +28,7 @@ import org.eclipse.cdt.internal.core.pdom.PDOM;
|
|||
import org.eclipse.cdt.internal.core.pdom.db.Database;
|
||||
import org.eclipse.cdt.internal.core.pdom.dom.PDOMBinding;
|
||||
import org.eclipse.cdt.internal.core.pdom.dom.PDOMLinkage;
|
||||
import org.eclipse.cdt.internal.core.pdom.dom.PDOMName;
|
||||
import org.eclipse.cdt.internal.core.pdom.dom.PDOMNode;
|
||||
import org.eclipse.cdt.internal.core.pdom.dom.c.PDOMCAnnotation;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
|
@ -145,4 +146,11 @@ class PDOMCPPVariable extends PDOMCPPBinding implements ICPPVariable, ICPPDelega
|
|||
public ICPPDelegate createDelegate(IASTName name) {
|
||||
return new CPPVariable.CPPVariableDelegate(name, this);
|
||||
}
|
||||
|
||||
public int getAdditionalNameFlags(int standardFlags, IASTName name) {
|
||||
if ((standardFlags & PDOMName.IS_REFERENCE) == PDOMName.IS_REFERENCE) {
|
||||
return CPPVariableReadWriteFlags.getReadWriteFlags(name);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue