1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-22 06:02:11 +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 {
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);
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;

View file

@ -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) {

View file

@ -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;

View file

@ -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) {