diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/VariableReadWriteFlags.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/VariableReadWriteFlags.java index 173d60b63c5..594a4240d0d 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/VariableReadWriteFlags.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/VariableReadWriteFlags.java @@ -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 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 bitwiseOr(Optional a, Optional b) { - Optional 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; - } + protected Optional union(Optional a, Optional b) { + if (a.isPresent() && b.isPresent()) { + return Optional.of(a.get() | b.get()); } - return or; + return Optional.empty(); } protected Optional 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) { - 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(); - 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); - } - } - } + int index = ArrayUtil.indexOf(args, argument); + if (index == -1) { + return Optional.empty(); + } + final IASTExpression functionNameExpression = funcCall.getFunctionNameExpression(); + if (functionNameExpression == null) { + return Optional.empty(); + } + IType type = functionNameExpression.getExpressionType(); + 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) { + 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) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CVariableReadWriteFlags.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CVariableReadWriteFlags.java index 100d2d4afe1..398bbb44eef 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CVariableReadWriteFlags.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CVariableReadWriteFlags.java @@ -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 evaluateDeferredFunction(final IASTFunctionCallExpression funcCall, - final IASTInitializerClause arg, int argPos, int indirection, IBinding defFunctionBinding) { - return Optional.empty(); - } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVariableReadWriteFlags.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVariableReadWriteFlags.java index 0b4e321c0f2..12e18c5e981 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVariableReadWriteFlags.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVariableReadWriteFlags.java @@ -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 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 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 cumulative = Optional.empty(); - for (ICPPFunction f : candidates) { - IType type = f.getType(); - if (type instanceof IFunctionType) { - Optional 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 res = rwArgumentForFunctionCall(((IFunction) binding).getType(), argPos, - arg, indirection); - cumulative = bitwiseOr(cumulative, res); + ICPPDeferredFunction deferredFunc = (ICPPDeferredFunction) b; + ICPPFunction[] candidates = deferredFunc.getCandidates(); + if (candidates != null) { + IASTInitializerClause[] args = funcCall.getArguments(); + int argPos = ArrayUtil.indexOf(args, argument); + Optional cumulative = Optional.empty(); + for (ICPPFunction f : candidates) { + IType type = f.getType(); + if (type instanceof IFunctionType) { + Optional res = rwArgumentForFunctionCall((IFunctionType) type, argPos, + args[argPos], indirection); + cumulative = union(cumulative, res); } } + return cumulative; } } - return cumulative; } - return Optional.empty(); // Fallback + return super.rwArgumentForFunctionCall(funcCall, argument, indirection); } }