From: Patrick Palka Date: Wed, 17 Jul 2024 15:08:35 +0000 (-0400) Subject: c++: constrained partial spec type context [PR111890] X-Git-Tag: basepoints/gcc-16~7455 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=247335823f420eb1dd56f4bf32ac78d441f5ccc2;p=thirdparty%2Fgcc.git c++: constrained partial spec type context [PR111890] 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. Reviewed-by: Jason Merrill --- diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index 4d72ff60cb8..0620c8c023a 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 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 +struct A { + template + struct B { }; + + template requires T::value + struct B { }; + + template requires (sizeof(T) == sizeof(int)) + struct B { + friend void operator+(B&, int) { } + }; +}; + +void f(A::B b) { + b + 0; +}