1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-22 06:02:11 +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.ICPPASTStructuredBindingDeclaration;
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;
/**
@ -242,79 +243,47 @@ public abstract class VariableReadWriteFlags {
}
/**
* Check if the function name expression involves a deferred function. Applicable
* only to C++.
* @param functionNameExpression The expression
* @return The binding found, null otherwise
* Helper method to take the union of two sets of read/write flags.
* Note that "unknown" (represented as Optional.empty()) unioned
* with anything is still "unknown", since "unknown" means that
* potentially any type of access is possible.
*/
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());
protected Optional<Integer> union(Optional<Integer> a, Optional<Integer> b) {
if (a.isPresent() && b.isPresent()) {
return 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,
int indirection) {
final IASTInitializerClause[] args = funcCall.getArguments();
for (int i = 0; i < args.length; i++) {
if (args[i] == argument) {
int index = ArrayUtil.indexOf(args, argument);
if (index == -1) {
return Optional.empty();
}
final IASTExpression functionNameExpression = funcCall.getFunctionNameExpression();
if (functionNameExpression != null) {
if (functionNameExpression == null) {
return Optional.empty();
}
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);
IFunctionType functionType = null;
if (type instanceof IFunctionType) {
functionType = (IFunctionType) type;
} 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) {
return rwArgumentForFunctionCall(((IFunction) binding).getType(), i, args[i],
indirection);
functionType = ((IFunction) binding).getType();
}
}
}
if (functionType == null) {
return Optional.empty();
}
break;
}
}
return Optional.empty(); // Fallback
return rwArgumentForFunctionCall(functionType, index, args[index], indirection);
}
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.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;
@ -93,15 +91,4 @@ public final class CVariableReadWriteFlags extends VariableReadWriteFlags {
}
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.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;
@ -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.ICPPFunctionType;
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.VariableReadWriteFlags;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownType;
@ -171,50 +171,32 @@ public final class CPPVariableReadWriteFlags extends VariableReadWriteFlags {
}
@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) {
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();
ICPPDeferredFunction deferredFunc = (ICPPDeferredFunction) b;
ICPPFunction[] candidates = deferredFunc.getCandidates();
if (candidates != null) {
IASTInitializerClause[] args = funcCall.getArguments();
int argPos = ArrayUtil.indexOf(args, argument);
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);
}
}
Optional<Integer> res = rwArgumentForFunctionCall((IFunctionType) type, argPos,
args[argPos], indirection);
cumulative = union(cumulative, res);
}
}
return cumulative;
}
return Optional.empty(); // Fallback
}
}
return super.rwArgumentForFunctionCall(funcCall, argument, indirection);
}
}