diff mbox series

c++: constrained partial spec type context [PR111890]

Message ID 20240711170830.3558231-1-ppalka@redhat.com
State New
Headers show
Series c++: constrained partial spec type context [PR111890] | expand

Commit Message

Patrick Palka July 11, 2024, 5:08 p.m. UTC
Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
trunk/14?

-- >8 --

maybe_new_partial_specialization wasn't propagating TYPE_CONTEXT when
creating a new class type corresponding to a constrained partial spec,
which do_friend relies on via template_class_depth to distinguish a
template friend from a non-template friend, and so in the below testcase
we were incorrectly instantiating the non-template operator+ as if it
were a template leading to an ICE.

	PR c++/111890

gcc/cp/ChangeLog:

	* pt.cc (maybe_new_partial_specialization): Propagate TYPE_CONTEXT to
	the newly created partial specialization.

gcc/testsuite/ChangeLog:

	* g++.dg/cpp2a/concepts-partial-spec15.C: New test.
---
 gcc/cp/pt.cc                                  |  1 +
 .../g++.dg/cpp2a/concepts-partial-spec15.C    | 20 +++++++++++++++++++
 2 files changed, 21 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-partial-spec15.C

Comments

Jason Merrill July 16, 2024, 10:03 p.m. UTC | #1
On 7/11/24 1:08 PM, Patrick Palka wrote:
> Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
> trunk/14?

OK.

> -- >8 --
> 
> maybe_new_partial_specialization wasn't propagating TYPE_CONTEXT when
> creating a new class type corresponding to a constrained partial spec,
> which do_friend relies on via template_class_depth to distinguish a
> template friend from a non-template friend, and so in the below testcase
> we were incorrectly instantiating the non-template operator+ as if it
> were a template leading to an ICE.
> 
> 	PR c++/111890
> 
> gcc/cp/ChangeLog:
> 
> 	* pt.cc (maybe_new_partial_specialization): Propagate TYPE_CONTEXT to
> 	the newly created partial specialization.
> 
> gcc/testsuite/ChangeLog:
> 
> 	* g++.dg/cpp2a/concepts-partial-spec15.C: New test.
> ---
>   gcc/cp/pt.cc                                  |  1 +
>   .../g++.dg/cpp2a/concepts-partial-spec15.C    | 20 +++++++++++++++++++
>   2 files changed, 21 insertions(+)
>   create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-partial-spec15.C
> 
> diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
> index a382dce8788..314b0be4f19 100644
> --- a/gcc/cp/pt.cc
> +++ b/gcc/cp/pt.cc
> @@ -992,6 +992,7 @@ maybe_new_partial_specialization (tree& type)
>         tree t = make_class_type (TREE_CODE (type));
>         CLASSTYPE_DECLARED_CLASS (t) = CLASSTYPE_DECLARED_CLASS (type);
>         SET_TYPE_TEMPLATE_INFO (t, build_template_info (tmpl, args));
> +      TYPE_CONTEXT (t) = TYPE_CONTEXT (type);
>   
>         /* We only need a separate type node for storing the definition of this
>   	 partial specialization; uses of S<T*> are unconstrained, so all are
> diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-partial-spec15.C b/gcc/testsuite/g++.dg/cpp2a/concepts-partial-spec15.C
> new file mode 100644
> index 00000000000..ad01a390fef
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-partial-spec15.C
> @@ -0,0 +1,20 @@
> +// PR c++/111890
> +// { dg-do compile { target c++20 } }
> +
> +template<class>
> +struct A {
> +  template<class T>
> +  struct B { };
> +
> +  template<class T> requires T::value
> +  struct B<T> { };
> +
> +  template<class T> requires (sizeof(T) == sizeof(int))
> +  struct B<T> {
> +    friend void operator+(B&, int) { }
> +  };
> +};
> +
> +void f(A<int>::B<int> b) {
> +  b + 0;
> +}
diff mbox series

Patch

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index a382dce8788..314b0be4f19 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -992,6 +992,7 @@  maybe_new_partial_specialization (tree& type)
       tree t = make_class_type (TREE_CODE (type));
       CLASSTYPE_DECLARED_CLASS (t) = CLASSTYPE_DECLARED_CLASS (type);
       SET_TYPE_TEMPLATE_INFO (t, build_template_info (tmpl, args));
+      TYPE_CONTEXT (t) = TYPE_CONTEXT (type);
 
       /* We only need a separate type node for storing the definition of this
 	 partial specialization; uses of S<T*> are unconstrained, so all are
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-partial-spec15.C b/gcc/testsuite/g++.dg/cpp2a/concepts-partial-spec15.C
new file mode 100644
index 00000000000..ad01a390fef
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-partial-spec15.C
@@ -0,0 +1,20 @@ 
+// PR c++/111890
+// { dg-do compile { target c++20 } }
+
+template<class>
+struct A {
+  template<class T>
+  struct B { };
+
+  template<class T> requires T::value
+  struct B<T> { };
+
+  template<class T> requires (sizeof(T) == sizeof(int))
+  struct B<T> {
+    friend void operator+(B&, int) { }
+  };
+};
+
+void f(A<int>::B<int> b) {
+  b + 0;
+}