aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2020-06-11 23:58:54 -0400
committerJason Merrill <jason@redhat.com>2020-06-20 10:57:21 -0400
commit57b4daf8dc4ed7b669cc70638866ddb00f5b7746 (patch)
tree25aa1fbdf05d421d0589bb95b9ecbb5bba6e74de /gcc
parent3345e74299687de6144b87c0632018cafd4ccf3b (diff)
downloadgcc-57b4daf8dc4ed7b669cc70638866ddb00f5b7746.zip
gcc-57b4daf8dc4ed7b669cc70638866ddb00f5b7746.tar.gz
gcc-57b4daf8dc4ed7b669cc70638866ddb00f5b7746.tar.bz2
c++: Refinements to "more constrained".
P2113 from the last C++ meeting clarified that we only compare constraints on functions or function templates that have equivalent template parameters and function parameters. I'm not currently implementing the complicated handling of reversed comparison operators here; thinking about it now, it seems like a lot of complexity to support a very weird usage. If I write two similar comparison operators to be distinguished by their constraints, why would I write one reversed? If they're two unrelated operators, they're very unlikely to be similar enough for the complexity to help. I've started a discussion on the committee reflector about changing these rules. This change breaks some greedy_ops tests in libstdc++ that were relying on comparing constraints on unrelated templates, which seems pretty clearly wrong, so I'm removing those tests for now. gcc/cp/ChangeLog: * call.c (joust): Only compare constraints for non-template candidates with matching parameters. * pt.c (tsubst_pack_expansion): Fix getting a type parameter pack. (more_specialized_fn): Only compare constraints for candidates with matching parameters. gcc/testsuite/ChangeLog: * g++.dg/cpp2a/concepts-return-req1.C: Expect error. * g++.dg/cpp2a/concepts-p2113a.C: New test. * g++.dg/cpp2a/concepts-p2113b.C: New test. libstdc++-v3/ChangeLog: * testsuite/24_iterators/move_iterator/rel_ops_c++20.cc: Remove greedy_ops tests. * testsuite/24_iterators/reverse_iterator/rel_ops_c++20.cc: Remove greedy_ops tests.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/call.c11
-rw-r--r--gcc/cp/pt.c14
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-p2113a.C12
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-p2113b.C25
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-return-req1.C2
5 files changed, 57 insertions, 7 deletions
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 5382b76..2b39a37 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -11435,12 +11435,13 @@ joust (struct z_candidate *cand1, struct z_candidate *cand2, bool warn,
return winner;
}
- /* Concepts: ... or, if not that, F1 is more constrained than F2.
+ /* Concepts: F1 and F2 are non-template functions with the same
+ parameter-type-lists, and F1 is more constrained than F2 according to the
+ partial ordering of constraints described in 13.5.4. */
- FIXME: For function templates with no winner, this subsumption may
- be computed a separate time. This needs to be validated, and if
- so, the redundant check removed. */
- if (flag_concepts && DECL_P (cand1->fn) && DECL_P (cand2->fn))
+ if (flag_concepts && DECL_P (cand1->fn) && DECL_P (cand2->fn)
+ && !cand1->template_decl && !cand2->template_decl
+ && cand_parms_match (cand1, cand2))
{
winner = more_constrained (cand1->fn, cand2->fn);
if (winner)
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 1c0759e..efaadf7 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -12849,6 +12849,10 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
template_parm_level_and_index (parm_pack, &level, &idx);
if (level <= levels)
arg_pack = TMPL_ARG (args, level, idx);
+
+ if (arg_pack && TREE_CODE (arg_pack) == TEMPLATE_TYPE_PARM
+ && TEMPLATE_TYPE_PARAMETER_PACK (arg_pack))
+ arg_pack = NULL_TREE;
}
orig_arg = arg_pack;
@@ -24061,7 +24065,15 @@ more_specialized_fn (tree pat1, tree pat2, int len)
/* If both deductions succeed, the partial ordering selects the more
constrained template. */
- if (!lose1 && !lose2)
+ /* P2113: If the corresponding template-parameters of the
+ template-parameter-lists are not equivalent ([temp.over.link]) or if
+ the function parameters that positionally correspond between the two
+ templates are not of the same type, neither template is more
+ specialized than the other. */
+ if (!lose1 && !lose2
+ && comp_template_parms (DECL_TEMPLATE_PARMS (pat1),
+ DECL_TEMPLATE_PARMS (pat2))
+ && compparms (origs1, origs2))
{
int winner = more_constrained (decl1, decl2);
if (winner > 0)
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-p2113a.C b/gcc/testsuite/g++.dg/cpp2a/concepts-p2113a.C
new file mode 100644
index 0000000..e2652dd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-p2113a.C
@@ -0,0 +1,12 @@
+// Test that the second foo is not considered more specialized because we don't
+// compare constraints unless the template parameters and function parameters
+// are equivalent (P2113)
+
+// { dg-do compile { target c++20 } }
+
+template <typename T> concept P = true;
+
+template <typename T> void foo(int, T);
+template <P U> void foo(U, int);
+
+void bar() { foo(1,2); } // { dg-error "ambiguous" }
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-p2113b.C b/gcc/testsuite/g++.dg/cpp2a/concepts-p2113b.C
new file mode 100644
index 0000000..18c4098
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-p2113b.C
@@ -0,0 +1,25 @@
+// testcase from P2113
+// { dg-do compile { target c++20 } }
+
+template <typename> constexpr bool True = true;
+template <typename T> concept C = True<T>;
+
+void f(C auto &, auto &) = delete;
+template <C Q> void f(Q &, C auto &);
+
+void g(struct A *ap, struct B *bp) {
+ f(*ap, *bp); // OK: Can use different methods to produce template parameters
+}
+
+template <typename T, typename U> struct X {};
+
+template <typename T1, C U1, typename V1>
+bool operator==(X<T1, U1>, V1) = delete;
+
+// In P2113 this candidate is reversed.
+template <C T2, C U2, C V2>
+bool operator==(X<T2, U2>, V2);
+
+void h() {
+ X<void *, int>{} == 0; // OK
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-return-req1.C b/gcc/testsuite/g++.dg/cpp2a/concepts-return-req1.C
index 84c9ae9..d21a49b 100644
--- a/gcc/testsuite/g++.dg/cpp2a/concepts-return-req1.C
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-return-req1.C
@@ -15,5 +15,5 @@ int f(...);
int main()
{
- f<int>();
+ f<int>(); // { dg-error "ambiguous" }
}