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:
parent
586ccf790b
commit
8f9e8f045c
5 changed files with 95 additions and 18 deletions
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Add table
Reference in a new issue