diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java index 06641c1293a..fb2861ea67d 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java @@ -11122,4 +11122,65 @@ public class AST2TemplateTests extends AST2CPPTestBase { public void testParameterPackInAliasTemplateArgs_540741() throws Exception { parseAndCheckBindings(); } + + // template + // void foo(T = {}); + // + // template + // void foo(U*); // more specialized + // + // int main() { + // int* p; + // foo(p); + // } + public void testDisambiguateFunctionWithDefaultArgument_541474() throws Exception { + parseAndCheckBindings(); + } + + // template + // void foo(T = {}); + // + // template + // void foo(U*); // more specialized + // + // // Which one is this an explicit spec. of? + // template <> + // void foo(int*); + public void testDisambiguateFunctionWithDefaultArgumentExplicitInstantiation_541474() throws Exception { + parseAndCheckBindings(); + } + + // struct A { + // template + // A(T = {}); + // + // template + // A(U*); // more specialized + // }; + // + // void bar(A); + // + // void foo() { + // int* p; + // // Which constructor is used for the conversion? + // bar(p); + // } + public void testDisambiguateFunctionWithDefaultArgumentConversion_541474() throws Exception { + parseAndCheckBindings(); + } + + // template + // void foo(T = {}); + // + // template + // void foo(U*); // more specialized + // + // int main() { + // using FPtr = void(*)(int*); + // // Which one are we taking the address of? + // FPtr x = &foo; + // } + public void testDisambiguateFunctionWithDefaultArgumentDeclaration_541474() throws Exception { + parseAndCheckBindings(); + } } 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 d4e6b667c63..2299b6b5dc5 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 @@ -2733,7 +2733,7 @@ public class CPPSemantics { potentialCosts.add(fnCost); continue; } - int cmp = fnCost.compareTo(tu, bestFnCost); + int cmp = fnCost.compareTo(tu, bestFnCost, data.getFunctionArgumentCount()); if (cmp < 0) { bestFnCost = fnCost; ambiguousFunctions = null; @@ -2745,7 +2745,7 @@ public class CPPSemantics { if (potentialCosts != null) { for (FunctionCost fnCost : potentialCosts) { if (!fnCost.mustBeWorse(bestFnCost) && fnCost.performUDC()) { - int cmp = fnCost.compareTo(tu, bestFnCost); + int cmp = fnCost.compareTo(tu, bestFnCost, data.getFunctionArgumentCount()); if (cmp < 0) { bestFnCost = fnCost; ambiguousFunctions = null; 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 a2b17c0e9fd..0c6e1954ffd 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 @@ -2502,9 +2502,19 @@ public class CPPTemplates { return null; } - // 14.5.6.2 Partial ordering of function templates - static int orderFunctionTemplates(ICPPFunctionTemplate f1, ICPPFunctionTemplate f2, TypeSelection mode) - throws DOMException { + /** + * 14.5.6.2 Partial ordering of function templates + * + * @param f1 + * @param f2 + * @param mode + * @param nExplicitArgs determines the number of parameters taken into consideration for ordering: + * for ordering in the context of a call, nExplicitArguments should be the number of arguments in the call + * for ordering in other contexts, nExplicitArguments should be Integer.MAX_VALUE to indicate + * that all parameters should be considered + */ + static int orderFunctionTemplates(ICPPFunctionTemplate f1, ICPPFunctionTemplate f2, TypeSelection mode, + int nExplicitArgs) throws DOMException { if (f1 == f2) return 0; if (f1 == null) @@ -2512,8 +2522,8 @@ public class CPPTemplates { if (f2 == null) return 1; - int s1 = compareSpecialization(f1, f2, mode); - int s2 = compareSpecialization(f2, f1, mode); + int s1 = compareSpecialization(f1, f2, mode, nExplicitArgs); + int s2 = compareSpecialization(f2, f1, mode, nExplicitArgs); if (s1 == s2) return 0; @@ -2523,6 +2533,11 @@ public class CPPTemplates { return 1; } + static int orderFunctionTemplates(ICPPFunctionTemplate f1, ICPPFunctionTemplate f2, TypeSelection mode) + throws DOMException { + return orderFunctionTemplates(f1, f2, mode, Integer.MAX_VALUE); + } + private static ICPPFunction transferFunctionTemplate(ICPPFunctionTemplate f) throws DOMException { final ICPPTemplateParameter[] tpars = f.getTemplateParameters(); final int argLen = tpars.length; @@ -2559,13 +2574,14 @@ public class CPPTemplates { return arg; } - private static ICPPFunctionType getFunctionTypeIgnoringParametersWithDefaults(ICPPFunction function) { + private static ICPPFunctionType getFunctionTypeIgnoringParametersWithDefaults(ICPPFunction function, + int nExplicitArgs) { ICPPParameter[] parameters = function.getParameters(); IType[] parameterTypes = new IType[parameters.length]; int i; for (i = 0; i < parameters.length; ++i) { ICPPParameter parameter = parameters[i]; - if (!parameter.hasDefaultValue()) { + if (i < nExplicitArgs || !parameter.hasDefaultValue()) { parameterTypes[i] = parameter.getType(); } else { break; @@ -2579,8 +2595,8 @@ public class CPPTemplates { originalType.takesVarArgs()); } - private static int compareSpecialization(ICPPFunctionTemplate f1, ICPPFunctionTemplate f2, TypeSelection mode) - throws DOMException { + private static int compareSpecialization(ICPPFunctionTemplate f1, ICPPFunctionTemplate f2, TypeSelection mode, + int nExplicitArgs) throws DOMException { ICPPFunction transF1 = transferFunctionTemplate(f1); if (transF1 == null) return -1; @@ -2588,7 +2604,7 @@ public class CPPTemplates { final ICPPFunctionType ft2 = f2.getType(); // Ignore parameters with default arguments in the transformed function template // as per [temp.func.order] p5. - final ICPPFunctionType transFt1 = getFunctionTypeIgnoringParametersWithDefaults(transF1); + final ICPPFunctionType transFt1 = getFunctionTypeIgnoringParametersWithDefaults(transF1, nExplicitArgs); IType[] pars; IType[] args; switch (mode) { 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 707ff7bd7e0..14470e681b2 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 @@ -269,7 +269,7 @@ public class Conversions { // Make sure top-level cv-qualifiers are compared udcCost.setReferenceBinding(ReferenceBinding.LVALUE_REF); FunctionCost udcFuncCost = new FunctionCost(op, udcCost); - int cmp = udcFuncCost.compareTo(null, bestUdcCost); + int cmp = udcFuncCost.compareTo(null, bestUdcCost, 1); if (cmp <= 0) { Cost cost = isReferenceCompatible(cv1T1, getNestedType(t, TDEF | REF), false); // converted to target if (cost != null) { @@ -794,7 +794,7 @@ public class Conversions { c1 = new FunctionCost(ctor, checkImplicitConversionSequence(ptype, source, valueCat, UDCMode.FORBIDDEN, Context.ORDINARY)); } - int cmp = c1.compareTo(null, cost1); + int cmp = c1.compareTo(null, cost1, 1); if (cmp <= 0) { cost1 = c1; cost2 = new Cost(t, t, Rank.IDENTITY); @@ -826,7 +826,7 @@ public class Conversions { // Make sure top-level cv-qualifiers are compared udcCost.setReferenceBinding(ReferenceBinding.LVALUE_REF); FunctionCost c1 = new FunctionCost(op, udcCost); - int cmp = c1.compareTo(null, cost1); + int cmp = c1.compareTo(null, cost1, 1); if (cmp <= 0) { cost1 = c1; cost2 = new Cost(t, t, Rank.IDENTITY); @@ -890,7 +890,7 @@ public class Conversions { udcCost.setReferenceBinding(ReferenceBinding.LVALUE_REF); } FunctionCost c1 = new FunctionCost(op, udcCost); - int cmp = c1.compareTo(null, cost1); + int cmp = c1.compareTo(null, cost1, 1); if (cmp <= 0) { cost1 = c1; cost2 = c2; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/FunctionCost.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/FunctionCost.java index a4833904dca..1044779f327 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/FunctionCost.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/FunctionCost.java @@ -140,7 +140,7 @@ class FunctionCost { /** * Compares this function call cost to another one. */ - public int compareTo(IASTTranslationUnit tu, FunctionCost other) throws DOMException { + public int compareTo(IASTTranslationUnit tu, FunctionCost other, int nArguments) throws DOMException { if (other == null) return -1; @@ -180,7 +180,7 @@ class FunctionCost { haveBetter = true; } else if (isTemplate && otherIsTemplate) { TypeSelection ts = SemanticUtil.isConversionOperator(f1) ? RETURN_TYPE : PARAMETERS; - int order = CPPTemplates.orderFunctionTemplates(otherAsTemplate, asTemplate, ts); + int order = CPPTemplates.orderFunctionTemplates(otherAsTemplate, asTemplate, ts, nArguments); if (order < 0) { haveBetter = true; } else if (order > 0) {