1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-21 21:52:10 +02:00

Bug 541474 - Disambiguate function with default argument

Take number of explicitly passed arguments into account.

Change-Id: If85f072d8b18f3fd1ca28f3c5688e864b0ffb4cd
Signed-off-by: Hannes Vogt <hannes@havogt.de>
This commit is contained in:
Hannes Vogt 2018-11-25 23:22:00 +01:00 committed by Nathan Ridge
parent 586ccf790b
commit 8f9e8f045c
5 changed files with 95 additions and 18 deletions

View file

@ -11122,4 +11122,65 @@ public class AST2TemplateTests extends AST2CPPTestBase {
public void testParameterPackInAliasTemplateArgs_540741() throws Exception { public void testParameterPackInAliasTemplateArgs_540741() throws Exception {
parseAndCheckBindings(); parseAndCheckBindings();
} }
// template <class T>
// void foo(T = {});
//
// template <class U>
// void foo(U*); // more specialized
//
// int main() {
// int* p;
// foo(p);
// }
public void testDisambiguateFunctionWithDefaultArgument_541474() throws Exception {
parseAndCheckBindings();
}
// template <class T>
// void foo(T = {});
//
// template <class U>
// 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 <typename T>
// A(T = {});
//
// template <typename U>
// 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 <class T>
// void foo(T = {});
//
// template <class U>
// 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();
}
} }

View file

@ -2733,7 +2733,7 @@ public class CPPSemantics {
potentialCosts.add(fnCost); potentialCosts.add(fnCost);
continue; continue;
} }
int cmp = fnCost.compareTo(tu, bestFnCost); int cmp = fnCost.compareTo(tu, bestFnCost, data.getFunctionArgumentCount());
if (cmp < 0) { if (cmp < 0) {
bestFnCost = fnCost; bestFnCost = fnCost;
ambiguousFunctions = null; ambiguousFunctions = null;
@ -2745,7 +2745,7 @@ public class CPPSemantics {
if (potentialCosts != null) { if (potentialCosts != null) {
for (FunctionCost fnCost : potentialCosts) { for (FunctionCost fnCost : potentialCosts) {
if (!fnCost.mustBeWorse(bestFnCost) && fnCost.performUDC()) { if (!fnCost.mustBeWorse(bestFnCost) && fnCost.performUDC()) {
int cmp = fnCost.compareTo(tu, bestFnCost); int cmp = fnCost.compareTo(tu, bestFnCost, data.getFunctionArgumentCount());
if (cmp < 0) { if (cmp < 0) {
bestFnCost = fnCost; bestFnCost = fnCost;
ambiguousFunctions = null; ambiguousFunctions = null;

View file

@ -2502,9 +2502,19 @@ public class CPPTemplates {
return null; return null;
} }
// 14.5.6.2 Partial ordering of function templates /**
static int orderFunctionTemplates(ICPPFunctionTemplate f1, ICPPFunctionTemplate f2, TypeSelection mode) * 14.5.6.2 Partial ordering of function templates
throws DOMException { *
* @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) if (f1 == f2)
return 0; return 0;
if (f1 == null) if (f1 == null)
@ -2512,8 +2522,8 @@ public class CPPTemplates {
if (f2 == null) if (f2 == null)
return 1; return 1;
int s1 = compareSpecialization(f1, f2, mode); int s1 = compareSpecialization(f1, f2, mode, nExplicitArgs);
int s2 = compareSpecialization(f2, f1, mode); int s2 = compareSpecialization(f2, f1, mode, nExplicitArgs);
if (s1 == s2) if (s1 == s2)
return 0; return 0;
@ -2523,6 +2533,11 @@ public class CPPTemplates {
return 1; 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 { private static ICPPFunction transferFunctionTemplate(ICPPFunctionTemplate f) throws DOMException {
final ICPPTemplateParameter[] tpars = f.getTemplateParameters(); final ICPPTemplateParameter[] tpars = f.getTemplateParameters();
final int argLen = tpars.length; final int argLen = tpars.length;
@ -2559,13 +2574,14 @@ public class CPPTemplates {
return arg; return arg;
} }
private static ICPPFunctionType getFunctionTypeIgnoringParametersWithDefaults(ICPPFunction function) { private static ICPPFunctionType getFunctionTypeIgnoringParametersWithDefaults(ICPPFunction function,
int nExplicitArgs) {
ICPPParameter[] parameters = function.getParameters(); ICPPParameter[] parameters = function.getParameters();
IType[] parameterTypes = new IType[parameters.length]; IType[] parameterTypes = new IType[parameters.length];
int i; int i;
for (i = 0; i < parameters.length; ++i) { for (i = 0; i < parameters.length; ++i) {
ICPPParameter parameter = parameters[i]; ICPPParameter parameter = parameters[i];
if (!parameter.hasDefaultValue()) { if (i < nExplicitArgs || !parameter.hasDefaultValue()) {
parameterTypes[i] = parameter.getType(); parameterTypes[i] = parameter.getType();
} else { } else {
break; break;
@ -2579,8 +2595,8 @@ public class CPPTemplates {
originalType.takesVarArgs()); originalType.takesVarArgs());
} }
private static int compareSpecialization(ICPPFunctionTemplate f1, ICPPFunctionTemplate f2, TypeSelection mode) private static int compareSpecialization(ICPPFunctionTemplate f1, ICPPFunctionTemplate f2, TypeSelection mode,
throws DOMException { int nExplicitArgs) throws DOMException {
ICPPFunction transF1 = transferFunctionTemplate(f1); ICPPFunction transF1 = transferFunctionTemplate(f1);
if (transF1 == null) if (transF1 == null)
return -1; return -1;
@ -2588,7 +2604,7 @@ public class CPPTemplates {
final ICPPFunctionType ft2 = f2.getType(); final ICPPFunctionType ft2 = f2.getType();
// Ignore parameters with default arguments in the transformed function template // Ignore parameters with default arguments in the transformed function template
// as per [temp.func.order] p5. // as per [temp.func.order] p5.
final ICPPFunctionType transFt1 = getFunctionTypeIgnoringParametersWithDefaults(transF1); final ICPPFunctionType transFt1 = getFunctionTypeIgnoringParametersWithDefaults(transF1, nExplicitArgs);
IType[] pars; IType[] pars;
IType[] args; IType[] args;
switch (mode) { switch (mode) {

View file

@ -269,7 +269,7 @@ public class Conversions {
// Make sure top-level cv-qualifiers are compared // Make sure top-level cv-qualifiers are compared
udcCost.setReferenceBinding(ReferenceBinding.LVALUE_REF); udcCost.setReferenceBinding(ReferenceBinding.LVALUE_REF);
FunctionCost udcFuncCost = new FunctionCost(op, udcCost); FunctionCost udcFuncCost = new FunctionCost(op, udcCost);
int cmp = udcFuncCost.compareTo(null, bestUdcCost); int cmp = udcFuncCost.compareTo(null, bestUdcCost, 1);
if (cmp <= 0) { if (cmp <= 0) {
Cost cost = isReferenceCompatible(cv1T1, getNestedType(t, TDEF | REF), false); // converted to target Cost cost = isReferenceCompatible(cv1T1, getNestedType(t, TDEF | REF), false); // converted to target
if (cost != null) { if (cost != null) {
@ -794,7 +794,7 @@ public class Conversions {
c1 = new FunctionCost(ctor, checkImplicitConversionSequence(ptype, source, valueCat, c1 = new FunctionCost(ctor, checkImplicitConversionSequence(ptype, source, valueCat,
UDCMode.FORBIDDEN, Context.ORDINARY)); UDCMode.FORBIDDEN, Context.ORDINARY));
} }
int cmp = c1.compareTo(null, cost1); int cmp = c1.compareTo(null, cost1, 1);
if (cmp <= 0) { if (cmp <= 0) {
cost1 = c1; cost1 = c1;
cost2 = new Cost(t, t, Rank.IDENTITY); cost2 = new Cost(t, t, Rank.IDENTITY);
@ -826,7 +826,7 @@ public class Conversions {
// Make sure top-level cv-qualifiers are compared // Make sure top-level cv-qualifiers are compared
udcCost.setReferenceBinding(ReferenceBinding.LVALUE_REF); udcCost.setReferenceBinding(ReferenceBinding.LVALUE_REF);
FunctionCost c1 = new FunctionCost(op, udcCost); FunctionCost c1 = new FunctionCost(op, udcCost);
int cmp = c1.compareTo(null, cost1); int cmp = c1.compareTo(null, cost1, 1);
if (cmp <= 0) { if (cmp <= 0) {
cost1 = c1; cost1 = c1;
cost2 = new Cost(t, t, Rank.IDENTITY); cost2 = new Cost(t, t, Rank.IDENTITY);
@ -890,7 +890,7 @@ public class Conversions {
udcCost.setReferenceBinding(ReferenceBinding.LVALUE_REF); udcCost.setReferenceBinding(ReferenceBinding.LVALUE_REF);
} }
FunctionCost c1 = new FunctionCost(op, udcCost); FunctionCost c1 = new FunctionCost(op, udcCost);
int cmp = c1.compareTo(null, cost1); int cmp = c1.compareTo(null, cost1, 1);
if (cmp <= 0) { if (cmp <= 0) {
cost1 = c1; cost1 = c1;
cost2 = c2; cost2 = c2;

View file

@ -140,7 +140,7 @@ class FunctionCost {
/** /**
* Compares this function call cost to another one. * 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) if (other == null)
return -1; return -1;
@ -180,7 +180,7 @@ class FunctionCost {
haveBetter = true; haveBetter = true;
} else if (isTemplate && otherIsTemplate) { } else if (isTemplate && otherIsTemplate) {
TypeSelection ts = SemanticUtil.isConversionOperator(f1) ? RETURN_TYPE : PARAMETERS; 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) { if (order < 0) {
haveBetter = true; haveBetter = true;
} else if (order > 0) { } else if (order > 0) {