1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-24 09:25:31 +02:00

Bug 85843: ADL for overloaded function sets.

This commit is contained in:
Markus Schorn 2010-09-16 07:31:42 +00:00
parent 497b9282a8
commit 4720831a18
16 changed files with 809 additions and 442 deletions

View file

@ -66,7 +66,7 @@ public class ASTCPPSpecDefectTests extends AST2BaseTest {
// void test() {
// fp(f0);
// }
public void _testADLForOverloadSet_324842() throws Exception {
public void testADLForOverloadSet_324842() throws Exception {
parseAndCheckBindings();
}
}

View file

@ -445,7 +445,7 @@ public class IndexCPPTemplateResolutionTest extends IndexBindingResolutionTestBa
// A<B> a;
// a.f= foo<B>;
// }
public void _testOverloadedFunctionTemplate() {
public void testOverloadedFunctionTemplate() {
IBinding b0= getBindingFromASTName("foo<B>;", 6);
assertInstance(b0, ICPPFunction.class);
assertInstance(b0, ICPPSpecialization.class);

View file

@ -14,6 +14,7 @@ package org.eclipse.cdt.internal.core.dom.parser.cpp;
import static org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory.LVALUE;
import static org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory.PRVALUE;
import static org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory.XVALUE;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExpressionTypes.prvalueType;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.*;
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
@ -213,46 +214,50 @@ public class CPPASTConditionalExpression extends ASTNode implements IASTConditio
final ValueCategory vcat2= expr2.getValueCategory();
final ValueCategory vcat3= expr3.getValueCategory();
final boolean isClassType2 = uqt2 instanceof ICPPClassType;
final boolean isClassType3 = uqt3 instanceof ICPPClassType;
// Same type and same value category
// Same type
if (t2.isSameType(t3)) {
if (vcat2 == vcat3) {
fType= t2;
fValueCategory= vcat2;
return;
}
} else {
// Different types with at least one class type
if (isClassType2 || isClassType3) {
final Cost cost2= convertToMatch(t2, vcat2, uqt2, t3, vcat3, uqt3); // sets fType and fValueCategory
final Cost cost3= convertToMatch(t3, vcat3, uqt3, t2, vcat2, uqt2); // sets fType and fValueCategory
if (cost2.converts() || cost3.converts()) {
if (cost2.converts()) {
if (cost3.converts() || cost2.isAmbiguousUDC()) {
fType= createProblem();
}
} else if (cost3.isAmbiguousUDC()) {
} else {
fType= prvalueType(t2);
fValueCategory= PRVALUE;
}
return;
}
final boolean isClassType2 = uqt2 instanceof ICPPClassType;
final boolean isClassType3 = uqt3 instanceof ICPPClassType;
// Different types with at least one class type
if (isClassType2 || isClassType3) {
final Cost cost2= convertToMatch(t2, vcat2, uqt2, t3, vcat3, uqt3); // sets fType and fValueCategory
final Cost cost3= convertToMatch(t3, vcat3, uqt3, t2, vcat2, uqt2); // sets fType and fValueCategory
if (cost2.converts() || cost3.converts()) {
if (cost2.converts()) {
if (cost3.converts() || cost2.isAmbiguousUDC()) {
fType= createProblem();
}
return;
}
} else if (vcat2 == vcat3 && vcat2.isGLValue() && uqt2.isSameType(uqt3)) {
// Two lvalues or two xvalues with same type up to qualification.
final CVQualifier cv2 = SemanticUtil.getCVQualifier(t2);
final CVQualifier cv3 = SemanticUtil.getCVQualifier(t3);
if (cv2.isAtLeastAsQualifiedAs(cv3)) {
fType= t2;
fValueCategory= vcat2;
} else if (cv3.isAtLeastAsQualifiedAs(cv2)) {
fType= t3;
fValueCategory= vcat3;
} else {
createProblem();
} else if (cost3.isAmbiguousUDC()) {
fType= createProblem();
}
return;
}
} else if (vcat2 == vcat3 && vcat2.isGLValue() && uqt2.isSameType(uqt3)) {
// Two lvalues or two xvalues with same type up to qualification.
final CVQualifier cv2 = SemanticUtil.getCVQualifier(t2);
final CVQualifier cv3 = SemanticUtil.getCVQualifier(t3);
if (cv2.isAtLeastAsQualifiedAs(cv3)) {
fType= t2;
fValueCategory= vcat2;
} else if (cv3.isAtLeastAsQualifiedAs(cv2)) {
fType= t3;
fValueCategory= vcat3;
} else {
createProblem();
}
return;
}
// 5.16-5: At least one class type but no conversion

View file

@ -14,8 +14,7 @@ package org.eclipse.cdt.internal.core.dom.parser.cpp;
import static org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory.LVALUE;
import static org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory.PRVALUE;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExpressionTypes.typeFromFunctionCall;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExpressionTypes.valueCategoryFromFunctionCall;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExpressionTypes.*;
import org.eclipse.cdt.core.dom.ast.ASTNodeProperty;
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
@ -155,22 +154,26 @@ public class CPPASTExpressionList extends ASTNode implements ICPPASTExpressionLi
return overloads = NO_FUNCTIONS;
overloads = new ICPPFunction[exprs.length-1];
IType lookupType = exprs[0].getExpressionType();
IType lookupType = typeOrFunctionSet(exprs[0]);
ValueCategory vcat= valueCat(exprs[0]);
for(int i = 1; i < exprs.length; i++) {
IASTExpression e1 = exprs[i-1], e2 = exprs[i];
ICPPFunction overload = CPPSemantics.findOverloadedOperatorComma(e1, e2, lookupType);
if(overload == null) {
lookupType = e2.getExpressionType();
}
else {
overloads[i-1] = overload;
try {
for (int i = 1; i < exprs.length; i++) {
IASTExpression e1 = exprs[i - 1], e2 = exprs[i];
ICPPFunction overload = CPPSemantics.findOverloadedOperatorComma(e1, lookupType, vcat, e2);
if (overload == null) {
lookupType = typeOrFunctionSet(e2);
vcat= valueCat(e2);
} else {
overloads[i - 1] = overload;
try {
lookupType = overload.getType().getReturnType();
vcat= valueCategoryFromReturnType(lookupType);
lookupType= typeFromReturnType(lookupType);
} catch (DOMException e) {
lookupType = e2.getExpressionType();
lookupType = typeOrFunctionSet(e2);
vcat= valueCat(e2);
}
}
}
}
}

View file

@ -42,6 +42,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateNonTypeParameter;
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPFunctionSet;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil;
@ -108,6 +109,9 @@ public class CPPASTIdExpression extends ASTNode implements IASTIdExpression, ICP
public IType getExpressionType() {
IBinding binding = name.resolvePreBinding();
if (binding instanceof CPPFunctionSet)
binding= name.resolveBinding();
if (checkForTransformation(binding)) {
return fTransformedExpression.getExpressionType();
}

View file

@ -26,7 +26,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameter;
*/
public class CPPUnknownFunction extends CPPUnknownBinding implements ICPPFunction {
public static IFunction createForSample(IFunction sample) throws DOMException {
public static ICPPFunction createForSample(IFunction sample) throws DOMException {
if (sample instanceof ICPPConstructor)
return new CPPUnknownConstructor(((ICPPConstructor) sample).getClassOwner());

View file

@ -10,6 +10,7 @@
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExpressionTypes.typeOrFunctionSet;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.*;
import java.util.ArrayList;
@ -83,13 +84,13 @@ class BuiltinOperators {
fUnary= args.length<2;
fGlobalCandidates= globCandidates;
if (args.length > 0 && args[0] instanceof IASTExpression) {
IType type= ((IASTExpression) args[0]).getExpressionType();
IType type= typeOrFunctionSet((IASTExpression) args[0]);
if (!(type instanceof IProblemBinding))
fType1= type;
}
if (args.length > 1 && args[1] instanceof IASTExpression) {
IType type= ((IASTExpression) args[1]).getExpressionType();
IType type= typeOrFunctionSet((IASTExpression) args[1]);
if (!(type instanceof IProblemBinding))
fType2= type;
}

View file

@ -0,0 +1,67 @@
/*
* CPPFunctionSet.java
* Created on Sep 13, 2010
*
* Copyright 2010 Wind River Systems, Inc. All rights reserved.
*/
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
import org.eclipse.cdt.core.dom.ILinkage;
import org.eclipse.cdt.core.dom.ast.DOMException;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IScope;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
import org.eclipse.cdt.core.parser.util.ArrayUtil;
import org.eclipse.cdt.internal.core.dom.Linkage;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTNameBase;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPTwoPhaseBinding;
/**
* Used as intermediate binding for names nominating a function without calling it.
* The actual function can be resolved in certain contexts.
*/
public class CPPFunctionSet implements ICPPTwoPhaseBinding {
final ICPPFunction[] fBindings;
public CPPFunctionSet(ICPPFunction[] bindingList) {
fBindings = ArrayUtil.removeNulls(bindingList);
}
public String getName() {
return fBindings[0].getName();
}
public char[] getNameCharArray() {
return fBindings[0].getNameCharArray();
}
public IScope getScope() throws DOMException {
return fBindings[0].getScope();
}
public IBinding getOwner() {
return fBindings[0].getOwner();
}
public ICPPFunction[] getBindings() {
return fBindings;
}
public ILinkage getLinkage() {
return Linkage.CPP_LINKAGE;
}
public IBinding resolveFinalBinding(CPPASTNameBase astName) {
return CPPSemantics.resolveTargetedFunction(astName, fBindings);
}
@SuppressWarnings("unchecked")
public Object getAdapter(@SuppressWarnings("rawtypes") Class adapter) {
if (adapter.isAssignableFrom(getClass()))
return this;
return null;
}
}

View file

@ -17,6 +17,8 @@ package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
import static org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory.LVALUE;
import static org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory.PRVALUE;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExpressionTypes.typeOrFunctionSet;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExpressionTypes.valueCat;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.*;
import java.util.ArrayList;
@ -51,6 +53,7 @@ import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.IASTIdExpression;
import org.eclipse.cdt.core.dom.ast.IASTImplicitNameOwner;
import org.eclipse.cdt.core.dom.ast.IASTInitializer;
import org.eclipse.cdt.core.dom.ast.IASTInitializerClause;
import org.eclipse.cdt.core.dom.ast.IASTLabelStatement;
@ -150,7 +153,6 @@ import org.eclipse.cdt.core.index.IIndexBinding;
import org.eclipse.cdt.core.index.IIndexFile;
import org.eclipse.cdt.core.index.IIndexFileSet;
import org.eclipse.cdt.core.index.IIndexName;
import org.eclipse.cdt.core.parser.IProblem;
import org.eclipse.cdt.core.parser.util.ArrayUtil;
import org.eclipse.cdt.core.parser.util.CharArrayObjectMap;
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
@ -642,7 +644,7 @@ public class CPPSemantics {
return data;
}
static private Set<ICPPNamespaceScope> getAssociatedScopes(LookupData data) {
private static Set<ICPPNamespaceScope> getAssociatedScopes(LookupData data) {
if (!data.hasFunctionArguments())
return Collections.emptySet();
@ -659,7 +661,7 @@ public class CPPSemantics {
return namespaces;
}
static private void getAssociatedScopes(IType t, Set<ICPPNamespaceScope> namespaces,
private static void getAssociatedScopes(IType t, Set<ICPPNamespaceScope> namespaces,
ObjectSet<ICPPClassType> classes, CPPASTTranslationUnit tu) throws DOMException {
// 3.4.2-2
if (t instanceof ICPPClassType) {
@ -691,11 +693,15 @@ public class CPPSemantics {
} else if (t instanceof ICPPPointerToMemberType) {
IType binding = ((ICPPPointerToMemberType) t).getMemberOfClass();
getAssociatedScopes(binding, namespaces, classes, tu);
}
return;
} else if (t instanceof FunctionSetType) {
FunctionSetType fst= (FunctionSetType) t;
for (ICPPFunction fn : fst.getFunctionSet()) {
getAssociatedScopes(fn.getType(), namespaces, classes, tu);
}
}
}
static private ICPPNamespaceScope getContainingNamespaceScope(IBinding binding,
private static ICPPNamespaceScope getContainingNamespaceScope(IBinding binding,
CPPASTTranslationUnit tu) throws DOMException {
if (binding == null)
return null;
@ -1099,7 +1105,7 @@ public class CPPSemantics {
public int visit(IASTExpression expression) {
if (expression instanceof IASTLiteralExpression) {
if (((IASTLiteralExpression) expression).getKind() == IASTLiteralExpression.lk_this) {
final IType thisType = SemanticUtil.getNestedType(expression.getExpressionType(), TDEF | ALLCVQ | PTR | ARRAY | MPTR | REF);
final IType thisType = SemanticUtil.getNestedType(typeOrFunctionSet(expression), TDEF | ALLCVQ | PTR | ARRAY | MPTR | REF);
if (thisType instanceof ICPPUnknownBinding || thisType instanceof ICPPTemplateDefinition) {
result[0]= true;
return PROCESS_ABORT;
@ -1250,7 +1256,7 @@ public class CPPSemantics {
* In case of an unqualified lookup the transitive directives are stored, also. This is important because
* the members nominated by a transitive directive can appear before those of the original directive.
*/
static private void storeUsingDirective(LookupData data, ICPPNamespaceScope container,
private static void storeUsingDirective(LookupData data, ICPPNamespaceScope container,
ICPPUsingDirective directive, Set<ICPPNamespaceScope> handled) throws DOMException {
ICPPNamespaceScope nominated= directive.getNominatedScope();
if (nominated instanceof IIndexScope && data.tu != null) {
@ -1291,7 +1297,7 @@ public class CPPSemantics {
/**
* Computes the common enclosing scope of s1 and s2.
*/
static private ICPPScope getCommonEnclosingScope(IScope s1, IScope s2, CPPASTTranslationUnit tu) throws DOMException {
private static ICPPScope getCommonEnclosingScope(IScope s1, IScope s2, CPPASTTranslationUnit tu) throws DOMException {
ObjectSet<IScope> set = new ObjectSet<IScope>(2);
IScope parent= s1;
while (parent != null) {
@ -1629,7 +1635,7 @@ public class CPPSemantics {
* are considered if the lookup of the original directive returns empty.
* @param fileSet
*/
static private void lookupInNominated(LookupData data, IIndexFileSet fileSet, ICPPNamespaceScope scope) throws DOMException {
private static void lookupInNominated(LookupData data, IIndexFileSet fileSet, ICPPNamespaceScope scope) throws DOMException {
List<ICPPNamespaceScope> allNominated= data.usingDirectives.remove(scope);
while (allNominated != null) {
for (ICPPNamespaceScope nominated : allNominated) {
@ -1821,13 +1827,13 @@ public class CPPSemantics {
return false;
}
static private IBinding resolveAmbiguities(LookupData data, IASTName name) throws DOMException {
private static IBinding resolveAmbiguities(LookupData data, IASTName name) throws DOMException {
if (!data.hasResults() || data.contentAssist)
return null;
final boolean indexBased= data.tu != null && data.tu.getIndex() != null;
@SuppressWarnings("unchecked")
ObjectSet<IFunction> fns= ObjectSet.EMPTY_SET;
ObjectSet<ICPPFunction> fns= ObjectSet.EMPTY_SET;
IBinding type = null;
IBinding obj = null;
IBinding temp = null;
@ -1878,15 +1884,15 @@ public class CPPSemantics {
mergeResults(data, bindings, false);
items = (Object[]) data.foundItems;
continue;
} else if (temp instanceof IFunction) {
} else if (temp instanceof ICPPFunction) {
if (temp instanceof ICPPTemplateInstance) {
temp= ((ICPPTemplateInstance) temp).getSpecializedBinding();
if (!(temp instanceof IFunction))
continue;
}
if (fns == ObjectSet.EMPTY_SET)
fns = new ObjectSet<IFunction>(2);
fns.put((IFunction) temp);
fns = new ObjectSet<ICPPFunction>(2);
fns.put((ICPPFunction) temp);
} else if (temp instanceof IType) {
// specializations are selected during instantiation
if (temp instanceof ICPPClassTemplatePartialSpecialization)
@ -1977,7 +1983,7 @@ public class CPPSemantics {
if (fns.size() > 0) {
final IFunction[] fnArray = fns.keyArray(IFunction.class);
final ICPPFunction[] fnArray = fns.keyArray(ICPPFunction.class);
if (type != null && overrulesByRelevance(data, type, fnArray)) {
return type;
}
@ -2200,69 +2206,60 @@ public class CPPSemantics {
}
}
static private void reduceToViable(LookupData data, IBinding[] functions) throws DOMException {
if (functions == null || functions.length == 0)
return;
final boolean def = data.forFunctionDeclaration();
private static ICPPFunction[] selectByArgumentCount(LookupData data, ICPPFunction[] functions) throws DOMException {
assert !data.forFunctionDeclaration();
int argumentCount = data.getFunctionArgumentCount();
if (def && argumentCount == 1) {
// check for parameter of type void
final IType[] argTypes = data.getFunctionArgumentTypes();
if (argTypes.length == 1 && SemanticUtil.isVoidType(argTypes[0])) {
argumentCount= 0;
}
}
// Trim the list down to the set of viable functions
ICPPFunction function = null;
int size = functions.length;
for (int i = 0; i < size; i++) {
if (functions[i] instanceof IProblemBinding) {
functions[i]= null;
continue;
}
function = (ICPPFunction) functions[i];
if (function == null)
continue;
if (function instanceof ICPPUnknownBinding) {
if (def) {
functions[i]= null;
}
continue;
}
// Trim the list down to the set of viable functions
ICPPFunction[] result= new ICPPFunction[functions.length];
int idx= 0;
for (ICPPFunction fn : functions) {
if (fn != null && !(fn instanceof IProblemBinding)) {
if (fn instanceof ICPPUnknownBinding) {
return new ICPPFunction[] {fn};
}
// the index is optimized to provide the function type, try not to use the parameters
// as long as possible.
final IType[] parameterTypes = function.getType().getParameterTypes();
int numPars = parameterTypes.length;
if (numPars == 1 && SemanticUtil.isVoidType(parameterTypes[0]))
numPars= 0;
int numArgs = argumentCount;
if (function instanceof ICPPMethod && data.argsContainImpliedObject)
numArgs--;
if (def) {
if (numPars != numArgs || !isMatchingFunctionDeclaration(function, data)) {
functions[i] = null;
}
} else {
// more arguments than parameters --> need ellipsis
// The index is optimized to provide the function type, try not to use the parameters
// as long as possible.
final ICPPFunctionType ft = fn.getType();
final IType[] parameterTypes = ft.getParameterTypes();
int numPars = parameterTypes.length;
if (numPars == 1 && SemanticUtil.isVoidType(parameterTypes[0]))
numPars= 0;
int numArgs = argumentCount;
if (fn instanceof ICPPMethod && data.argsContainImpliedObject)
numArgs--;
boolean ok;
if (numArgs > numPars) {
if (!function.takesVarArgs() && !function.hasParameterPack()) {
functions[i] = null;
// more arguments than parameters --> need ellipsis or parameter pack
ok= fn.takesVarArgs() || fn.hasParameterPack();
} else {
ok = numArgs >= fn.getRequiredArgumentCount();
}
if (ok) {
if (fn instanceof IIndexBinding) {
for (ICPPFunction other : result) {
if (other == null || other instanceof IIndexBinding)
break;
if (other.getType().isSameType(ft)) {
ok= false;
break;
}
}
}
if (ok) {
result[idx++]= fn;
}
} else if (numArgs < function.getRequiredArgumentCount()) {
// fewer arguments than required
functions[i]= null;
}
}
}
}
return result;
}
static private boolean isMatchingFunctionDeclaration(ICPPFunction candidate, LookupData data) {
private static boolean isMatchingFunctionDeclaration(ICPPFunction candidate, LookupData data) {
IASTNode node = data.astName.getParent();
while (node instanceof IASTName)
node = node.getParent();
@ -2272,54 +2269,65 @@ public class CPPSemantics {
return false;
}
static IBinding resolveFunction(LookupData data, IFunction[] fns, boolean allowUDC) throws DOMException {
fns= (IFunction[]) ArrayUtil.trim(IFunction.class, fns);
static IBinding resolveFunction(LookupData data, ICPPFunction[] fns, boolean allowUDC) throws DOMException {
fns= (ICPPFunction[]) ArrayUtil.trim(ICPPFunction.class, fns);
if (fns == null || fns.length == 0)
return null;
if (data.forUsingDeclaration()) {
return new CPPUsingDeclaration(data.astName, fns);
}
sortAstBeforeIndex(fns);
if (data.forUsingDeclaration())
return new CPPUsingDeclaration(data.astName, fns);
// We don't have any arguments with which to resolve the function
final boolean isFuncDecl = data.forFunctionDeclaration();
// No arguments to resolve function
if (!data.hasFunctionArguments()) {
return resolveTargetedFunction(data, fns);
ICPPFunction cand= fns[0];
if (!(cand instanceof ICPPFunctionTemplate)) {
if (fns.length == 1)
return cand;
// Just one binding from ast, use it.
if (!(cand instanceof IIndexBinding) && fns[1] instanceof IIndexBinding)
return cand;
}
return new CPPFunctionSet(fns);
}
if (data.astName instanceof ICPPASTConversionName) {
return resolveUserDefinedConversion(data, fns);
}
if (!isFuncDecl || data.forExplicitFunctionSpecialization()) {
CPPTemplates.instantiateFunctionTemplates(fns, data.getFunctionArgumentTypes(), data.getFunctionArgumentValueCategories(),
data.astName, data.argsContainImpliedObject);
}
if (data.forFunctionDeclaration())
return resolveFunctionDeclaration(data, fns);
// Reduce our set of candidate functions to only those who have the right number of parameters
reduceToViable(data, fns);
final IType[] argTypes = data.getFunctionArgumentTypes();
ICPPFunction[] tmp= selectByArgumentCount(data, fns);
tmp= CPPTemplates.instantiateFunctionTemplates(tmp, argTypes, data.getFunctionArgumentValueCategories(),
data.astName, data.argsContainImpliedObject);
if (tmp.length == 0 || tmp[0] == null)
return new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_NAME_NOT_FOUND, fns);
int viableCount= 0;
IFunction firstViable= null;
for (IFunction f : fns) {
if (f != null) {
if (++viableCount == 1) {
firstViable= f;
}
if (f instanceof ICPPUnknownBinding) {
return f;
}
for (IFunction f : tmp) {
if (f instanceof ICPPUnknownBinding) {
setTargetedFunctionsToUnknown(argTypes);
return f;
}
if (f == null)
break;
++viableCount;
}
if (firstViable == null || isFuncDecl)
return firstViable;
if (viableCount == 0)
return new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_NAME_NOT_FOUND, fns);
// The arguments the function is being called with
IType[] argTypes = data.getFunctionArgumentTypes();
// Check for dependent arguments
fns= tmp;
if (CPPTemplates.containsDependentType(argTypes)) {
if (viableCount == 1)
return firstViable;
return CPPUnknownFunction.createForSample(firstViable);
if (viableCount == 1)
return fns[0];
setTargetedFunctionsToUnknown(argTypes);
return CPPUnknownFunction.createForSample(fns[0]);
}
IFunction[] ambiguousFunctions= null; // ambiguity, 2 functions are equally good
@ -2336,11 +2344,12 @@ public class CPPSemantics {
continue;
if (fnCost == CONTAINS_DEPENDENT_TYPES) {
if (viableCount == 1)
return firstViable;
return CPPUnknownFunction.createForSample(firstViable);
if (viableCount == 1)
return fns[0];
setTargetedFunctionsToUnknown(argTypes);
return CPPUnknownFunction.createForSample(fns[0]);
}
if (fnCost.hasDeferredUDC()) {
if (potentialCosts == null) {
potentialCosts= new ArrayList<FunctionCost>();
@ -2383,10 +2392,70 @@ public class CPPSemantics {
return new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP,
data.getFoundBindings());
}
for (int i = 0; i < argTypes.length; i++) {
IType iType = argTypes[i];
if (iType instanceof FunctionSetType) {
((FunctionSetType) iType).applySelectedFunction(bestFnCost.getCost(i).getSelectedFunction());
}
}
return bestFnCost.getFunction();
}
private static void setTargetedFunctionsToUnknown(IType[] argTypes) {
for (IType argType : argTypes) {
if (argType instanceof FunctionSetType) {
((FunctionSetType) argType).setToUnknown();
}
}
}
private static IBinding resolveFunctionDeclaration(LookupData data, ICPPFunction[] fns) throws DOMException {
if (data.forExplicitFunctionSpecialization()) {
fns= CPPTemplates.instantiateFunctionTemplates(fns, data.getFunctionArgumentTypes(),
data.getFunctionArgumentValueCategories(), data.astName, data.argsContainImpliedObject);
}
int argCount = data.getFunctionArgumentCount();
if (argCount == 1) {
// check for parameter of type void
final IType[] argTypes = data.getFunctionArgumentTypes();
if (argTypes.length == 1 && SemanticUtil.isVoidType(argTypes[0])) {
argCount= 0;
}
}
for (ICPPFunction fn : fns) {
if (fn != null && !(fn instanceof IProblemBinding) && !(fn instanceof ICPPUnknownBinding)) {
// The index is optimized to provide the function type, avoid using the parameters
// as long as possible.
final IType[] parameterTypes = fn.getType().getParameterTypes();
int parCount = parameterTypes.length;
if (parCount == 1 && SemanticUtil.isVoidType(parameterTypes[0]))
parCount= 0;
if (parCount == argCount && isMatchingFunctionDeclaration(fn, data)) {
return fn;
}
}
}
return null;
}
public static void sortAstBeforeIndex(IFunction[] fns) {
int iast= 0;
for (int i = 0; i < fns.length; i++) {
IFunction fn= fns[i];
if (!(fn instanceof IIndexBinding)) {
if (iast != i) {
fns[i]= fns[iast];
fns[iast]= fn;
iast++;
}
}
}
}
private static FunctionCost costForFunctionCall(IFunction fn, boolean allowUDC, LookupData data)
throws DOMException {
IType[] argTypes = data.getFunctionArgumentTypes();
@ -2466,7 +2535,9 @@ public class CPPSemantics {
continue;
}
if (argType.isSameType(paramType)) {
if (argType instanceof FunctionSetType) {
cost= ((FunctionSetType) argType).costForTarget(paramType);
} else if (argType.isSameType(paramType)) {
cost = new Cost(argType, paramType, Rank.IDENTITY);
} else {
if (CPPTemplates.isDependentType(paramType))
@ -2537,245 +2608,186 @@ public class CPPSemantics {
/**
* 13.4-1 A use of an overloaded function without arguments is resolved in certain contexts to a function
* @param data
* @param fns
* @return
*/
private static IBinding resolveTargetedFunction(LookupData data, IBinding[] fns) {
if (fns.length == 1)
return fns[0];
IBinding oneFromAST= null;
for (IBinding fn : fns) {
if (!isFromIndex(fn)) {
if (oneFromAST != null) {
oneFromAST= null;
static IBinding resolveTargetedFunction(IASTName name, ICPPFunction[] fns) {
boolean addressOf= false;
IASTNode node= name.getParent();
while (node instanceof IASTName)
node= node.getParent();
if (!(node instanceof IASTIdExpression))
return new ProblemBinding(name, IProblemBinding.SEMANTIC_INVALID_OVERLOAD);
ASTNodeProperty prop= node.getPropertyInParent();
IASTNode parent = node.getParent();
while (parent instanceof IASTUnaryExpression) {
final int op= ((IASTUnaryExpression) parent).getOperator();
if (op == IASTUnaryExpression.op_bracketedPrimary) {
} else if (!addressOf && op == IASTUnaryExpression.op_amper) {
addressOf= true;
} else {
break;
}
node= parent;
prop= node.getPropertyInParent();
parent= node.getParent();
}
IType targetType= null;
if (prop == IASTDeclarator.INITIALIZER) {
// Target is an object or reference being initialized
IASTDeclarator dtor = (IASTDeclarator) parent;
targetType= CPPVisitor.createType(dtor);
} else if (prop == IASTEqualsInitializer.INITIALIZER) {
IASTEqualsInitializer initExp = (IASTEqualsInitializer) parent;
if (initExp.getParent() instanceof IASTDeclarator) {
IASTDeclarator dtor = (IASTDeclarator) initExp.getParent();
targetType= CPPVisitor.createType(dtor);
}
} else if (prop == ICPPASTConstructorInitializer.ARGUMENT) {
ICPPASTConstructorInitializer init = (ICPPASTConstructorInitializer) parent;
if (init.getArguments().length == 1) {
final IASTNode parentOfInit = init.getParent();
if (parentOfInit instanceof IASTDeclarator) {
IASTDeclarator dtor = (IASTDeclarator) parentOfInit;
targetType= CPPVisitor.createType(dtor);
} else if (parentOfInit instanceof ICPPASTConstructorChainInitializer) {
ICPPASTConstructorChainInitializer memInit= (ICPPASTConstructorChainInitializer) parentOfInit;
IBinding var= memInit.getMemberInitializerId().resolveBinding();
if (var instanceof IVariable) {
try {
targetType= ((IVariable) var).getType();
} catch (DOMException e) {
}
}
}
}
} else if (prop == IASTBinaryExpression.OPERAND_TWO) {
IASTBinaryExpression binaryExp = (IASTBinaryExpression) parent;
if (binaryExp.getOperator() == IASTBinaryExpression.op_assign) {
targetType= binaryExp.getOperand1().getExpressionType();
}
} else if (prop == IASTFunctionCallExpression.ARGUMENT) {
// Target is a parameter of a function, need to resolve the function call
IASTFunctionCallExpression fnCall = (IASTFunctionCallExpression) parent;
IType t= SemanticUtil.getNestedType(fnCall.getFunctionNameExpression().getExpressionType(), TDEF|REF|CVTYPE);
if (t instanceof IPointerType) {
t= SemanticUtil.getNestedType(((IPointerType) t).getType(), TDEF | REF | CVTYPE);
}
if (t instanceof IFunctionType) {
int i= 0;
for (IASTNode arg : fnCall.getArguments()) {
if (arg == node) {
IType[] params= ((IFunctionType) t).getParameterTypes();
if (params.length > i) {
targetType= params[i];
}
break;
}
i++;
}
}
} else if (prop == IASTCastExpression.OPERAND) {
// target is an explicit type conversion
IASTCastExpression cast = (IASTCastExpression) parent;
targetType= CPPVisitor.createType(cast.getTypeId().getAbstractDeclarator());
} else if (prop == ICPPASTTemplateId.TEMPLATE_ID_ARGUMENT) {
// target is a template non-type parameter (14.3.2-5)
ICPPASTTemplateId id = (ICPPASTTemplateId) parent;
IASTNode[] args = id.getTemplateArguments();
int i = 0;
for (; i < args.length; i++) {
if (args[i] == node) {
break;
}
oneFromAST= fn;
}
}
if (oneFromAST != null)
return oneFromAST;
if (data.forAssociatedScopes) {
return new CPPCompositeBinding(fns);
}
IBinding result = null;
Object o = getTargetType(data);
IType type, types[] = null;
int idx = -1;
if (o instanceof IType[]) {
types = (IType[]) o;
type = types[++idx];
} else {
type = (IType) o;
}
while (type != null) {
type = getUltimateType(type, false);
if (type == null || !(type instanceof IFunctionType)) {
return new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP,
data.getFoundBindings());
}
for (IBinding fn2 : fns) {
IFunction fn = (IFunction) fn2;
IType ft = null;
try {
ft = fn.getType();
} catch (DOMException e) {
ft = e.getProblem();
}
if (type.isSameType(ft)) {
if (result == null) {
result = fn;
} else {
int c = compareByRelevance(data, result, fn);
if (c < 0) {
result= fn;
} else if (c == 0) {
return new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP,
data.getFoundBindings());
}
}
}
}
if (types != null && ++idx < types.length) {
type = types[idx];
} else {
type = null;
}
}
return result != null ? result :
new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP, data.getFoundBindings());
}
private static Object getTargetType(LookupData data) {
IASTName name = data.astName;
if (name.getPropertyInParent() == ICPPASTQualifiedName.SEGMENT_NAME)
name = (IASTName) name.getParent();
if (name.getPropertyInParent() != IASTIdExpression.ID_NAME)
return null;
IASTIdExpression idExp = (IASTIdExpression) name.getParent();
IASTNode node = idExp;
ASTNodeProperty prop = null;
while (node != null) {
prop = node.getPropertyInParent();
if (prop == IASTDeclarator.INITIALIZER) {
// target is an object or reference being initialized
IASTDeclarator dtor = (IASTDeclarator) node.getParent();
return CPPVisitor.createType(dtor);
} else if (prop == IASTEqualsInitializer.INITIALIZER) {
IASTEqualsInitializer initExp = (IASTEqualsInitializer) node.getParent();
if (initExp.getParent() instanceof IASTDeclarator) {
IASTDeclarator dtor = (IASTDeclarator) initExp.getParent();
return CPPVisitor.createType(dtor);
}
return null;
} else if (prop == IASTBinaryExpression.OPERAND_TWO &&
((IASTBinaryExpression) node.getParent()).getOperator() == IASTBinaryExpression.op_assign) {
// target is the left side of an assignment
IASTBinaryExpression binaryExp = (IASTBinaryExpression) node.getParent();
IASTExpression exp = binaryExp.getOperand1();
return exp.getExpressionType();
} else if (prop == IASTFunctionCallExpression.ARGUMENT) {
// target is a parameter of a function
// if this function call refers to an overloaded function, there is more than one possibility
// for the target type
IASTFunctionCallExpression fnCall = (IASTFunctionCallExpression) node.getParent();
int idx = 0;
final IASTInitializerClause[] arguments = fnCall.getArguments();
for (IASTInitializerClause arg : arguments) {
if (arg == node)
break;
idx++;
IBinding template = id.getTemplateName().resolveBinding();
if (template instanceof ICPPTemplateDefinition) {
try {
ICPPTemplateParameter[] ps = ((ICPPTemplateDefinition) template).getTemplateParameters();
if (i < args.length && i < ps.length && ps[i] instanceof ICPPTemplateNonTypeParameter) {
targetType= ((ICPPTemplateNonTypeParameter) ps[i]).getType();
}
} catch (DOMException e) {
}
if (idx >= arguments.length)
return null;
IFunctionType[] types = getPossibleFunctions(fnCall);
if (types == null)
return null;
IType[] result = null;
for (int i = 0; i < types.length && types[i] != null; i++) {
IType[] pts = null;
pts = types[i].getParameterTypes();
if (pts.length > idx)
result = (IType[]) ArrayUtil.append(IType.class, result, pts[idx]);
}
return result;
} else if (prop == IASTCastExpression.OPERAND) {
// target is an explicit type conversion
IASTCastExpression cast = (IASTCastExpression) node.getParent();
return CPPVisitor.createType(cast.getTypeId().getAbstractDeclarator());
} else if (prop == ICPPASTTemplateId.TEMPLATE_ID_ARGUMENT) {
//target is a template non-type parameter (14.3.2-5)
ICPPASTTemplateId id = (ICPPASTTemplateId) node.getParent();
IASTNode[] args = id.getTemplateArguments();
int i = 0;
for (; i < args.length; i++) {
if (args[i] == node) {
break;
}
}
IBinding template =id.getTemplateName().resolveBinding();
if (template instanceof ICPPTemplateDefinition) {
try {
ICPPTemplateParameter[] ps = ((ICPPTemplateDefinition) template).getTemplateParameters();
if (i < args.length && i < ps.length && ps[i] instanceof ICPPTemplateNonTypeParameter) {
return ((ICPPTemplateNonTypeParameter) ps[i]).getType();
}
} catch (DOMException e) {
return null;
}
}
} else if (prop == IASTReturnStatement.RETURNVALUE) {
// target is the return value of a function, operator or conversion
while (!(node instanceof IASTFunctionDefinition)) {
node = node.getParent();
}
IASTDeclarator dtor = ((IASTFunctionDefinition) node).getDeclarator();
dtor= ASTQueries.findInnermostDeclarator(dtor);
IBinding binding = dtor.getName().resolveBinding();
if (binding instanceof IFunction) {
try {
IFunctionType ft = ((IFunction) binding).getType();
return ft.getReturnType();
} catch (DOMException e) {
}
}
} else if (prop == IASTUnaryExpression.OPERAND) {
IASTUnaryExpression parent = (IASTUnaryExpression) node.getParent();
if (parent.getOperator() == IASTUnaryExpression.op_bracketedPrimary ||
parent.getOperator() == IASTUnaryExpression.op_amper) {
node = parent;
continue;
}
}
break;
}
return null;
}
} else if (prop == IASTReturnStatement.RETURNVALUE) {
// target is the return value of a function, operator or conversion
while (parent != null && !(parent instanceof IASTFunctionDefinition)) {
parent = parent.getParent();
}
if (parent instanceof IASTFunctionDefinition) {
IASTDeclarator dtor = ((IASTFunctionDefinition) parent).getDeclarator();
dtor= ASTQueries.findInnermostDeclarator(dtor);
IBinding binding = dtor.getName().resolveBinding();
if (binding instanceof IFunction) {
try {
IFunctionType ft = ((IFunction) binding).getType();
targetType= ft.getReturnType();
} catch (DOMException e) {
}
}
}
}
if (targetType == null && parent instanceof IASTExpression
&& parent instanceof IASTImplicitNameOwner) {
// Trigger resolution of overloaded operator, which may resolve the
// function set.
((IASTImplicitNameOwner) parent).getImplicitNames();
final IBinding newBinding = name.getPreBinding();
if (!(newBinding instanceof CPPFunctionSet))
return newBinding;
}
ICPPFunction function = resolveTargetedFunction(targetType, name, fns);
if (function == null)
return new ProblemBinding(name, IProblemBinding.SEMANTIC_INVALID_OVERLOAD);
return function;
}
static private IFunctionType[] getPossibleFunctions(IASTFunctionCallExpression call) {
IFunctionType[] result = null;
IASTExpression exp = call.getFunctionNameExpression();
if (exp instanceof IASTIdExpression) {
IASTIdExpression idExp = (IASTIdExpression) exp;
IASTName name = idExp.getName();
LookupData data = createLookupData(name);
try {
lookup(data, null);
} catch (DOMException e) {
return null;
}
final boolean isIndexBased= data.tu != null && data.tu.getIndex() != null;
if (data.hasResults()) {
Object[] items = (Object[]) data.foundItems;
IBinding temp = null;
for (Object o : items) {
if (o == null) break;
if (o instanceof IASTName) {
temp = ((IASTName) o).resolveBinding();
} else if (o instanceof IBinding) {
temp = (IBinding) o;
if (!declaredBefore(temp, name, isIndexBased))
continue;
} else {
continue;
}
try {
if (temp instanceof IFunction) {
result = (IFunctionType[]) ArrayUtil.append(IFunctionType.class, result, ((IFunction) temp).getType());
} else if (temp instanceof IVariable) {
IType type = getUltimateType(((IVariable) temp).getType(), false);
if (type instanceof IFunctionType)
result = (IFunctionType[]) ArrayUtil.append(IFunctionType.class, result, type);
}
} catch (DOMException e) {
}
}
}
} else {
IType type = exp.getExpressionType();
type = getUltimateType(type, false);
if (type instanceof IFunctionType) {
result = new IFunctionType[] { (IFunctionType) type };
}
}
return result;
}
static ICPPFunction resolveTargetedFunction(IType targetType, IASTName name, ICPPFunction[] fns) {
targetType= getNestedType(targetType, TDEF | REF | CVTYPE | PTR | MPTR);
if (!(targetType instanceof ICPPFunctionType))
return null;
// First pass, consider functions
for (ICPPFunction fn : fns) {
try {
if (!(fn instanceof ICPPFunctionTemplate)) {
if (targetType.isSameType(fn.getType()))
return fn;
}
} catch (DOMException e) {
}
}
// Second pass, consider templates
ICPPFunction result= null;
ICPPFunctionTemplate resultTemplate= null;
for (IFunction fn : fns) {
try {
if (fn instanceof ICPPFunctionTemplate) {
final ICPPFunctionTemplate template = (ICPPFunctionTemplate) fn;
ICPPFunction inst= CPPTemplates.instantiateFunctionTemplate(template, (ICPPFunctionType) targetType, name);
if (inst != null) {
int cmp= -1;
if (result != null) {
cmp= CPPTemplates.orderTemplateFunctions(resultTemplate, template);
if (cmp == 0)
return null;
}
if (cmp < 0) {
resultTemplate= template;
result= inst;
}
}
}
} catch (DOMException e) {
}
}
return result;
}
/**
* For a pointer dereference expression e1->e2, return the type that e1 ultimately evaluates to
@ -2790,7 +2802,7 @@ public class CPPSemantics {
}
/*
* Also collections the function bindings if requested.
* Also collects the function bindings if requested.
*/
public static IType getFieldOwnerType(ICPPASTFieldReference fieldReference, Collection<ICPPFunction> functionBindings) throws DOMException {
final IASTExpression owner = fieldReference.getFieldOwner();
@ -2849,9 +2861,10 @@ public class CPPSemantics {
}
public static ICPPFunction findOverloadedOperator(IASTArraySubscriptExpression exp) {
IASTInitializerClause[] args = {exp.getArrayExpression(), exp.getArgument()};
IType type = exp.getArrayExpression().getExpressionType();
type = SemanticUtil.getUltimateTypeUptoPointers(type);
final IASTExpression arrayExpression = exp.getArrayExpression();
IASTInitializerClause[] args = {arrayExpression, exp.getArgument()};
IType type = typeOrFunctionSet(arrayExpression);
type = SemanticUtil.getNestedType(type, TDEF | REF | CVTYPE);
return findOverloadedOperator(exp, args, type, OverloadableOperator.BRACKET, LookupMode.NO_GLOBALS);
}
@ -2871,7 +2884,7 @@ public class CPPSemantics {
OverloadableOperator op = OverloadableOperator.fromNewExpression(exp);
IType type = exp.getExpressionType();
if (type instanceof IProblem)
if (!(type instanceof IPointerType))
return null;
type = ((IPointerType) type).getType();
@ -2964,8 +2977,8 @@ public class CPPSemantics {
ValueCategory isLValue= PRVALUE;
if (initClause instanceof IASTExpression) {
final IASTExpression expr = (IASTExpression) initClause;
isLValue= expr.getValueCategory();
sourceType= SemanticUtil.getSimplifiedType(expr.getExpressionType());
isLValue= valueCat(expr);
sourceType= SemanticUtil.getSimplifiedType(typeOrFunctionSet(expr));
} else if (initClause instanceof ICPPASTInitializerList) {
sourceType= new InitializerListType((ICPPASTInitializerList) initClause);
}
@ -3044,25 +3057,26 @@ public class CPPSemantics {
}
public static ICPPFunction findOverloadedOperator(IASTUnaryExpression exp) {
if (exp.getOperand() == null)
final IASTExpression operand = exp.getOperand();
if (operand == null)
return null;
OverloadableOperator op = OverloadableOperator.fromUnaryExpression(exp);
if (op == null)
return null;
IASTExpression[] args;
int operator = exp.getOperator();
if (operator == IASTUnaryExpression.op_postFixDecr || operator == IASTUnaryExpression.op_postFixIncr)
args = new IASTExpression[] { exp.getOperand(), CPPASTLiteralExpression.INT_ZERO };
else
args = new IASTExpression[] { exp.getOperand() };
IType type = exp.getOperand().getExpressionType();
IType type = typeOrFunctionSet(operand);
type = SemanticUtil.getNestedType(type, TDEF | REF | CVTYPE);
if (!isUserDefined(type))
if (!isUserDefined(type))
return null;
IASTExpression[] args;
int operator = exp.getOperator();
if (operator == IASTUnaryExpression.op_postFixDecr || operator == IASTUnaryExpression.op_postFixIncr) {
args = new IASTExpression[] { operand, CPPASTLiteralExpression.INT_ZERO };
} else {
args = new IASTExpression[] { operand };
}
return findOverloadedOperator(exp, args, type, op, LookupMode.LIMITED_GLOBALS);
}
@ -3076,8 +3090,8 @@ public class CPPSemantics {
if(op2==null){
return null;
}
IType op1type = getNestedType(op1.getExpressionType(), TDEF | REF | CVTYPE);
IType op2type = getNestedType(op2.getExpressionType(), TDEF | REF | CVTYPE);
IType op1type = getNestedType(typeOrFunctionSet(op1), TDEF | REF | CVTYPE);
IType op2type = getNestedType(typeOrFunctionSet(op2), TDEF | REF | CVTYPE);
if (!isUserDefined(op1type) && !isUserDefined(op2type))
return null;
@ -3105,14 +3119,15 @@ public class CPPSemantics {
* Returns the operator,() function that would apply to the two given arguments.
* The lookup type of the class where the operator,() might be found must also be provided.
*/
public static ICPPFunction findOverloadedOperatorComma(IASTExpression first, IASTExpression second, final IType lookupType) {
public static ICPPFunction findOverloadedOperatorComma(IASTExpression first, final IType lookupType, final ValueCategory valueCat, IASTExpression second) {
IType op1type = getNestedType(lookupType, TDEF | REF | CVTYPE);
IType op2type = getNestedType(typeOrFunctionSet(second), TDEF | REF | CVTYPE);
if (!isUserDefined(op1type) && !isUserDefined(op2type))
return null;
IASTUnaryExpression dummy = new CPPASTUnaryExpression() {
@Override public IType getExpressionType() { return lookupType; }
@Override public IASTExpression getOperand() {
return new CPPASTUnaryExpression() {
@Override public IType getExpressionType() { return lookupType; }
};
}
@Override public ValueCategory getValueCategory() { return valueCat; }
};
dummy.setParent(first);
@ -3126,10 +3141,16 @@ public class CPPSemantics {
ICPPClassType callToObjectOfClassType= null;
IType type2= null;
if (args.length >= 2 && args[1] instanceof IASTExpression) {
type2= getUltimateTypeUptoPointers(((IASTExpression) args[1]).getExpressionType());
type2 = typeOrFunctionSet((IASTExpression) args[1]);
type2= getNestedType(type2, TDEF | REF | CVTYPE);
}
if (methodLookupType instanceof ICPPUnknownType || type2 instanceof ICPPUnknownType) {
if (methodLookupType instanceof FunctionSetType)
((FunctionSetType) methodLookupType).setToUnknown();
if (type2 instanceof FunctionSetType)
((FunctionSetType) type2).setToUnknown();
return new CPPUnknownFunction(null, operator.toCharArray());
}
@ -3308,7 +3329,7 @@ public class CPPSemantics {
if (type instanceof IProblemBinding)
return false;
return type instanceof ICPPClassType || type instanceof IEnumeration;
return type instanceof ICPPClassType || type instanceof IEnumeration || type instanceof ICPPUnknownType;
}
public static IBinding[] findBindings(IScope scope, String name, boolean qualified) {

View file

@ -152,6 +152,7 @@ public class CPPTemplates {
private static final int PACK_SIZE_DEFER = -1;
private static final int PACK_SIZE_FAIL = -2;
private static final int PACK_SIZE_NOT_FOUND = Integer.MAX_VALUE;
private static final ICPPFunction[] NO_FUNCTIONS = {};
/**
* Instantiates a class template with the given arguments. May return <code>null</code>.
@ -1515,7 +1516,7 @@ public class CPPTemplates {
* empty IType array is returned if id is <code>null</code>
* @throws DOMException
*/
static public ICPPTemplateArgument[] createTemplateArgumentArray(ICPPASTTemplateId id) throws DOMException {
public static ICPPTemplateArgument[] createTemplateArgumentArray(ICPPASTTemplateId id) throws DOMException {
ICPPTemplateArgument[] result= ICPPTemplateArgument.EMPTY_ARGUMENTS;
if (id != null) {
IASTNode[] params= id.getTemplateArguments();
@ -1537,7 +1538,7 @@ public class CPPTemplates {
return result;
}
static protected void instantiateFunctionTemplates(IFunction[] functions, IType[] allFnArgs,
static ICPPFunction[] instantiateFunctionTemplates(ICPPFunction[] fns, IType[] allFnArgs,
ValueCategory[] allValueCategories, IASTName name, boolean argsContainImpliedObject) {
boolean requireTemplate= false;
if (name != null) {
@ -1552,12 +1553,13 @@ public class CPPTemplates {
IType[] reducedFnArgs= null;
ValueCategory[] reducedValueCategories= null;
ICPPTemplateArgument[] tmplArgs= null;
for (int i = 0; i < functions.length; i++) {
IFunction func = functions[i];
ICPPFunction[] result= fns;
int idx= 0;
for (int i = 0; i < fns.length; i++) {
final ICPPFunction func = fns[i];
ICPPFunction rf= null;
if (func instanceof ICPPFunctionTemplate) {
ICPPFunctionTemplate template= (ICPPFunctionTemplate) func;
functions[i]= null;
final IType[] fnArgs;
final ValueCategory[] valueCategories;
if (argsContainImpliedObject && template instanceof ICPPMethod) {
@ -1583,18 +1585,16 @@ public class CPPTemplates {
tmplArgs = ICPPTemplateArgument.EMPTY_ARGUMENTS;
try {
if (fnArgs == null || containsDependentType(fnArgs)) {
functions[i]= CPPUnknownFunction.createForSample(template);
return;
return new ICPPFunction[] {CPPUnknownFunction.createForSample(template)};
}
if (name instanceof ICPPASTTemplateId && !(template instanceof ICPPConstructor)) {
tmplArgs = createTemplateArgumentArray((ICPPASTTemplateId) name);
if (hasDependentArgument(tmplArgs)) {
functions[i]= CPPUnknownFunction.createForSample(template);
return;
return new ICPPFunction[] {CPPUnknownFunction.createForSample(template)};
}
}
} catch (DOMException e) {
return;
return NO_FUNCTIONS;
}
}
CPPTemplateParameterMap map= new CPPTemplateParameterMap(fnArgs.length);
@ -1602,19 +1602,30 @@ public class CPPTemplates {
ICPPTemplateArgument[] args= TemplateArgumentDeduction.deduceForFunctionCall(template, tmplArgs, fnArgs, valueCategories, map);
if (args != null) {
IBinding instance= instantiateFunctionTemplate(template, args, map);
if (instance instanceof IFunction) {
functions[i]= (IFunction) instance;
if (instance instanceof ICPPFunction) {
rf= (ICPPFunction) instance;
}
}
} catch (DOMException e) {
// try next candidate
}
} else if (requireTemplate
&& !(func instanceof ICPPConstructor) && !(func instanceof ICPPUnknownBinding)
&& !(func instanceof ICPPMethod && ((ICPPMethod) func).isDestructor())) {
functions[i]= null;
}
} else if (!requireTemplate
|| (func instanceof ICPPConstructor) || (func instanceof ICPPUnknownBinding)
|| (func instanceof ICPPMethod && ((ICPPMethod) func).isDestructor())) {
rf= func;
}
if (rf != func || result != fns) {
if (result == fns) {
result= new ICPPFunction[fns.length-(i-idx)];
System.arraycopy(fns, 0, result, 0, idx);
}
if (rf != null)
result[idx]= rf;
}
if (rf != null)
idx++;
}
return result;
}
static protected void instantiateConversionTemplates(IFunction[] functions, IType conversionType) {
@ -1653,6 +1664,42 @@ public class CPPTemplates {
}
}
/**
* 14.8.2.2 Deducing template arguments taking the address of a function template [temp.deduct.funcaddr]
*/
static protected ICPPFunction instantiateFunctionTemplate(ICPPFunctionTemplate template, IFunctionType target, IASTName name) {
if (name.getPropertyInParent() == ICPPASTTemplateId.TEMPLATE_NAME) {
name= (IASTName) name.getParent();
}
try {
if (isDependentType(target)) {
return CPPUnknownFunction.createForSample(template);
}
ICPPTemplateArgument[] tmplArgs;
if (name instanceof ICPPASTTemplateId && !(template instanceof ICPPConstructor)) {
tmplArgs = createTemplateArgumentArray((ICPPASTTemplateId) name);
if (hasDependentArgument(tmplArgs)) {
return CPPUnknownFunction.createForSample(template);
}
} else {
tmplArgs= ICPPTemplateArgument.EMPTY_ARGUMENTS;
}
CPPTemplateParameterMap map= new CPPTemplateParameterMap(4);
ICPPTemplateArgument[] args= TemplateArgumentDeduction.deduceForAddressOf(template, tmplArgs, target, map);
if (args != null) {
IBinding instance= instantiateFunctionTemplate(template, args, map);
if (instance instanceof ICPPFunction) {
return (ICPPFunction) instance;
}
}
} catch (DOMException e) {
}
return null;
}
/**
* Transforms a function template for use in partial ordering, as described in the
* spec 14.5.5.2-3

View file

@ -41,6 +41,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPBasicType;
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.ICPPEnumeration;
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.ICPPMethod;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace;
@ -668,14 +669,18 @@ public class Conversions {
FunctionCost cost1= null;
Cost cost2= null;
ICPPConstructor[] ctors= t.getConstructors();
CPPTemplates.instantiateFunctionTemplates(ctors, new IType[]{source}, new ValueCategory[] {valueCat}, null, false);
ICPPFunction[] ctors= t.getConstructors();
ctors= CPPTemplates.instantiateFunctionTemplates(ctors, new IType[]{source}, new ValueCategory[] {valueCat}, null, false);
for (ICPPConstructor ctor : ctors) {
for (ICPPFunction f : ctors) {
if (!(f instanceof ICPPConstructor) || f instanceof IProblemBinding)
continue;
ICPPConstructor ctor= (ICPPConstructor) f;
// Note: the special case of initializing a temporary to be bound to the first parameter
// of a copy constructor called with a single argument in the context of direct-initialization
// is (more naturally) handled in initializationByConversionForDirectReference.
if (ctor != null && !(ctor instanceof IProblemBinding) && !ctor.isExplicit()) {
if (!ctor.isExplicit()) {
final ICPPFunctionType ft = ctor.getType();
final IType[] ptypes = ft.getParameterTypes();
FunctionCost c1;

View file

@ -89,6 +89,7 @@ public class Cost {
private ReferenceBinding fReferenceBinding;
private boolean fCouldNarrow;
private ICPPFunction fSelectedFunction; // For targeted functions
public Cost(IType s, IType t, Rank rank) {
source = s;
@ -266,4 +267,15 @@ public class Cost {
public ICPPFunction getUserDefinedConversion() {
return fUserDefinedConversion;
}
/**
* Stores a selected function. Used when resolving targeted functions.
*/
public void setSelectedFunction(ICPPFunction function) {
fSelectedFunction= function;
}
public ICPPFunction getSelectedFunction() {
return fSelectedFunction;
}
}

View file

@ -15,7 +15,12 @@ import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUti
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.TDEF;
import org.eclipse.cdt.core.dom.ast.DOMException;
import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory;
import org.eclipse.cdt.core.dom.ast.IASTIdExpression;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression;
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.cpp.ICPPFunction;
@ -77,5 +82,46 @@ public class ExpressionTypes {
return glvalueType(r);
}
return prvalueType(r);
}
public static IType typeOrFunctionSet(IASTExpression e) {
FunctionSetType fs= getFunctionSetType(e);
if (fs != null) {
return fs;
}
return e.getExpressionType();
}
public static ValueCategory valueCat(IASTExpression e) {
FunctionSetType fs= getFunctionSetType(e);
if (fs != null)
return fs.getValueCategory();
return e.getValueCategory();
}
private static FunctionSetType getFunctionSetType(IASTExpression e) {
boolean addressOf= false;
while (e instanceof IASTUnaryExpression) {
final IASTUnaryExpression unary = (IASTUnaryExpression) e;
final int op= unary.getOperator();
if (op == IASTUnaryExpression.op_bracketedPrimary) {
e= unary.getOperand();
} else if (!addressOf && op == IASTUnaryExpression.op_amper) {
addressOf= true;
e= unary.getOperand();
} else {
break;
}
}
if (e instanceof IASTIdExpression) {
IASTIdExpression idexpr= (IASTIdExpression) e;
final IASTName name = idexpr.getName();
IBinding b= name.resolvePreBinding();
if (b instanceof CPPFunctionSet) {
return new FunctionSetType(((CPPFunctionSet) b).getBindings(), name, addressOf);
}
}
return null;
}
}

View file

@ -0,0 +1,73 @@
/*
* FunctionSetType.java
* Created on Sep 14, 2010
*
* Copyright 2010 Wind River Systems, Inc. All rights reserved.
*/
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
import static org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory.LVALUE;
import static org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory.PRVALUE;
import org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IProblemBinding;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUnknownFunction;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Cost.Rank;
/**
* Used during overload resolution as a place-holder for function sets.
*/
public class FunctionSetType implements IType {
private ICPPFunction[] fFunctionSet;
private boolean fPointerType;
private IASTName fName;
public FunctionSetType(ICPPFunction[] functions, IASTName name, boolean addressOf) {
fName= name;
fFunctionSet= functions;
fPointerType= addressOf;
}
public boolean isSameType(IType type) {
return type == this;
}
@Override
public Object clone() {
throw new UnsupportedOperationException();
}
public ValueCategory getValueCategory() {
return fPointerType ? PRVALUE : LVALUE;
}
public Cost costForTarget(IType paramType) {
IBinding result = CPPSemantics.resolveTargetedFunction(paramType, fName, fFunctionSet);
if (result instanceof ICPPFunction && !(result instanceof IProblemBinding)) {
Cost c= new Cost(paramType, paramType, Rank.IDENTITY);
c.setSelectedFunction((ICPPFunction) result);
return c;
}
return Cost.NO_CONVERSION;
}
public void applySelectedFunction(ICPPFunction selectedFunction) {
if (selectedFunction != null) {
fName.setBinding(selectedFunction);
}
}
public ICPPFunction[] getFunctionSet() {
return fFunctionSet;
}
public void setToUnknown() {
fName.setBinding(new CPPUnknownFunction(null, fName.toCharArray()));
}
}

View file

@ -15,6 +15,7 @@
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExpressionTypes.valueCategoryFromReturnType;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.getSimplifiedType;
import java.util.Collections;
import java.util.List;
@ -509,8 +510,9 @@ public class LookupData {
for (int i = 0; i < exprs.length; i++) {
IASTInitializerClause e = exprs[i];
if (e instanceof IASTExpression) {
IType etype= ((IASTExpression) e).getExpressionType();
functionArgTypes[i]= SemanticUtil.getSimplifiedType(etype);
// Find function set when taking an address of a function
final IType t = ExpressionTypes.typeOrFunctionSet((IASTExpression) e);
functionArgTypes[i]= getSimplifiedType(t);
} else if (e instanceof ICPPASTInitializerList) {
functionArgTypes[i]= new InitializerListType((ICPPASTInitializerList) e);
}
@ -535,7 +537,7 @@ public class LookupData {
for (int i = 0; i < args.length; i++) {
final IASTInitializerClause arg = args[i];
if (arg instanceof IASTExpression) {
functionArgValueCategories[i]= ((IASTExpression) arg).getValueCategory();
functionArgValueCategories[i] = ExpressionTypes.valueCat((IASTExpression) arg);
}
}
} else {

View file

@ -118,6 +118,87 @@ public class TemplateArgumentDeduction {
return result.toArray(new ICPPTemplateArgument[result.size()]);
}
/**
* 14.8.2.2 [temp.deduct.funcaddr]
* Deducing template arguments taking the address of a function template
* @throws DOMException
*/
static ICPPTemplateArgument[] deduceForAddressOf(ICPPFunctionTemplate template,
ICPPTemplateArgument[] tmplArgs, IFunctionType arg, CPPTemplateParameterMap map) throws DOMException {
final ICPPTemplateParameter[] tmplParams = template.getTemplateParameters();
final int numTmplParams = tmplParams.length;
final int numTmplArgs = tmplArgs.length;
tmplArgs= SemanticUtil.getSimplifiedArguments(tmplArgs);
ICPPTemplateParameter tmplParam= null;
int packOffset= -1;
for (int i = 0; i < numTmplArgs; i++) {
if (packOffset < 0 || tmplParam == null) {
if (i >= numTmplParams)
return null;
tmplParam= tmplParams[i];
if (tmplParam.isParameterPack()) {
packOffset= i;
}
}
ICPPTemplateArgument tmplArg= tmplArgs[i];
tmplArg= CPPTemplates.matchTemplateParameterAndArgument(tmplParam, tmplArg, map);
if (tmplArg == null)
return null;
if (packOffset < 0) {
map.put(tmplParam, tmplArg);
}
}
if (packOffset >= 0) {
final int packSize= tmplArgs.length- packOffset;
ICPPTemplateArgument[] pack= new ICPPTemplateArgument[packSize];
System.arraycopy(tmplArgs, packOffset, pack, 0, packSize);
map.put(tmplParam, pack);
}
IType par= template.getType();
par= CPPTemplates.instantiateType(par, map, -1, null);
if (!CPPTemplates.isValidType(par))
return null;
boolean isDependentPar= CPPTemplates.isDependentType(par);
if (isDependentPar) {
TemplateArgumentDeduction deduct= new TemplateArgumentDeduction(tmplParams, map, new CPPTemplateParameterMap(tmplParams.length), 0);
par= SemanticUtil.getNestedType(par, SemanticUtil.TDEF);
if (!deduct.fromType(par, arg, false))
return null;
if (!map.mergeToExplicit(deduct.fDeducedArgs))
return null;
if (!verifyDeduction(tmplParams, map, true))
return null;
par= CPPTemplates.instantiateType(par, map, -1, null);
}
if (arg.isSameType(par)) {
List<ICPPTemplateArgument> result= new ArrayList<ICPPTemplateArgument>(numTmplParams);
for (ICPPTemplateParameter tpar : tmplParams) {
if (tpar.isParameterPack()) {
ICPPTemplateArgument[] deducedArgs= map.getPackExpansion(tpar);
if (deducedArgs == null)
return null;
result.addAll(Arrays.asList(deducedArgs));
} else {
ICPPTemplateArgument deducedArg= map.getArgument(tpar);
if (deducedArg == null)
return null;
result.add(deducedArg);
}
}
return result.toArray(new ICPPTemplateArgument[result.size()]);
}
return null;
}
/**
* Deduce arguments for a user defined conversion template
* 14.8.2.3