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

Bug 541717 - Partial ordering and DR1395

- As of [temp.func.order] p5 only parameters for which there are explicit
arguments should be considered.
- Implement [temp.deduct.partial] p11 (resolution of DR1395).

Change-Id: I56262229a6fe4717c22aac814aa9ea42eb37a10d
Signed-off-by: Hannes Vogt <hannes@havogt.de>
This commit is contained in:
Hannes Vogt 2018-12-02 21:43:18 +01:00
parent 12207e79db
commit 2fc42590fb
2 changed files with 100 additions and 23 deletions

View file

@ -4816,8 +4816,16 @@ public class AST2TemplateTests extends AST2CPPTestBase {
// int main() {
// foo(0);
// }
public void testFunctionTemplateOrdering_388805() throws Exception {
parseAndCheckBindings();
public void testFunctionTemplateOrdering_DR1395_388805() throws Exception {
String code = getAboveComment();
BindingAssertionHelper bh = new AST2AssertionHelper(code, CPP);
ICPPFunctionTemplate f1 = bh.assertNonProblem("foo(A)", 3);
ICPPFunctionTemplate f2 = bh.assertNonProblem("foo(A, B...)", 3);
ICPPTemplateInstance t;
t = bh.assertNonProblem("foo(0)", 3);
assertSame(f1, t.getTemplateDefinition());
}
// template <typename T>
@ -11200,4 +11208,56 @@ public class AST2TemplateTests extends AST2CPPTestBase {
public void testDisambiguateFunctionWithDefaultArgumentDeclaration_541474() throws Exception {
parseAndCheckBindings();
}
// template<typename T>
// void info(T a) {
// }
// template<typename... Args>
// void info(int a, Args... args) {
// // this is more specialized
// }
// int main( ) {
// info(1);
// }
public void testDisambiguateFunctionUnusedPack_541474() throws Exception {
parseAndCheckBindings();
}
// template<typename A, typename B = int>
// void foo(A, B=0); // this overload is taken
//
// template<typename A, typename... B>
// void foo(A, B...);
//
// int main() {
// foo(0);
// }
public void testDisambiguateFunctionUnusedPackVsDefault_541474() throws Exception {
String code = getAboveComment();
BindingAssertionHelper bh = new AST2AssertionHelper(code, CPP);
ICPPFunctionTemplate f1 = bh.assertNonProblem("foo(A, B=0)", 3);
ICPPFunctionTemplate f2 = bh.assertNonProblem("foo(A, B...)", 3);
ICPPTemplateInstance t;
t = bh.assertNonProblem("foo(0)", 3);
assertSame(f1, t.getTemplateDefinition());
}
// template<typename A, typename B = int, typename... C>
// void foo(A, B=0, C...);
//
// template<typename A, typename... B>
// void foo(A, B...);
//
// int main() {
// foo(0);
// }
public void testDisambiguateFunctionUnusedPackVsDefault2_541474() throws Exception {
BindingAssertionHelper bh = new AST2AssertionHelper(getAboveComment(), CPP);
// clang (7.0.0) and gcc (7.3.1) disagree, clang thinks this is ambiguous
// which seems correct according to [temp.deduct.partial] p11
bh.assertProblem("foo(0)", 3);
}
}

View file

@ -27,6 +27,7 @@ import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUti
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.getNestedType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@ -2504,6 +2505,23 @@ public class CPPTemplates {
return null;
}
/**
* N4659: [temp.deduct.partial] p11
*/
static int disambiguateTrailingParameterPack(ICPPFunctionTemplate f1, ICPPFunctionTemplate f2, int nExplicitArgs) {
ICPPTemplateParameter[] f1params = f1.getTemplateParameters();
ICPPTemplateParameter[] f2params = f2.getTemplateParameters();
boolean f1hasTrailingPack = f1params[f1params.length - 1].isParameterPack();
boolean f2hasTrailingPack = f2params[f2params.length - 1].isParameterPack();
if (f1hasTrailingPack && f1params.length > nExplicitArgs && !f2hasTrailingPack) {
return -1;
} else if (f2hasTrailingPack && f2params.length > nExplicitArgs && !f1hasTrailingPack) {
return 1;
} else {
return 0;
}
}
/**
* 14.5.6.2 Partial ordering of function templates
*
@ -2527,8 +2545,9 @@ public class CPPTemplates {
int s1 = compareSpecialization(f1, f2, mode, nExplicitArgs);
int s2 = compareSpecialization(f2, f1, mode, nExplicitArgs);
if (s1 == s2)
return 0;
if (s1 == s2) {
return disambiguateTrailingParameterPack(f1, f2, nExplicitArgs);
}
if (s1 < 0 || s2 > 0)
return -1;
assert s2 < 0 || s1 > 0;
@ -2576,25 +2595,24 @@ public class CPPTemplates {
return arg;
}
private static ICPPFunctionType getFunctionTypeIgnoringParametersWithDefaults(ICPPFunction function,
/**
* [temp.func.order] p5: Considers only parameters for which there are explicit call arguments.
*
* Since at this point non-viable functions are already excluded, it is safe to just ignore extra parameters
* without checking if they can be ignored, i.e. without checking if they are function parameter packs,
* parameters with default arguments, or ellipsis parameter.
*/
private static ICPPFunctionType getFunctionTypeIgnoringParametersWithoutExplicitArguments(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 (i < nExplicitArgs || !parameter.hasDefaultValue()) {
parameterTypes[i] = parameter.getType();
} else {
break;
}
}
ICPPFunctionType originalType = function.getType();
if (i == parameters.length) // No parameters with default arguments.
if (nExplicitArgs < function.getParameters().length) {
IType[] parameterTypesWithExplicitArguments = Arrays.copyOf(originalType.getParameterTypes(),
nExplicitArgs);
return new CPPFunctionType(originalType.getReturnType(), parameterTypesWithExplicitArguments,
originalType.isConst(), originalType.isVolatile(), originalType.hasRefQualifier(),
originalType.isRValueReference(), originalType.takesVarArgs());
} else
return originalType;
return new CPPFunctionType(originalType.getReturnType(), ArrayUtil.trim(parameterTypes), originalType.isConst(),
originalType.isVolatile(), originalType.hasRefQualifier(), originalType.isRValueReference(),
originalType.takesVarArgs());
}
private static int compareSpecialization(ICPPFunctionTemplate f1, ICPPFunctionTemplate f2, TypeSelection mode,
@ -2604,9 +2622,8 @@ public class CPPTemplates {
return -1;
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, nExplicitArgs);
final ICPPFunctionType transFt1 = getFunctionTypeIgnoringParametersWithoutExplicitArguments(transF1,
nExplicitArgs);
IType[] pars;
IType[] args;
switch (mode) {