Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHannes Vogt2018-12-02 20:43:18 +0000
committerHannes Vogt2018-12-08 10:15:40 +0000
commit2fc42590fb8e9169941ce822ef7123e8b4f63690 (patch)
tree11efbf3bb66286648840b078c916ed1b59b72c6f
parent12207e79dba630db61194df723e199d86c2728b1 (diff)
downloadorg.eclipse.cdt-2fc42590fb8e9169941ce822ef7123e8b4f63690.tar.gz
org.eclipse.cdt-2fc42590fb8e9169941ce822ef7123e8b4f63690.tar.xz
org.eclipse.cdt-2fc42590fb8e9169941ce822ef7123e8b4f63690.zip
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>
-rw-r--r--core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java64
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java59
2 files changed, 100 insertions, 23 deletions
diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java
index e73f0ec9d8b..7872bd93ab5 100644
--- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java
+++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java
@@ -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);
+ }
+
}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java
index 5a6327ca3bd..f8703278cc8 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java
@@ -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;
@@ -2505,6 +2506,23 @@ public class CPPTemplates {
}
/**
+ * 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
*
* @param f1
@@ -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) {

Back to the top