diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/ASTCPPSpecDefectTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/ASTCPPSpecDefectTests.java index c5e82ec6c19..80914d4e308 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/ASTCPPSpecDefectTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/ASTCPPSpecDefectTests.java @@ -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(); } } diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPTemplateResolutionTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPTemplateResolutionTest.java index 4e15f7cef25..01a2b7bc090 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPTemplateResolutionTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPTemplateResolutionTest.java @@ -445,7 +445,7 @@ public class IndexCPPTemplateResolutionTest extends IndexBindingResolutionTestBa // A a; // a.f= foo; // } - public void _testOverloadedFunctionTemplate() { + public void testOverloadedFunctionTemplate() { IBinding b0= getBindingFromASTName("foo;", 6); assertInstance(b0, ICPPFunction.class); assertInstance(b0, ICPPSpecialization.class); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTConditionalExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTConditionalExpression.java index 3c293e8505b..293d23976bb 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTConditionalExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTConditionalExpression.java @@ -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 diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTExpressionList.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTExpressionList.java index 3ef72524c25..96ecd9e047c 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTExpressionList.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTExpressionList.java @@ -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); } - } + } } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTIdExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTIdExpression.java index 086c2aa0173..a61e0ca86d9 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTIdExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTIdExpression.java @@ -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(); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPUnknownFunction.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPUnknownFunction.java index 183fc520df6..15fdf0453b0 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPUnknownFunction.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPUnknownFunction.java @@ -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()); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/BuiltinOperators.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/BuiltinOperators.java index bd7e20c2c76..7b15b2fee19 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/BuiltinOperators.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/BuiltinOperators.java @@ -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; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPFunctionSet.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPFunctionSet.java new file mode 100644 index 00000000000..f6a714cf3d6 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPFunctionSet.java @@ -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; + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java index 25192d765c3..6cfdd585447 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java @@ -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 getAssociatedScopes(LookupData data) { + private static Set 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 namespaces, + private static void getAssociatedScopes(IType t, Set namespaces, ObjectSet 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 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 set = new ObjectSet(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 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 fns= ObjectSet.EMPTY_SET; + ObjectSet 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(2); - fns.put((IFunction) temp); + fns = new ObjectSet(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(); @@ -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 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) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java index b2107373433..8938438e84a 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java @@ -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 null. @@ -1515,7 +1516,7 @@ public class CPPTemplates { * empty IType array is returned if id is null * @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 diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Conversions.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Conversions.java index 77c21f12f98..81040d55f15 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Conversions.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Conversions.java @@ -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; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Cost.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Cost.java index 639bf3d3f51..e1c735a4bf8 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Cost.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Cost.java @@ -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; + } } \ No newline at end of file diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExpressionTypes.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExpressionTypes.java index e1eedd416ac..1cd2795bc07 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExpressionTypes.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExpressionTypes.java @@ -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; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/FunctionSetType.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/FunctionSetType.java new file mode 100644 index 00000000000..b6c39944c15 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/FunctionSetType.java @@ -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())); + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/LookupData.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/LookupData.java index e12ed82da51..ecea5e21ff3 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/LookupData.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/LookupData.java @@ -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 { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/TemplateArgumentDeduction.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/TemplateArgumentDeduction.java index be396a2bc2a..a2398fe9236 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/TemplateArgumentDeduction.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/TemplateArgumentDeduction.java @@ -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 result= new ArrayList(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