diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexNamesTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexNamesTests.java index 4468eb80d1e..b089bbf2efb 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexNamesTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexNamesTests.java @@ -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); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndexName.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndexName.java index 804a6efb415..7a9673dcaa9 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndexName.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndexName.java @@ -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.
+ * 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.
+ * 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; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CVisitor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CVisitor.java index 705598926bd..79ab33bf59a 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CVisitor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CVisitor.java @@ -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() ); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMName.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMName.java index 29032973c2d..d8454d36b87 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMName.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMName.java @@ -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); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/VariableReadWriteFlags.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/VariableReadWriteFlags.java new file mode 100644 index 00000000000..d45d0083fe7 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/VariableReadWriteFlags.java @@ -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 + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/c/CVariableReadWriteFlags.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/c/CVariableReadWriteFlags.java new file mode 100644 index 00000000000..134a1148cd4 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/c/CVariableReadWriteFlags.java @@ -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 + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/c/PDOMCVariable.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/c/PDOMCVariable.java index 2125129c564..71e5b3c6038 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/c/PDOMCVariable.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/c/PDOMCVariable.java @@ -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; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/CPPVariableReadWriteFlags.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/CPPVariableReadWriteFlags.java new file mode 100644 index 00000000000..c68029c4bde --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/CPPVariableReadWriteFlags.java @@ -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 + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPVariable.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPVariable.java index d983c7fd773..8265eda8cd8 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPVariable.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPVariable.java @@ -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; + } }