mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-24 01:15:29 +02:00
Bug 561088 - Fix read/write flags in case of dependent types
Change-Id: I072bb53a95d17137eb614bff34de6bd57a371d33
This commit is contained in:
parent
c69bec4979
commit
7a833fbb50
11 changed files with 301 additions and 118 deletions
|
@ -17,6 +17,7 @@
|
|||
package org.eclipse.cdt.codan.internal.checkers;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.Stack;
|
||||
|
||||
|
@ -59,7 +60,6 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPDeferredClassInstance;
|
|||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVariableReadWriteFlags;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
|
||||
import org.eclipse.cdt.internal.core.pdom.dom.PDOMName;
|
||||
|
||||
/**
|
||||
* Checks that class members of simple types (int, float, pointers,
|
||||
|
@ -212,7 +212,8 @@ public class ClassMembersInitializationChecker extends AbstractIndexAstChecker {
|
|||
IField equivalentFieldBinding = getContainedEquivalentBinding(actualConstructorFields, binding,
|
||||
name.getTranslationUnit().getIndex());
|
||||
if (equivalentFieldBinding != null) {
|
||||
if ((CPPVariableReadWriteFlags.getReadWriteFlags(name) & PDOMName.WRITE_ACCESS) != 0) {
|
||||
Optional<Integer> res = CPPVariableReadWriteFlags.getReadWriteFlags(name);
|
||||
if (CPPVariableReadWriteFlags.mayBeWriteAccess(res)) {
|
||||
actualConstructorFields.remove(equivalentFieldBinding);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
package org.eclipse.cdt.core.parser.tests.ast2;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.eclipse.cdt.core.dom.ast.IASTName;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.c.CVariableReadWriteFlags;
|
||||
|
@ -35,27 +36,34 @@ public class VariableReadWriteFlagsTest extends AST2TestBase {
|
|||
super(contents, isCPP);
|
||||
}
|
||||
|
||||
void assertReadWriteFlags(String context, String name, int expectedFlags) throws Exception {
|
||||
void assertReadWriteFlags(String context, String name, Optional<Integer> expectedFlags) throws Exception {
|
||||
IASTName variable = findName(context, name);
|
||||
assertNotNull(variable);
|
||||
assertEquals(flagsToString(expectedFlags), flagsToString(getReadWriteFlags(variable)));
|
||||
}
|
||||
|
||||
void assertReadWriteFlags(String name, int expectedFlags) throws Exception {
|
||||
assertReadWriteFlags(null, name, expectedFlags);
|
||||
void assertReadWriteFlags(String context, String name, int expectedFlags) throws Exception {
|
||||
assertReadWriteFlags(context, name, Optional.of(expectedFlags));
|
||||
}
|
||||
|
||||
int getReadWriteFlags(IASTName variable) {
|
||||
void assertReadWriteFlags(String context, String name) throws Exception {
|
||||
assertReadWriteFlags(context, name, Optional.empty());
|
||||
}
|
||||
|
||||
Optional<Integer> getReadWriteFlags(IASTName variable) {
|
||||
return isCPP ? CPPVariableReadWriteFlags.getReadWriteFlags(variable)
|
||||
: CVariableReadWriteFlags.getReadWriteFlags(variable);
|
||||
}
|
||||
|
||||
private String flagsToString(int flags) {
|
||||
private String flagsToString(Optional<Integer> flags) {
|
||||
StringBuilder buf = new StringBuilder();
|
||||
if ((flags & READ) != 0) {
|
||||
if (!flags.isPresent()) {
|
||||
buf.append("UNK");
|
||||
}
|
||||
if (flags.isPresent() && (flags.get() & READ) != 0) {
|
||||
buf.append("READ");
|
||||
}
|
||||
if ((flags & WRITE) != 0) {
|
||||
if (flags.isPresent() && (flags.get() & WRITE) != 0) {
|
||||
if (buf.length() != 0)
|
||||
buf.append(" | ");
|
||||
buf.append("WRITE");
|
||||
|
@ -153,8 +161,8 @@ public class VariableReadWriteFlagsTest extends AST2TestBase {
|
|||
// };
|
||||
public void testFunctionCall() throws Exception {
|
||||
AssertionHelper a = getCPPAssertionHelper();
|
||||
a.assertReadWriteFlags("f(&a, b)", "a", READ | WRITE);
|
||||
a.assertReadWriteFlags("f(&a, b)", "b", READ | WRITE);
|
||||
a.assertReadWriteFlags("f(&a, b)", "a");
|
||||
a.assertReadWriteFlags("f(&a, b)", "b");
|
||||
a.assertReadWriteFlags("f(&a, b)", "f", READ);
|
||||
a.assertReadWriteFlags("g(&a, b, c)", "a", READ);
|
||||
a.assertReadWriteFlags("g(&a, b, c)", "b", READ);
|
||||
|
@ -176,12 +184,12 @@ public class VariableReadWriteFlagsTest extends AST2TestBase {
|
|||
// };
|
||||
public void testConstructorCall_393068() throws Exception {
|
||||
AssertionHelper a = getCPPAssertionHelper();
|
||||
a.assertReadWriteFlags("= A(&a, b)", "a", READ | WRITE);
|
||||
a.assertReadWriteFlags("= A(&a, b)", "b", READ | WRITE);
|
||||
a.assertReadWriteFlags("new A(&a, b)", "a", READ | WRITE);
|
||||
a.assertReadWriteFlags("new A(&a, b)", "b", READ | WRITE);
|
||||
a.assertReadWriteFlags("w(&a, b)", "a", READ | WRITE);
|
||||
a.assertReadWriteFlags("w(&a, b)", "b", READ | WRITE);
|
||||
a.assertReadWriteFlags("= A(&a, b)", "a");
|
||||
a.assertReadWriteFlags("= A(&a, b)", "b");
|
||||
a.assertReadWriteFlags("new A(&a, b)", "a");
|
||||
a.assertReadWriteFlags("new A(&a, b)", "b");
|
||||
a.assertReadWriteFlags("w(&a, b)", "a");
|
||||
a.assertReadWriteFlags("w(&a, b)", "b");
|
||||
a.assertReadWriteFlags("w(&a, b)", "w", WRITE);
|
||||
a.assertReadWriteFlags("= A(&a, b, c)", "a", READ);
|
||||
a.assertReadWriteFlags("= A(&a, b, c)", "b", READ);
|
||||
|
@ -227,7 +235,7 @@ public class VariableReadWriteFlagsTest extends AST2TestBase {
|
|||
public void testVariadicFunctionCall_452416() throws Exception {
|
||||
AssertionHelper a = getCPPAssertionHelper();
|
||||
a.assertReadWriteFlags("variadic(waldo)", "waldo", READ);
|
||||
a.assertReadWriteFlags("variadic(&waldo)", "waldo", READ | WRITE);
|
||||
a.assertReadWriteFlags("variadic(&waldo)", "waldo");
|
||||
}
|
||||
|
||||
// int arr[5];
|
||||
|
@ -257,4 +265,20 @@ public class VariableReadWriteFlagsTest extends AST2TestBase {
|
|||
AssertionHelper a = getCPPAssertionHelper();
|
||||
a.assertReadWriteFlags("decltype(v) o = 14;", "v", READ);
|
||||
}
|
||||
|
||||
//template <typename S, typename T>
|
||||
//void g(S, T);
|
||||
//
|
||||
//struct A {
|
||||
// int field;
|
||||
//
|
||||
// template <typename S>
|
||||
// void method3(S s) const {
|
||||
// g(s, field);
|
||||
// }
|
||||
//};
|
||||
public void testDependentType() throws Exception {
|
||||
AssertionHelper a = getCPPAssertionHelper();
|
||||
a.assertReadWriteFlags("g(s, field);", "field");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.cdt.internal.core.dom.parser;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.eclipse.cdt.core.dom.ast.IASTArrayModifier;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTArraySubscriptExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression;
|
||||
|
@ -68,7 +70,19 @@ public abstract class VariableReadWriteFlags {
|
|||
protected static final int READ = PDOMName.READ_ACCESS;
|
||||
protected static final int WRITE = PDOMName.WRITE_ACCESS;
|
||||
|
||||
protected int rwAnyNode(IASTNode node, int indirection) {
|
||||
/**
|
||||
* Check if the access could be a write access taking into
|
||||
* account the "unknown" state.
|
||||
* @param flags The flags
|
||||
* @return True if either write or unknown access detected, false otherwise
|
||||
*/
|
||||
public static boolean mayBeWriteAccess(Optional<Integer> flags) {
|
||||
if (!flags.isPresent() || (flags.get() & WRITE) != 0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
protected Optional<Integer> rwAnyNode(IASTNode node, int indirection) {
|
||||
final IASTNode parent = node.getParent();
|
||||
if (parent instanceof IASTExpression) {
|
||||
return rwInExpression((IASTExpression) parent, node, indirection);
|
||||
|
@ -79,22 +93,22 @@ public abstract class VariableReadWriteFlags {
|
|||
} else if (parent instanceof IASTEqualsInitializer) {
|
||||
return rwInEqualsInitializer((IASTEqualsInitializer) parent, indirection);
|
||||
} else if (parent instanceof IASTArrayModifier) {
|
||||
return READ; // dimension
|
||||
return Optional.of(READ); // dimension
|
||||
} else if (parent instanceof IASTInitializerList) {
|
||||
return rwInInitializerList((IASTInitializerList) parent, indirection);
|
||||
} else if (parent instanceof IASTDeclSpecifier) {
|
||||
return READ;
|
||||
return Optional.of(READ);
|
||||
}
|
||||
return READ | WRITE; // fallback
|
||||
return Optional.empty(); // fallback
|
||||
}
|
||||
|
||||
protected int rwInDeclarator(IASTDeclarator parent, int indirection) {
|
||||
protected Optional<Integer> rwInDeclarator(IASTDeclarator parent, int indirection) {
|
||||
if (parent.getInitializer() != null)
|
||||
return WRITE;
|
||||
return 0;
|
||||
return Optional.of(WRITE);
|
||||
return Optional.of(0);
|
||||
}
|
||||
|
||||
protected int rwInEqualsInitializer(IASTEqualsInitializer parent, int indirection) {
|
||||
protected Optional<Integer> rwInEqualsInitializer(IASTEqualsInitializer parent, int indirection) {
|
||||
IASTNode grand = parent.getParent();
|
||||
if (grand instanceof IASTDeclarator) {
|
||||
IBinding binding = ((IASTDeclarator) grand).getName().getBinding();
|
||||
|
@ -104,10 +118,10 @@ public abstract class VariableReadWriteFlags {
|
|||
} else if (grand instanceof ICPPASTStructuredBindingDeclaration) {
|
||||
return rwInStructuredBinding((ICPPASTStructuredBindingDeclaration) grand);
|
||||
}
|
||||
return READ | WRITE; // fallback
|
||||
return Optional.empty(); // fallback
|
||||
}
|
||||
|
||||
protected int rwInInitializerList(IASTInitializerList parent, int indirection) {
|
||||
protected Optional<Integer> rwInInitializerList(IASTInitializerList parent, int indirection) {
|
||||
IASTNode grand = parent.getParent();
|
||||
if (grand instanceof IASTEqualsInitializer) {
|
||||
IASTNode grandGrand = grand.getParent();
|
||||
|
@ -123,15 +137,15 @@ public abstract class VariableReadWriteFlags {
|
|||
} else if (grand instanceof ICPPASTStructuredBindingDeclaration) {
|
||||
return rwInStructuredBinding((ICPPASTStructuredBindingDeclaration) grand);
|
||||
}
|
||||
return READ | WRITE; // fallback
|
||||
return Optional.empty(); // fallback
|
||||
}
|
||||
|
||||
protected int rwInStructuredBinding(ICPPASTStructuredBindingDeclaration declaration) {
|
||||
protected Optional<Integer> rwInStructuredBinding(ICPPASTStructuredBindingDeclaration declaration) {
|
||||
RefQualifier refQualifier = declaration.getRefQualifier();
|
||||
if (refQualifier != null && !declaration.getDeclSpecifier().isConst()) {
|
||||
return READ | WRITE;
|
||||
return Optional.of(READ | WRITE);
|
||||
} else {
|
||||
return READ;
|
||||
return Optional.of(READ);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -153,7 +167,7 @@ public abstract class VariableReadWriteFlags {
|
|||
return false;
|
||||
}
|
||||
|
||||
protected int rwInExpression(IASTExpression expr, IASTNode node, int indirection) {
|
||||
protected Optional<Integer> rwInExpression(IASTExpression expr, IASTNode node, int indirection) {
|
||||
if (expr instanceof IASTIdExpression) {
|
||||
return rwAnyNode(expr, indirection);
|
||||
}
|
||||
|
@ -176,13 +190,13 @@ public abstract class VariableReadWriteFlags {
|
|||
if (expr.getParent() instanceof IASTBinaryExpression
|
||||
&& expr.getPropertyInParent() == IASTBinaryExpression.OPERAND_ONE
|
||||
&& isAssignment((IASTBinaryExpression) expr.getParent())) {
|
||||
return READ | WRITE;
|
||||
return Optional.of(READ | WRITE);
|
||||
}
|
||||
return READ;
|
||||
return Optional.of(READ);
|
||||
}
|
||||
if (expr instanceof IASTConditionalExpression) {
|
||||
if (node.getPropertyInParent() == IASTConditionalExpression.LOGICAL_CONDITION) {
|
||||
return READ;
|
||||
return Optional.of(READ);
|
||||
}
|
||||
return rwAnyNode(expr, indirection);
|
||||
}
|
||||
|
@ -192,7 +206,7 @@ public abstract class VariableReadWriteFlags {
|
|||
if (expressions.length > 0 && expressions[0] == node) {
|
||||
return rwAnyNode(expr, indirection);
|
||||
}
|
||||
return 0;
|
||||
return Optional.of(0);
|
||||
}
|
||||
if (expr instanceof IASTFunctionCallExpression) {
|
||||
if (node.getPropertyInParent() == IASTFunctionCallExpression.FUNCTION_NAME) {
|
||||
|
@ -201,16 +215,16 @@ public abstract class VariableReadWriteFlags {
|
|||
return rwArgumentForFunctionCall((IASTFunctionCallExpression) expr, node, indirection);
|
||||
}
|
||||
if (expr instanceof IASTProblemExpression) {
|
||||
return READ | WRITE;
|
||||
return Optional.of(READ | WRITE);
|
||||
}
|
||||
if (expr instanceof IASTTypeIdExpression) {
|
||||
return 0;
|
||||
return Optional.of(0);
|
||||
}
|
||||
|
||||
return READ | WRITE; // fall back
|
||||
return Optional.empty(); // fall back
|
||||
}
|
||||
|
||||
protected int rwInFieldReference(IASTNode node, IASTFieldReference expr, int indirection) {
|
||||
protected Optional<Integer> rwInFieldReference(IASTNode node, IASTFieldReference expr, int indirection) {
|
||||
if (node.getPropertyInParent() == IASTFieldReference.FIELD_NAME) {
|
||||
if (expr.getPropertyInParent() != IASTFunctionCallExpression.FUNCTION_NAME)
|
||||
return rwAnyNode(expr, indirection);
|
||||
|
@ -220,22 +234,70 @@ public abstract class VariableReadWriteFlags {
|
|||
if (indirection >= 0)
|
||||
return rwAnyNode(expr, indirection);
|
||||
}
|
||||
return READ;
|
||||
return Optional.of(READ);
|
||||
}
|
||||
|
||||
protected int rwInFunctionName(IASTExpression node) {
|
||||
return READ;
|
||||
protected Optional<Integer> rwInFunctionName(IASTExpression node) {
|
||||
return Optional.of(READ);
|
||||
}
|
||||
|
||||
protected int rwArgumentForFunctionCall(final IASTFunctionCallExpression funcCall, IASTNode argument,
|
||||
/**
|
||||
* Check if the function name expression involves a deferred function. Applicable
|
||||
* only to C++.
|
||||
* @param functionNameExpression The expression
|
||||
* @return The binding found, null otherwise
|
||||
*/
|
||||
protected abstract IBinding getDeferredFunction(IASTExpression functionNameExpression);
|
||||
|
||||
/**
|
||||
* Evaluate the deferred function and check the flags for arguments passed. Applicable
|
||||
* only to C++.
|
||||
* @param funcCall The function call expression
|
||||
* @param arg The argument to be evaluated
|
||||
* @param argPos The argument position
|
||||
* @param indirection Level of indirection
|
||||
* @param defFunctionBinding The function binding
|
||||
* @return Access flags
|
||||
*/
|
||||
protected abstract Optional<Integer> evaluateDeferredFunction(final IASTFunctionCallExpression funcCall,
|
||||
final IASTInitializerClause arg, int argPos, int indirection, IBinding defFunctionBinding);
|
||||
|
||||
/**
|
||||
* Helper method to merge two optional flags containers
|
||||
* @param a A flag optional container
|
||||
* @param b A flag optional container
|
||||
* @return An optional with bit or operation between a and b
|
||||
*/
|
||||
protected Optional<Integer> bitwiseOr(Optional<Integer> a, Optional<Integer> b) {
|
||||
Optional<Integer> or = Optional.empty();
|
||||
if (a.isPresent()) {
|
||||
if (!b.isPresent()) {
|
||||
or = a;
|
||||
} else {
|
||||
or = Optional.of(a.get() | b.get());
|
||||
}
|
||||
} else {
|
||||
if (!b.isPresent()) {
|
||||
return or;
|
||||
} else {
|
||||
or = b;
|
||||
}
|
||||
}
|
||||
return or;
|
||||
}
|
||||
|
||||
protected Optional<Integer> rwArgumentForFunctionCall(final IASTFunctionCallExpression funcCall, IASTNode argument,
|
||||
int indirection) {
|
||||
final IASTInitializerClause[] args = funcCall.getArguments();
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
if (args[i] == argument) {
|
||||
final IASTExpression functionNameExpression = funcCall.getFunctionNameExpression();
|
||||
if (functionNameExpression != null) {
|
||||
final IType type = functionNameExpression.getExpressionType();
|
||||
if (type instanceof IFunctionType) {
|
||||
IType type = functionNameExpression.getExpressionType();
|
||||
IBinding deferredFunc = getDeferredFunction(functionNameExpression);
|
||||
if (deferredFunc != null) {
|
||||
return evaluateDeferredFunction(funcCall, args[i], i, indirection, deferredFunc);
|
||||
} else if (type instanceof IFunctionType) {
|
||||
return rwArgumentForFunctionCall((IFunctionType) type, i, args[i], indirection);
|
||||
} else if (funcCall instanceof IASTImplicitNameOwner) {
|
||||
IASTImplicitName[] implicitNames = ((IASTImplicitNameOwner) funcCall).getImplicitNames();
|
||||
|
@ -252,7 +314,7 @@ public abstract class VariableReadWriteFlags {
|
|||
break;
|
||||
}
|
||||
}
|
||||
return READ | WRITE; // Fallback
|
||||
return Optional.empty(); // Fallback
|
||||
}
|
||||
|
||||
private IType getArgumentType(IASTInitializerClause argument) {
|
||||
|
@ -264,8 +326,8 @@ public abstract class VariableReadWriteFlags {
|
|||
return null;
|
||||
}
|
||||
|
||||
protected int rwArgumentForFunctionCall(IFunctionType type, int parameterIdx, IASTInitializerClause argument,
|
||||
int indirection) {
|
||||
protected Optional<Integer> rwArgumentForFunctionCall(IFunctionType type, int parameterIdx,
|
||||
IASTInitializerClause argument, int indirection) {
|
||||
IType[] ptypes = type.getParameterTypes();
|
||||
IType parameterType = null;
|
||||
if (ptypes != null && ptypes.length > parameterIdx) {
|
||||
|
@ -279,19 +341,19 @@ public abstract class VariableReadWriteFlags {
|
|||
if (parameterType != null) {
|
||||
return rwAssignmentToType(parameterType, indirection);
|
||||
}
|
||||
return READ | WRITE; // Fallback
|
||||
return Optional.empty(); // Fallback
|
||||
}
|
||||
|
||||
protected abstract int rwAssignmentToType(IType type, int indirection);
|
||||
protected abstract Optional<Integer> rwAssignmentToType(IType type, int indirection);
|
||||
|
||||
protected int rwInStatement(IASTStatement stmt, IASTNode node, int indirection) {
|
||||
protected Optional<Integer> rwInStatement(IASTStatement stmt, IASTNode node, int indirection) {
|
||||
if (stmt instanceof IASTCaseStatement) {
|
||||
if (node.getPropertyInParent() == IASTCaseStatement.EXPRESSION) {
|
||||
return READ;
|
||||
return Optional.of(READ);
|
||||
}
|
||||
} else if (stmt instanceof IASTDoStatement) {
|
||||
if (node.getPropertyInParent() == IASTDoStatement.CONDITION) {
|
||||
return READ;
|
||||
return Optional.of(READ);
|
||||
}
|
||||
} else if (stmt instanceof IASTExpressionStatement) {
|
||||
IASTNode parent = stmt.getParent();
|
||||
|
@ -299,7 +361,7 @@ public abstract class VariableReadWriteFlags {
|
|||
IASTCompoundStatement compound = (IASTCompoundStatement) parent;
|
||||
IASTStatement[] statements = compound.getStatements();
|
||||
if (statements[statements.length - 1] != stmt) {
|
||||
return 0;
|
||||
return Optional.of(0);
|
||||
}
|
||||
stmt = compound;
|
||||
parent = stmt.getParent();
|
||||
|
@ -309,33 +371,33 @@ public abstract class VariableReadWriteFlags {
|
|||
}
|
||||
} else if (stmt instanceof IASTForStatement) {
|
||||
if (node.getPropertyInParent() == IASTForStatement.CONDITION) {
|
||||
return READ;
|
||||
return Optional.of(READ);
|
||||
}
|
||||
} else if (stmt instanceof ICPPASTRangeBasedForStatement) {
|
||||
if (node.getPropertyInParent() == ICPPASTRangeBasedForStatement.INITIALIZER) {
|
||||
return READ;
|
||||
return Optional.of(READ);
|
||||
}
|
||||
} else if (stmt instanceof IASTIfStatement) {
|
||||
if (node.getPropertyInParent() == IASTIfStatement.CONDITION) {
|
||||
return READ;
|
||||
return Optional.of(READ);
|
||||
}
|
||||
} else if (stmt instanceof IASTProblemStatement) {
|
||||
return READ | WRITE;
|
||||
return Optional.empty();
|
||||
} else if (stmt instanceof IASTReturnStatement) {
|
||||
return indirection == 0 ? READ : WRITE;
|
||||
return indirection == 0 ? Optional.of(READ) : Optional.of(WRITE);
|
||||
} else if (stmt instanceof IASTSwitchStatement) {
|
||||
if (node.getPropertyInParent() == IASTSwitchStatement.CONTROLLER_EXP) {
|
||||
return READ;
|
||||
return Optional.of(READ);
|
||||
}
|
||||
} else if (stmt instanceof IASTWhileStatement) {
|
||||
if (node.getPropertyInParent() == IASTWhileStatement.CONDITIONEXPRESSION) {
|
||||
return READ;
|
||||
return Optional.of(READ);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return Optional.of(0);
|
||||
}
|
||||
|
||||
protected int rwInUnaryExpression(IASTNode node, IASTUnaryExpression expr, int indirection) {
|
||||
protected Optional<Integer> rwInUnaryExpression(IASTNode node, IASTUnaryExpression expr, int indirection) {
|
||||
switch (expr.getOperator()) {
|
||||
case IASTUnaryExpression.op_bracketedPrimary:
|
||||
return rwAnyNode(expr, indirection);
|
||||
|
@ -347,33 +409,33 @@ public abstract class VariableReadWriteFlags {
|
|||
if (indirection > 0) {
|
||||
return rwAnyNode(expr, indirection - 1);
|
||||
}
|
||||
return READ;
|
||||
return Optional.of(READ);
|
||||
|
||||
case IASTUnaryExpression.op_postFixDecr:
|
||||
case IASTUnaryExpression.op_postFixIncr:
|
||||
case IASTUnaryExpression.op_prefixDecr:
|
||||
case IASTUnaryExpression.op_prefixIncr:
|
||||
return READ | WRITE;
|
||||
return Optional.of(READ | WRITE);
|
||||
|
||||
case IASTUnaryExpression.op_minus:
|
||||
case IASTUnaryExpression.op_not:
|
||||
case IASTUnaryExpression.op_plus:
|
||||
case IASTUnaryExpression.op_tilde:
|
||||
return PDOMName.READ_ACCESS;
|
||||
return Optional.of(READ);
|
||||
|
||||
case IASTUnaryExpression.op_sizeof:
|
||||
case IASTUnaryExpression.op_sizeofParameterPack:
|
||||
case IASTUnaryExpression.op_alignOf:
|
||||
return 0;
|
||||
return Optional.of(0);
|
||||
}
|
||||
return READ;
|
||||
return Optional.of(READ);
|
||||
}
|
||||
|
||||
protected int rwInBinaryExpression(IASTNode node, IASTBinaryExpression expr, int indirection) {
|
||||
protected Optional<Integer> rwInBinaryExpression(IASTNode node, IASTBinaryExpression expr, int indirection) {
|
||||
switch (expr.getOperator()) {
|
||||
case IASTBinaryExpression.op_assign:
|
||||
if (node.getPropertyInParent() == IASTBinaryExpression.OPERAND_ONE) {
|
||||
return WRITE;
|
||||
return Optional.of(WRITE);
|
||||
}
|
||||
return rwAssignmentToType(expr.getOperand1().getExpressionType(), indirection);
|
||||
|
||||
|
@ -388,9 +450,9 @@ public abstract class VariableReadWriteFlags {
|
|||
case IASTBinaryExpression.op_shiftLeftAssign:
|
||||
case IASTBinaryExpression.op_shiftRightAssign:
|
||||
if (node.getPropertyInParent() == IASTBinaryExpression.OPERAND_ONE) {
|
||||
return READ | WRITE;
|
||||
return Optional.of(READ | WRITE);
|
||||
}
|
||||
return READ;
|
||||
return Optional.of(READ);
|
||||
|
||||
case IASTBinaryExpression.op_binaryAnd:
|
||||
case IASTBinaryExpression.op_binaryOr:
|
||||
|
@ -408,7 +470,7 @@ public abstract class VariableReadWriteFlags {
|
|||
case IASTBinaryExpression.op_notequals:
|
||||
case IASTBinaryExpression.op_shiftLeft:
|
||||
case IASTBinaryExpression.op_shiftRight:
|
||||
return READ;
|
||||
return Optional.of(READ);
|
||||
|
||||
case IASTBinaryExpression.op_minus:
|
||||
case IASTBinaryExpression.op_plus:
|
||||
|
@ -416,8 +478,8 @@ public abstract class VariableReadWriteFlags {
|
|||
// can be pointer arithmetics
|
||||
return rwAnyNode(expr, indirection);
|
||||
}
|
||||
return READ;
|
||||
return Optional.of(READ);
|
||||
}
|
||||
return READ; // fallback
|
||||
return Optional.of(READ); // fallback
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,11 +13,15 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.cdt.internal.core.dom.parser.c;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.eclipse.cdt.core.dom.ast.IASTEqualsInitializer;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTInitializerClause;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTName;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||
import org.eclipse.cdt.core.dom.ast.IPointerType;
|
||||
import org.eclipse.cdt.core.dom.ast.IQualifierType;
|
||||
import org.eclipse.cdt.core.dom.ast.IType;
|
||||
|
@ -33,47 +37,48 @@ import org.eclipse.cdt.internal.core.dom.parser.VariableReadWriteFlags;
|
|||
public final class CVariableReadWriteFlags extends VariableReadWriteFlags {
|
||||
private static CVariableReadWriteFlags INSTANCE = new CVariableReadWriteFlags();
|
||||
|
||||
public static int getReadWriteFlags(IASTName variable) {
|
||||
public static Optional<Integer> getReadWriteFlags(IASTName variable) {
|
||||
return INSTANCE.rwAnyNode(variable, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int rwAnyNode(IASTNode node, int indirection) {
|
||||
protected Optional<Integer> rwAnyNode(IASTNode node, int indirection) {
|
||||
final IASTNode parent = node.getParent();
|
||||
if (parent instanceof ICASTFieldDesignator) {
|
||||
return WRITE; // node is initialized via designated initializer
|
||||
return Optional.of(WRITE); // node is initialized via designated initializer
|
||||
}
|
||||
return super.rwAnyNode(node, indirection);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int rwInExpression(IASTExpression expr, IASTNode node, int indirection) {
|
||||
protected Optional<Integer> rwInExpression(IASTExpression expr, IASTNode node, int indirection) {
|
||||
if (expr instanceof ICASTTypeIdInitializerExpression) {
|
||||
return 0;
|
||||
return Optional.of(0);
|
||||
}
|
||||
return super.rwInExpression(expr, node, indirection);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int rwInEqualsInitializer(IASTEqualsInitializer parent, int indirection) {
|
||||
protected Optional<Integer> rwInEqualsInitializer(IASTEqualsInitializer parent, int indirection) {
|
||||
if (indirection == 0) {
|
||||
return READ;
|
||||
return Optional.of(READ);
|
||||
}
|
||||
return super.rwInEqualsInitializer(parent, indirection);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int rwArgumentForFunctionCall(IASTFunctionCallExpression funcCall, IASTNode argument, int indirection) {
|
||||
protected Optional<Integer> rwArgumentForFunctionCall(IASTFunctionCallExpression funcCall, IASTNode argument,
|
||||
int indirection) {
|
||||
if (indirection == 0) {
|
||||
return READ;
|
||||
return Optional.of(READ);
|
||||
}
|
||||
return super.rwArgumentForFunctionCall(funcCall, argument, indirection);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int rwAssignmentToType(IType type, int indirection) {
|
||||
protected Optional<Integer> rwAssignmentToType(IType type, int indirection) {
|
||||
if (indirection == 0) {
|
||||
return READ;
|
||||
return Optional.of(READ);
|
||||
}
|
||||
while (indirection > 0 && (type instanceof IPointerType)) {
|
||||
type = ((IPointerType) type).getType();
|
||||
|
@ -81,11 +86,22 @@ public final class CVariableReadWriteFlags extends VariableReadWriteFlags {
|
|||
}
|
||||
if (indirection == 0) {
|
||||
if (type instanceof IQualifierType) {
|
||||
return ((IQualifierType) type).isConst() ? READ : READ | WRITE;
|
||||
return ((IQualifierType) type).isConst() ? Optional.of(READ) : Optional.of(READ | WRITE);
|
||||
} else if (type instanceof IPointerType) {
|
||||
return ((IPointerType) type).isConst() ? READ : READ | WRITE;
|
||||
return ((IPointerType) type).isConst() ? Optional.of(READ) : Optional.of(READ | WRITE);
|
||||
}
|
||||
}
|
||||
return READ | WRITE; // fallback
|
||||
return Optional.empty(); // Fallback
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IBinding getDeferredFunction(IASTExpression functionNameExpression) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Optional<Integer> evaluateDeferredFunction(final IASTFunctionCallExpression funcCall,
|
||||
final IASTInitializerClause arg, int argPos, int indirection, IBinding defFunctionBinding) {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,8 +15,11 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
|
||||
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.IASTImplicitName;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTImplicitNameOwner;
|
||||
|
@ -25,6 +28,8 @@ 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.IBinding;
|
||||
import org.eclipse.cdt.core.dom.ast.IFunction;
|
||||
import org.eclipse.cdt.core.dom.ast.IFunctionType;
|
||||
import org.eclipse.cdt.core.dom.ast.IPointerType;
|
||||
import org.eclipse.cdt.core.dom.ast.IQualifierType;
|
||||
import org.eclipse.cdt.core.dom.ast.IType;
|
||||
|
@ -36,6 +41,8 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTStructuredBindingDeclaration;
|
|||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUnaryExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPDeferredFunction;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionType;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.ITypeContainer;
|
||||
|
@ -50,7 +57,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownType;
|
|||
public final class CPPVariableReadWriteFlags extends VariableReadWriteFlags {
|
||||
private static CPPVariableReadWriteFlags INSTANCE = new CPPVariableReadWriteFlags();
|
||||
|
||||
public static int getReadWriteFlags(IASTName variable) {
|
||||
public static Optional<Integer> getReadWriteFlags(IASTName variable) {
|
||||
CPPSemantics.pushLookupPoint(variable);
|
||||
try {
|
||||
return INSTANCE.rwAnyNode(variable, 0);
|
||||
|
@ -60,28 +67,29 @@ public final class CPPVariableReadWriteFlags extends VariableReadWriteFlags {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected int rwAnyNode(IASTNode node, int indirection) {
|
||||
protected Optional<Integer> rwAnyNode(IASTNode node, int indirection) {
|
||||
final IASTNode parent = node.getParent();
|
||||
if (parent instanceof ICPPASTConstructorInitializer) {
|
||||
return rwInCtorInitializer(node, indirection, (ICPPASTConstructorInitializer) parent);
|
||||
}
|
||||
if (parent instanceof ICPPASTFieldDesignator) {
|
||||
return WRITE; // Field is initialized via a designated initializer.
|
||||
return Optional.of(WRITE); // Field is initialized via a designated initializer.
|
||||
}
|
||||
return super.rwAnyNode(node, indirection);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int rwInDeclarator(IASTDeclarator parent, int indirection) {
|
||||
protected Optional<Integer> rwInDeclarator(IASTDeclarator parent, int indirection) {
|
||||
IType type = CPPVisitor.createType(parent);
|
||||
if (type instanceof ICPPUnknownType || type instanceof ICPPClassType
|
||||
&& !TypeTraits.hasTrivialDefaultConstructor((ICPPClassType) type, CPPSemantics.MAX_INHERITANCE_DEPTH)) {
|
||||
return WRITE;
|
||||
return Optional.of(WRITE);
|
||||
}
|
||||
return super.rwInDeclarator(parent, indirection);
|
||||
}
|
||||
|
||||
private int rwInCtorInitializer(IASTNode node, int indirection, ICPPASTConstructorInitializer parent) {
|
||||
private Optional<Integer> rwInCtorInitializer(IASTNode node, int indirection,
|
||||
ICPPASTConstructorInitializer parent) {
|
||||
IASTNode grand = parent.getParent();
|
||||
if (grand instanceof IASTDeclarator || grand instanceof ICPPASTNewExpression) {
|
||||
// Look for a constructor being called.
|
||||
|
@ -112,33 +120,37 @@ public final class CPPVariableReadWriteFlags extends VariableReadWriteFlags {
|
|||
} else if (grand instanceof ICPPASTStructuredBindingDeclaration) {
|
||||
return rwInStructuredBinding((ICPPASTStructuredBindingDeclaration) grand);
|
||||
}
|
||||
return READ | WRITE; // fallback
|
||||
return Optional.empty(); // Fallback
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int rwInUnaryExpression(IASTNode node, IASTUnaryExpression expr, int indirection) {
|
||||
protected Optional<Integer> rwInUnaryExpression(IASTNode node, IASTUnaryExpression expr, int indirection) {
|
||||
switch (expr.getOperator()) {
|
||||
case ICPPASTUnaryExpression.op_typeid:
|
||||
return 0;
|
||||
return Optional.of(0);
|
||||
}
|
||||
return super.rwInUnaryExpression(node, expr, indirection);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int rwInFunctionName(IASTExpression node) {
|
||||
protected Optional<Integer> rwInFunctionName(IASTExpression node) {
|
||||
if (!(node instanceof IASTIdExpression)) {
|
||||
IType type = node.getExpressionType();
|
||||
if (type instanceof ICPPFunctionType && !((ICPPFunctionType) type).isConst())
|
||||
return READ | WRITE;
|
||||
return Optional.of(READ | WRITE);
|
||||
}
|
||||
return READ;
|
||||
return Optional.of(READ);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int rwAssignmentToType(IType type, int indirection) {
|
||||
protected Optional<Integer> rwAssignmentToType(IType type, int indirection) {
|
||||
if (CPPTemplates.isDependentType(type)) {
|
||||
return Optional.empty(); // Fallback
|
||||
}
|
||||
|
||||
if (indirection == 0) {
|
||||
if (!(type instanceof ICPPReferenceType) || ((ICPPReferenceType) type).isRValueReference()) {
|
||||
return READ;
|
||||
return Optional.of(READ);
|
||||
}
|
||||
type = ((ICPPReferenceType) type).getType();
|
||||
}
|
||||
|
@ -150,11 +162,59 @@ public final class CPPVariableReadWriteFlags extends VariableReadWriteFlags {
|
|||
}
|
||||
if (indirection == 0) {
|
||||
if (type instanceof IQualifierType) {
|
||||
return ((IQualifierType) type).isConst() ? READ : READ | WRITE;
|
||||
return ((IQualifierType) type).isConst() ? Optional.of(READ) : Optional.of(READ | WRITE);
|
||||
} else if (type instanceof IPointerType) {
|
||||
return ((IPointerType) type).isConst() ? READ : READ | WRITE;
|
||||
return ((IPointerType) type).isConst() ? Optional.of(READ) : Optional.of(READ | WRITE);
|
||||
}
|
||||
}
|
||||
return READ | WRITE; // fallback
|
||||
return Optional.empty(); // Fallback
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IBinding getDeferredFunction(IASTExpression functionNameExpression) {
|
||||
if (functionNameExpression instanceof IASTIdExpression) {
|
||||
IBinding b = ((IASTIdExpression) functionNameExpression).getName().resolveBinding();
|
||||
if (b instanceof ICPPDeferredFunction) {
|
||||
return b;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Optional<Integer> evaluateDeferredFunction(final IASTFunctionCallExpression funcCall,
|
||||
final IASTInitializerClause arg, int argPos, int indirection, IBinding defFunctionBinding) {
|
||||
|
||||
ICPPDeferredFunction deferredFunc = (defFunctionBinding instanceof ICPPDeferredFunction)
|
||||
? (ICPPDeferredFunction) defFunctionBinding
|
||||
: null;
|
||||
|
||||
if (deferredFunc == null)
|
||||
return Optional.empty();
|
||||
|
||||
ICPPFunction[] candidates = deferredFunc.getCandidates();
|
||||
if (candidates != null) {
|
||||
Optional<Integer> cumulative = Optional.empty();
|
||||
for (ICPPFunction f : candidates) {
|
||||
IType type = f.getType();
|
||||
if (type instanceof IFunctionType) {
|
||||
Optional<Integer> res = rwArgumentForFunctionCall((IFunctionType) type, argPos, arg, indirection);
|
||||
cumulative = bitwiseOr(cumulative, res);
|
||||
} else if (funcCall instanceof IASTImplicitNameOwner) {
|
||||
IASTImplicitName[] implicitNames = ((IASTImplicitNameOwner) funcCall).getImplicitNames();
|
||||
if (implicitNames.length == 1) {
|
||||
IASTImplicitName name = implicitNames[0];
|
||||
IBinding binding = name.resolveBinding();
|
||||
if (binding instanceof IFunction) {
|
||||
Optional<Integer> res = rwArgumentForFunctionCall(((IFunction) binding).getType(), argPos,
|
||||
arg, indirection);
|
||||
cumulative = bitwiseOr(cumulative, res);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return cumulative;
|
||||
}
|
||||
return Optional.empty(); // Fallback
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,6 +56,7 @@ public final class PDOMName implements IIndexFragmentName {
|
|||
public static final int IS_FRIEND_SPEC = 0x08;
|
||||
public static final int IS_INLINE_NAMESPACE = 0x0C;
|
||||
public static final int COULD_BE_POLYMORPHIC_METHOD_CALL = 0x10;
|
||||
//TODO We haven't got any flag for "unknown" access, we should add it to the index
|
||||
public static final int READ_ACCESS = 0x20;
|
||||
public static final int WRITE_ACCESS = 0x40;
|
||||
// Whether this name is a potential match for its binding, rather than an exact match.
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.cdt.internal.core.pdom.dom.c;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.eclipse.cdt.core.CCorePlugin;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTName;
|
||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||
|
@ -138,7 +140,11 @@ class PDOMCVariable extends PDOMBinding implements IVariable {
|
|||
@Override
|
||||
public int getAdditionalNameFlags(int standardFlags, IASTName name) {
|
||||
if ((standardFlags & PDOMName.IS_REFERENCE) == PDOMName.IS_REFERENCE) {
|
||||
return CVariableReadWriteFlags.getReadWriteFlags(name);
|
||||
Optional<Integer> res = CVariableReadWriteFlags.getReadWriteFlags(name);
|
||||
if (!res.isPresent()) {
|
||||
return PDOMName.WRITE_ACCESS | PDOMName.READ_ACCESS;
|
||||
}
|
||||
return res.get();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.cdt.internal.core.pdom.dom.cpp;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.eclipse.cdt.core.CCorePlugin;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTName;
|
||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||
|
@ -162,7 +164,11 @@ class PDOMCPPVariable extends PDOMCPPBinding implements ICPPVariable {
|
|||
@Override
|
||||
public int getAdditionalNameFlags(int standardFlags, IASTName name) {
|
||||
if ((standardFlags & PDOMName.IS_REFERENCE) == PDOMName.IS_REFERENCE) {
|
||||
return CPPVariableReadWriteFlags.getReadWriteFlags(name);
|
||||
Optional<Integer> res = CPPVariableReadWriteFlags.getReadWriteFlags(name);
|
||||
if (!res.isPresent()) {
|
||||
return PDOMName.READ_ACCESS | PDOMName.WRITE_ACCESS;
|
||||
}
|
||||
return res.get();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ package org.eclipse.cdt.internal.corext.refactoring.code.flow;
|
|||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.eclipse.cdt.core.dom.ast.ASTGenericVisitor;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTArrayDeclarator;
|
||||
|
@ -918,10 +919,10 @@ abstract class FlowAnalyzer extends ASTGenericVisitor {
|
|||
if (!(variable instanceof IField)) {
|
||||
int index = fFlowContext.getIndexFromLocal(variable);
|
||||
if (index >= 0) {
|
||||
int accessMode = CPPVariableReadWriteFlags.getReadWriteFlags(node);
|
||||
if (accessMode != 0) {
|
||||
Optional<Integer> accessMode = CPPVariableReadWriteFlags.getReadWriteFlags(node);
|
||||
if (accessMode.isPresent() && accessMode.get() != 0) {
|
||||
int flowInfoMode = FlowInfo.UNUSED;
|
||||
switch (accessMode) {
|
||||
switch (accessMode.get()) {
|
||||
case PDOMName.READ_ACCESS:
|
||||
flowInfoMode = FlowInfo.READ;
|
||||
break;
|
||||
|
@ -933,6 +934,8 @@ abstract class FlowAnalyzer extends ASTGenericVisitor {
|
|||
break;
|
||||
}
|
||||
setFlowInfo(node, new LocalFlowInfo(variable, index, flowInfoMode, fFlowContext));
|
||||
} else if (!accessMode.isPresent()) {
|
||||
setFlowInfo(node, new LocalFlowInfo(variable, index, FlowInfo.UNKNOWN, fFlowContext));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ import java.util.Collections;
|
|||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
|
||||
|
@ -43,7 +44,6 @@ import org.eclipse.cdt.internal.core.dom.parser.ASTInternal;
|
|||
import org.eclipse.cdt.internal.core.dom.parser.ASTQueries;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVariableReadWriteFlags;
|
||||
import org.eclipse.cdt.internal.core.dom.rewrite.util.ASTNodes;
|
||||
import org.eclipse.cdt.internal.core.pdom.dom.PDOMName;
|
||||
import org.eclipse.cdt.internal.corext.refactoring.code.flow.FlowContext;
|
||||
import org.eclipse.cdt.internal.corext.refactoring.code.flow.FlowInfo;
|
||||
import org.eclipse.cdt.internal.corext.refactoring.code.flow.InputFlowAnalyzer;
|
||||
|
@ -179,8 +179,8 @@ public class NodeContainer {
|
|||
if (!hasReferenceOperator(declarator)) {
|
||||
for (NameInformation n2 : names) {
|
||||
if (n2.getDeclarationName() == declarationName) {
|
||||
int flag = CPPVariableReadWriteFlags.getReadWriteFlags(n2.getName());
|
||||
if ((flag & PDOMName.WRITE_ACCESS) != 0) {
|
||||
Optional<Integer> flags = CPPVariableReadWriteFlags.getReadWriteFlags(n2.getName());
|
||||
if (CPPVariableReadWriteFlags.mayBeWriteAccess(flags)) {
|
||||
nameInfo.setWriteAccess(true);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.cdt.internal.ui.search;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.eclipse.cdt.core.dom.ast.IASTName;
|
||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPVariable;
|
||||
|
@ -62,9 +64,11 @@ public class CSearchUtil {
|
|||
public static boolean isWriteOccurrence(IASTName node, IBinding binding) {
|
||||
boolean isWrite;
|
||||
if (binding instanceof ICPPVariable) {
|
||||
isWrite = ((CPPVariableReadWriteFlags.getReadWriteFlags(node) & PDOMName.WRITE_ACCESS) != 0);
|
||||
Optional<Integer> res = CPPVariableReadWriteFlags.getReadWriteFlags(node);
|
||||
isWrite = !res.isPresent() || ((res.get() & PDOMName.WRITE_ACCESS) != 0);
|
||||
} else {
|
||||
isWrite = ((CVariableReadWriteFlags.getReadWriteFlags(node) & PDOMName.WRITE_ACCESS) != 0);
|
||||
Optional<Integer> res = CVariableReadWriteFlags.getReadWriteFlags(node);
|
||||
isWrite = !res.isPresent() || ((res.get() & PDOMName.WRITE_ACCESS) != 0);
|
||||
}
|
||||
return isWrite;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue