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 {
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue