On 5/22/20 10:56 AM, Patrick Palka wrote:
On Fri, 22 May 2020, Patrick Palka wrote:
When comparing two special member function templates to see if one hides
the other (as per P0848R3), we need to check satisfaction which we can't
do on templates. So this patch makes add_method skip the eligibility
test on member function templates and just lets them coexist.
It just occurred to me that this problem isn't limited to member function
templates. Consider this valid testcase which we currently reject:
template<bool B> struct g {
g() requires B && false;
g() requires B;
};
g<true> b; // error
During add_method, we check satisfaction of both default constructors,
and since their constraints are dependent, constraints_satisfied_p
returns true for both sets of constraints. We then see that
'B && false' is more constrained than 'B' and therefore discard the second
constructor. Since we discarded the second default constructor at
definition time, the instantiation g<true> has no eligible default
constructor.
I am not sure what to do from here...
I looked at this and it seems enough to let the functions coexist
without trying to compare their constraints if processing_template_decl;
we'll handle the hiding properly when the class template is instantiated.
So this is what I'm committing:
commit c591bb815e359a6f5c5ef5a9c9f9a7a646a99ea0
Author: Patrick Palka <ppa...@redhat.com>
Date: Fri May 22 10:28:19 2020 -0400
c++: P0848R3 and member function templates [PR95181]
When comparing two special member function templates to see if one hides
the other (as per P0848R3), we need to check satisfaction which we can't
do on templates. So this patch makes add_method skip the eligibility
test on member function templates and just lets them coexist.
gcc/cp/ChangeLog:
PR c++/95181
* class.c (add_method): Let special member function templates
coexist if they are not equivalently constrained, or in a class
template.
gcc/testsuite/ChangeLog:
PR c++/95181
* g++.dg/concepts/pr95181.C: New test.
* g++.dg/concepts/pr95181-2.C: New test.
Co-authored-by: Jason Merrill <ja...@redhat.com>
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index ca492cdbd40..c818826a108 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -1081,12 +1081,19 @@ add_method (tree type, tree method, bool via_using)
{
if (!equivalently_constrained (fn, method))
{
+ if (processing_template_decl)
+ /* We can't check satisfaction in dependent context, wait until
+ the class is instantiated. */
+ continue;
+
special_function_kind sfk = special_memfn_p (method);
- if (sfk == sfk_none || DECL_INHERITED_CTOR (fn))
- /* Non-special member functions coexist if they are not
- equivalently constrained. A member function is not hidden
- by an inherited constructor. */
+ if (sfk == sfk_none
+ || DECL_INHERITED_CTOR (fn)
+ || TREE_CODE (fn) == TEMPLATE_DECL)
+ /* Member function templates and non-special member functions
+ coexist if they are not equivalently constrained. A member
+ function is not hidden by an inherited constructor. */
continue;
/* P0848: For special member functions, deleted, unsatisfied, or
diff --git a/gcc/testsuite/g++.dg/concepts/pr95181-2.C b/gcc/testsuite/g++.dg/concepts/pr95181-2.C
new file mode 100644
index 00000000000..6d67350e58f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/concepts/pr95181-2.C
@@ -0,0 +1,8 @@
+// { dg-do compile { target concepts } }
+
+template<bool B> struct g {
+ g() requires B && false;
+ g() requires B;
+};
+
+g<true> b; // error
diff --git a/gcc/testsuite/g++.dg/concepts/pr95181.C b/gcc/testsuite/g++.dg/concepts/pr95181.C
new file mode 100644
index 00000000000..0185c86b438
--- /dev/null
+++ b/gcc/testsuite/g++.dg/concepts/pr95181.C
@@ -0,0 +1,9 @@
+// PR c++/95181
+// { dg-do compile { target concepts } }
+
+template <typename> struct f {
+ template <typename T=int> f();
+ template <typename T=int> requires false f();
+};
+
+f<int> a;