public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Jason Merrill <jason@redhat.com>
To: Nick Huang <nickhuang99@gmail.com>,
	Gcc-patches <gcc-patches@gcc.gnu.org>
Subject: Re: [PATCH] c++: fix cases of core1001/1322 by not dropping cv-qualifier of function parameter of type of typename or decltype[PR101402,PR102033,PR102034,PR102039,PR102
Date: Fri, 15 Oct 2021 17:00:19 -0400	[thread overview]
Message-ID: <e57aac88-334f-16a6-373b-4db053bf00b3@redhat.com> (raw)
In-Reply-To: <CAP6LXBuCuhghFWcxaPViDE22W-c3--my-cT60fXdRjh0uNgVqA@mail.gmail.com>

[-- Attachment #1: Type: text/plain, Size: 559 bytes --]

On 10/14/21 07:04, Nick Huang wrote:
> IMHO, I think your patch probably finally solved this long-standing Core
> 1001 issue. Of course it is not up to me to say so. I just want to point out
> that it even solves the following case, even though it is more or less
> expected if concept and lambda all work expectedly.
> 
> template<class T>
> concept IsLambdaAry3=__is_same(T, decltype(+[]{})[3]);
> template<IsLambdaAry3 T>
> void bar(const T){}
> template<>
> void bar<decltype(+[]{})[3]>(const decltype(+[]{})[3]){}

Sounds good.  Here's what I'm applying:

[-- Attachment #2: 0001-c-array-cv-quals-and-template-specialization-PR10140.patch --]
[-- Type: text/x-patch, Size: 9484 bytes --]

From 79802c5dcc043a515f429bb2bec7573b8537c32a Mon Sep 17 00:00:00 2001
From: Jason Merrill <jason@redhat.com>
Date: Tue, 28 Sep 2021 10:02:04 -0400
Subject: [PATCH] c++: array cv-quals and template specialization [PR101402]
To: gcc-patches@gcc.gnu.org

PRs 101402, 102033, etc. demonstrated that the fix for PR92010 wasn't
handling all cases of the CWG1001/1322 issue with parameter type qual
stripping and arrays with templates.  The problem turned out to be in
determine_specialization, which did an extra substitution without the 92010
fix and then complained that the result didn't match.

But just removing that wrong/redundant code meant that we were accepting
specializations with different numbers of parameters, because the code in
fn_type_unification that compares types in this case wasn't checking for
length mismatch.

After fixing that, I realized that fn_type_unification couldn't tell the
difference between variadic and non-variadic function types, because the
args array doesn't include the terminal void we use to indicate non-variadic
function type.  So I added it, and made the necessary adjustments.

Thanks to qingzhe "nick" huang <nickhuang99@hotmail.com> for the patch that
led me to dig more into this, and the extensive testcases.

	PR c++/51851
	PR c++/101402
	PR c++/102033
	PR c++/102034
	PR c++/102039
	PR c++/102044

gcc/cp/ChangeLog:

	* pt.c (determine_specialization): Remove redundant code.
	(fn_type_unification): Check for mismatched length.
	(type_unification_real): Ignore terminal void.
	(get_bindings): Don't stop at void_list_node.
	* class.c (resolve_address_of_overloaded_function): Likewise.

gcc/testsuite/ChangeLog:

	* g++.dg/template/fnspec2.C: New test.
	* g++.dg/template/parm-cv1.C: New test.
	* g++.dg/template/parm-cv2.C: New test.
	* g++.dg/template/parm-cv3.C: New test.
---
 gcc/cp/class.c                           |   2 +-
 gcc/cp/pt.c                              |  30 +++--
 gcc/testsuite/g++.dg/template/fnspec2.C  |   9 ++
 gcc/testsuite/g++.dg/template/parm-cv1.C |  15 +++
 gcc/testsuite/g++.dg/template/parm-cv2.C |  23 ++++
 gcc/testsuite/g++.dg/template/parm-cv3.C | 142 +++++++++++++++++++++++
 6 files changed, 204 insertions(+), 17 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/template/fnspec2.C
 create mode 100644 gcc/testsuite/g++.dg/template/parm-cv1.C
 create mode 100644 gcc/testsuite/g++.dg/template/parm-cv2.C
 create mode 100644 gcc/testsuite/g++.dg/template/parm-cv3.C

diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 59611627d18..f16e50b9de9 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -8382,7 +8382,7 @@ resolve_address_of_overloaded_function (tree target_type,
       nargs = list_length (target_arg_types);
       args = XALLOCAVEC (tree, nargs);
       for (arg = target_arg_types, ia = 0;
-	   arg != NULL_TREE && arg != void_list_node;
+	   arg != NULL_TREE;
 	   arg = TREE_CHAIN (arg), ++ia)
 	args[ia] = TREE_VALUE (arg);
       nargs = ia;
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 009fe6db573..287cf4ce9d0 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -2230,7 +2230,6 @@ determine_specialization (tree template_id,
 	{
 	  tree decl_arg_types;
 	  tree fn_arg_types;
-	  tree insttype;
 
 	  /* In case of explicit specialization, we need to check if
 	     the number of template headers appearing in the specialization
@@ -2356,20 +2355,6 @@ determine_specialization (tree template_id,
 	       template argument.  */
 	    continue;
 
-          /* Remove, from the set of candidates, all those functions
-             whose constraints are not satisfied. */
-          if (flag_concepts && !constraints_satisfied_p (fn, targs))
-            continue;
-
-          // Then, try to form the new function type.
-	  insttype = tsubst (TREE_TYPE (fn), targs, tf_fndecl_type, NULL_TREE);
-	  if (insttype == error_mark_node)
-	    continue;
-	  fn_arg_types
-	    = skip_artificial_parms_for (fn, TYPE_ARG_TYPES (insttype));
-	  if (!compparms (fn_arg_types, decl_arg_types))
-	    continue;
-
 	  /* Save this template, and the arguments deduced.  */
 	  templates = tree_cons (targs, fn, templates);
 	}
@@ -21862,6 +21847,15 @@ fn_type_unification (tree fn,
 				 TREE_VALUE (sarg));
 	    goto fail;
 	  }
+      if ((i < nargs || sarg)
+	  /* add_candidates uses DEDUCE_EXACT for x.operator foo(), but args
+	     doesn't contain the trailing void, and conv fns are always ().  */
+	  && !DECL_CONV_FN_P (decl))
+	{
+	  unsigned nsargs = i + list_length (sarg);
+	  unify_arity (explain_p, nargs, nsargs);
+	  goto fail;
+	}
     }
 
   /* After doing deduction with the inherited constructor, actually return an
@@ -22385,6 +22379,10 @@ type_unification_real (tree tparms,
   args = xargs;
   nargs = xnargs;
 
+  /* Only fn_type_unification cares about terminal void.  */
+  if (nargs && args[nargs-1] == void_type_node)
+    --nargs;
+
   ia = 0;
   while (parms && parms != void_list_node
 	 && ia < nargs)
@@ -24886,7 +24884,7 @@ get_bindings (tree fn, tree decl, tree explicit_args, bool check_rettype)
   nargs = list_length (decl_arg_types);
   args = XALLOCAVEC (tree, nargs);
   for (arg = decl_arg_types, ix = 0;
-       arg != NULL_TREE && arg != void_list_node;
+       arg != NULL_TREE;
        arg = TREE_CHAIN (arg), ++ix)
     args[ix] = TREE_VALUE (arg);
 
diff --git a/gcc/testsuite/g++.dg/template/fnspec2.C b/gcc/testsuite/g++.dg/template/fnspec2.C
new file mode 100644
index 00000000000..7a4b1012d89
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/fnspec2.C
@@ -0,0 +1,9 @@
+template <class T>
+void f(T);
+
+template<> void f(int, ...);	// { dg-error "match" }
+
+template <class T>
+void g(T, ...);
+
+template<> void g(int);		// { dg-error "match" }
diff --git a/gcc/testsuite/g++.dg/template/parm-cv1.C b/gcc/testsuite/g++.dg/template/parm-cv1.C
new file mode 100644
index 00000000000..2677992770d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/parm-cv1.C
@@ -0,0 +1,15 @@
+// CWG 1001
+
+template<class T> struct A {
+  typedef T arr[3];
+};
+
+template<class T> void f(const typename A<T>::arr) { } // #1
+
+template void f<int>(const A<int>::arr);
+
+template <class T> struct B {
+  void g(T);
+};
+
+template <class T> void B<T>::g(const T) { } // #2
diff --git a/gcc/testsuite/g++.dg/template/parm-cv2.C b/gcc/testsuite/g++.dg/template/parm-cv2.C
new file mode 100644
index 00000000000..cd40e868017
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/parm-cv2.C
@@ -0,0 +1,23 @@
+// PR c++/51851
+
+template<class T>
+struct A
+{
+  typedef double Point[2];
+  virtual double calculate(const Point point) const = 0;
+};
+
+template<class T>
+struct B : public A<T>
+{
+  virtual double calculate(const typename A<T>::Point point) const
+  {
+    return point[0];
+  }
+};
+
+int main()
+{
+  B<int> b;
+  return 0;
+}
diff --git a/gcc/testsuite/g++.dg/template/parm-cv3.C b/gcc/testsuite/g++.dg/template/parm-cv3.C
new file mode 100644
index 00000000000..1b69c3b2a48
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/parm-cv3.C
@@ -0,0 +1,142 @@
+// CWG 1001/1322
+
+// PR c++/101402
+// PR c++/102033
+// PR c++/102034
+// PR c++/102039
+// PR c++/102044
+
+namespace test2{
+template <class T>
+void f(const T);
+
+template<>
+void f<int[]>(const int*){}
+}
+
+namespace test3{
+template <class T>
+struct A{
+void f(T);
+};
+
+template<class T>
+void A<T>::f(const T){}
+
+template<>
+void A<int[3]>::f(const int*){}
+}
+
+namespace test4 {
+template<class TA>
+struct A{
+  template<class TB>
+  struct B{
+    typedef TB Arr3[3];
+  };
+};
+template<class TA, class TB>
+void f(const typename A<TA>::template B<TB>::Arr3){}
+template <>
+void f<int, char>(const typename A<int>::B<char>::Arr3){}
+}
+
+namespace test5
+{
+struct A{
+  typedef int Arr3[3];
+};
+
+template<class T>
+void f(const typename T::Arr3){}
+
+template<>
+void f<A>(const int[3]){}
+}
+
+namespace test6
+{
+struct A{
+  typedef int Arr3[3];
+};
+template<class T>
+void f(const typename T::Arr3){}
+template<>
+void f<A>(const int*){}
+}
+
+#if __cpp_alias_templates
+namespace test7
+{
+template<class TA>
+struct A{
+  template<class TB>
+  using Type=TB[3];
+};
+template<class TA, class TB>
+void f(const typename A<TA>::template Type<TB>){}
+template <>
+void f<int, char>(const typename A<int>::template Type<char>){}
+}
+namespace test8
+{
+template<class TA>
+struct A{
+  template<class TB>
+  struct B{
+    using TB_Alias=TB;
+    template<class TC=TB_Alias>
+    struct C{
+      typedef TC Arr3[3];
+    };
+  };
+};
+template<class TA, class TB>
+void f(const typename A<TA>::template B<TB>::template C<>::Arr3){}
+template <>
+void f<int, char>(const typename A<int>::template B<char>::template C<>::Arr3){}
+}
+#endif
+
+#if __cpp_decltype
+namespace test0
+{
+template <class T>
+struct A{
+  T arr3[3];
+};
+template <class T>
+void f(const decltype(A<T>::arr3)){}
+template <>
+void f<int>(const int[3]){}
+}
+
+#if __cpp_variable_templates
+namespace test9
+{
+template<unsigned int N, class T>
+void f(const T[N]){}
+
+template<unsigned int N, class T>
+using fPtr=decltype(f<N,T>)*;
+
+template<unsigned int N, class T>
+fPtr<N,T> af[N]={&f<N,T>};
+
+template<unsigned int N, class T>
+void g(const decltype(af<N,T>)){}
+
+template<>
+void g<1,int>(const fPtr<1,int>[1]){}
+}
+#endif
+#endif
+
+#if __cpp_concepts
+template<class T>
+concept IsLambdaAry3=__is_same(T, decltype(+[]{})[3]);
+template<IsLambdaAry3 T>
+void bar(const T){}
+template<>
+void bar<decltype(+[]{})[3]>(const decltype(+[]{})[3]){}
+#endif
-- 
2.27.0


  reply	other threads:[~2021-10-15 21:00 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-10-08 20:19 [PATCH] c++: fix cases of core1001/1322 by not dropping cv-qualifier of function parameter of type of typename or decltype[PR101402, PR102033, PR102034, PR102039, PR102 Nick Huang
2021-10-14 11:04 ` Nick Huang
2021-10-15 21:00   ` Jason Merrill [this message]
  -- strict thread matches above, loose matches on Subject: below --
2021-10-03 11:14 Nick Huang
2021-10-03 20:16 ` Nick Huang
2021-10-07 20:50 ` [PATCH] c++: fix cases of core1001/1322 by not dropping cv-qualifier of function parameter of type of typename or decltype[PR101402,PR102033,PR102034,PR102039,PR102 Jason Merrill

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=e57aac88-334f-16a6-373b-4db053bf00b3@redhat.com \
    --to=jason@redhat.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=nickhuang99@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).