Message ID | 20240711170830.3558231-1-ppalka@redhat.com |
---|---|
State | New |
Headers | show |
Series | c++: constrained partial spec type context [PR111890] | expand |
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 --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; +}