1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-22 14:12:10 +02:00

Bug 561088 - Some cleanups to VariableReadWriteFlags classes

Change-Id: I63c5333b4c97062229c7f421b4f152ba3f90a996
This commit is contained in:
Nathan Ridge 2020-03-23 00:04:31 -04:00
parent b65be51fc9
commit 65e8a04447
3 changed files with 52 additions and 114 deletions

View file

@ -59,6 +59,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTInitializerClause;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTRangeBasedForStatement; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTRangeBasedForStatement;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTStructuredBindingDeclaration; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTStructuredBindingDeclaration;
import org.eclipse.cdt.core.dom.ast.gnu.IGNUASTCompoundStatementExpression; import org.eclipse.cdt.core.dom.ast.gnu.IGNUASTCompoundStatementExpression;
import org.eclipse.cdt.core.parser.util.ArrayUtil;
import org.eclipse.cdt.internal.core.pdom.dom.PDOMName; import org.eclipse.cdt.internal.core.pdom.dom.PDOMName;
/** /**
@ -242,79 +243,47 @@ public abstract class VariableReadWriteFlags {
} }
/** /**
* Check if the function name expression involves a deferred function. Applicable * Helper method to take the union of two sets of read/write flags.
* only to C++. * Note that "unknown" (represented as Optional.empty()) unioned
* @param functionNameExpression The expression * with anything is still "unknown", since "unknown" means that
* @return The binding found, null otherwise * potentially any type of access is possible.
*/ */
protected abstract IBinding getDeferredFunction(IASTExpression functionNameExpression); protected Optional<Integer> union(Optional<Integer> a, Optional<Integer> b) {
if (a.isPresent() && b.isPresent()) {
/** return Optional.of(a.get() | b.get());
* 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; return Optional.empty();
} }
protected Optional<Integer> rwArgumentForFunctionCall(final IASTFunctionCallExpression funcCall, IASTNode argument, protected Optional<Integer> rwArgumentForFunctionCall(final IASTFunctionCallExpression funcCall, IASTNode argument,
int indirection) { int indirection) {
final IASTInitializerClause[] args = funcCall.getArguments(); final IASTInitializerClause[] args = funcCall.getArguments();
for (int i = 0; i < args.length; i++) { int index = ArrayUtil.indexOf(args, argument);
if (args[i] == argument) { if (index == -1) {
final IASTExpression functionNameExpression = funcCall.getFunctionNameExpression(); return Optional.empty();
if (functionNameExpression != null) { }
IType type = functionNameExpression.getExpressionType(); final IASTExpression functionNameExpression = funcCall.getFunctionNameExpression();
IBinding deferredFunc = getDeferredFunction(functionNameExpression); if (functionNameExpression == null) {
if (deferredFunc != null) { return Optional.empty();
return evaluateDeferredFunction(funcCall, args[i], i, indirection, deferredFunc); }
} else if (type instanceof IFunctionType) { IType type = functionNameExpression.getExpressionType();
return rwArgumentForFunctionCall((IFunctionType) type, i, args[i], indirection); IFunctionType functionType = null;
} else if (funcCall instanceof IASTImplicitNameOwner) { if (type instanceof IFunctionType) {
IASTImplicitName[] implicitNames = ((IASTImplicitNameOwner) funcCall).getImplicitNames(); functionType = (IFunctionType) type;
if (implicitNames.length == 1) { } else if (funcCall instanceof IASTImplicitNameOwner) {
IASTImplicitName name = implicitNames[0]; IASTImplicitName[] implicitNames = ((IASTImplicitNameOwner) funcCall).getImplicitNames();
IBinding binding = name.resolveBinding(); if (implicitNames.length == 1) {
if (binding instanceof IFunction) { IASTImplicitName name = implicitNames[0];
return rwArgumentForFunctionCall(((IFunction) binding).getType(), i, args[i], IBinding binding = name.resolveBinding();
indirection); if (binding instanceof IFunction) {
} functionType = ((IFunction) binding).getType();
}
}
} }
break;
} }
} }
return Optional.empty(); // Fallback if (functionType == null) {
return Optional.empty();
}
return rwArgumentForFunctionCall(functionType, index, args[index], indirection);
} }
private IType getArgumentType(IASTInitializerClause argument) { private IType getArgumentType(IASTInitializerClause argument) {

View file

@ -18,10 +18,8 @@ import java.util.Optional;
import org.eclipse.cdt.core.dom.ast.IASTEqualsInitializer; import org.eclipse.cdt.core.dom.ast.IASTEqualsInitializer;
import org.eclipse.cdt.core.dom.ast.IASTExpression; import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression; 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.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode; 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.IPointerType;
import org.eclipse.cdt.core.dom.ast.IQualifierType; import org.eclipse.cdt.core.dom.ast.IQualifierType;
import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.IType;
@ -93,15 +91,4 @@ public final class CVariableReadWriteFlags extends VariableReadWriteFlags {
} }
return Optional.empty(); // 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();
}
} }

View file

@ -28,7 +28,6 @@ import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression; import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression;
import org.eclipse.cdt.core.dom.ast.IBinding; 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.IFunctionType;
import org.eclipse.cdt.core.dom.ast.IPointerType; import org.eclipse.cdt.core.dom.ast.IPointerType;
import org.eclipse.cdt.core.dom.ast.IQualifierType; import org.eclipse.cdt.core.dom.ast.IQualifierType;
@ -45,6 +44,7 @@ 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.ICPPFunction;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType;
import org.eclipse.cdt.core.parser.util.ArrayUtil;
import org.eclipse.cdt.internal.core.dom.parser.ITypeContainer; import org.eclipse.cdt.internal.core.dom.parser.ITypeContainer;
import org.eclipse.cdt.internal.core.dom.parser.VariableReadWriteFlags; import org.eclipse.cdt.internal.core.dom.parser.VariableReadWriteFlags;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownType; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownType;
@ -171,50 +171,32 @@ public final class CPPVariableReadWriteFlags extends VariableReadWriteFlags {
} }
@Override @Override
protected IBinding getDeferredFunction(IASTExpression functionNameExpression) { protected Optional<Integer> rwArgumentForFunctionCall(final IASTFunctionCallExpression funcCall, IASTNode argument,
int indirection) {
// Handle deferred functions (unresolved overloads) by taking the union (bitwise or)
// of the flags of each candidate function.
IASTExpression functionNameExpression = funcCall.getFunctionNameExpression();
if (functionNameExpression instanceof IASTIdExpression) { if (functionNameExpression instanceof IASTIdExpression) {
IBinding b = ((IASTIdExpression) functionNameExpression).getName().resolveBinding(); IBinding b = ((IASTIdExpression) functionNameExpression).getName().resolveBinding();
if (b instanceof ICPPDeferredFunction) { if (b instanceof ICPPDeferredFunction) {
return b; ICPPDeferredFunction deferredFunc = (ICPPDeferredFunction) b;
} ICPPFunction[] candidates = deferredFunc.getCandidates();
} if (candidates != null) {
return null; IASTInitializerClause[] args = funcCall.getArguments();
} int argPos = ArrayUtil.indexOf(args, argument);
Optional<Integer> cumulative = Optional.empty();
@Override for (ICPPFunction f : candidates) {
protected Optional<Integer> evaluateDeferredFunction(final IASTFunctionCallExpression funcCall, IType type = f.getType();
final IASTInitializerClause arg, int argPos, int indirection, IBinding defFunctionBinding) { if (type instanceof IFunctionType) {
Optional<Integer> res = rwArgumentForFunctionCall((IFunctionType) type, argPos,
ICPPDeferredFunction deferredFunc = (defFunctionBinding instanceof ICPPDeferredFunction) args[argPos], indirection);
? (ICPPDeferredFunction) defFunctionBinding cumulative = union(cumulative, res);
: 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 cumulative;
} }
return Optional.empty(); // Fallback return super.rwArgumentForFunctionCall(funcCall, argument, indirection);
} }
} }