On Wed, 23 Jun 2021, Jason Merrill wrote: > On 6/23/21 2:18 PM, Patrick Palka wrote: > > We set DECL_CONTEXT on implicitly generated deduction guides so that > > their access is consistent with that of the constructor. But this > > apparently leads to excessive instantiation in some cases, ultimately > > because instantiation of a deduction guide should be independent of > > instantiation of the resulting class specialization, but setting the > > DECL_CONTEXT of the former to the latter breaks this independence. > > > > To fix this, this patch makes push_access_scope handle artificial > > deduction guides specifically instead of setting their DECL_CONTEXT > > in build_deduction_guide. We could alternatively make the class > > befriend the guide via DECL_BEFRIENDING_CLASSES, but that'd break > > class-deduction-access3.C below since friendship isn't transitive. > > > > Bootstrapped and regtested on x86_64-pc-linxu-gnu, does this look OK for > > trunk? > > > > PR c++/101174 > > > > gcc/cp/ChangeLog: > > > > * pt.c (push_access_scope): For artificial deduction guides, > > set the access scope to that of the constructor. > > (pop_access_scope): Likewise. > > (build_deduction_guide): Don't set DECL_CONTEXT. > > > > libstdc++-v3/ChangeLog: > > > > * testsuite/23_containers/multiset/cons/deduction.cc: > > Uncomment CTAD example that was rejected by this bug. > > * testsuite/23_containers/set/cons/deduction.cc: Likewise. > > > > gcc/testsuite/ChangeLog: > > > > * g++.dg/cpp1z/class-deduction-access3.C: New test. > > * g++.dg/cpp1z/class-deduction91.C: New test. > > --- > > gcc/cp/pt.c | 11 ++++++---- > > .../g++.dg/cpp1z/class-deduction-access3.C | 22 +++++++++++++++++++ > > .../g++.dg/cpp1z/class-deduction91.C | 16 ++++++++++++++ > > .../23_containers/multiset/cons/deduction.cc | 2 -- > > .../23_containers/set/cons/deduction.cc | 2 -- > > 5 files changed, 45 insertions(+), 8 deletions(-) > > create mode 100644 gcc/testsuite/g++.dg/cpp1z/class-deduction-access3.C > > create mode 100644 gcc/testsuite/g++.dg/cpp1z/class-deduction91.C > > > > diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c > > index 732fb405adf..5c55507203a 100644 > > --- a/gcc/cp/pt.c > > +++ b/gcc/cp/pt.c > > @@ -236,6 +236,10 @@ push_access_scope (tree t) > > push_nested_class (DECL_FRIEND_CONTEXT (t)); > > else if (DECL_CLASS_SCOPE_P (t)) > > push_nested_class (DECL_CONTEXT (t)); > > + else if (deduction_guide_p (t) && DECL_ARTIFICIAL (t)) > > + /* An artificial deduction guide should have the same access as > > + the constructor. */ > > + push_nested_class (TREE_TYPE (TREE_TYPE (t))); > > Let's be more specific and actually push into the access scope of the > constructor (DECL_ABSTRACT_ORIGIN) if set.
Hmm, IIUC this doesn't seem to work because DECL_ABSTRACT_ORIGIN is not set on specializations of a deduction guide, only on the TEMPLATE_DECL. > > > else > > push_to_top_level (); > > @@ -255,7 +259,9 @@ pop_access_scope (tree t) > > if (TREE_CODE (t) == FUNCTION_DECL) > > current_function_decl = saved_access_scope->pop(); > > - if (DECL_FRIEND_CONTEXT (t) || DECL_CLASS_SCOPE_P (t)) > > + if (DECL_FRIEND_CONTEXT (t) > > + || DECL_CLASS_SCOPE_P (t) > > + || (deduction_guide_p (t) && DECL_ARTIFICIAL (t))) > > pop_nested_class (); > > else > > pop_from_top_level (); > > @@ -28804,9 +28810,6 @@ build_deduction_guide (tree type, tree ctor, tree > > outer_args, tsubst_flags_t com > > DECL_ABSTRACT_ORIGIN (ded_tmpl) = fn_tmpl; > > if (ci) > > set_constraints (ded_tmpl, ci); > > - /* The artificial deduction guide should have same access as the > > - constructor. */ > > - DECL_CONTEXT (ded_fn) = type; > > return ded_tmpl; > > } > > diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction-access3.C > > b/gcc/testsuite/g++.dg/cpp1z/class-deduction-access3.C > > new file mode 100644 > > index 00000000000..44b4b5c455f > > --- /dev/null > > +++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction-access3.C > > @@ -0,0 +1,22 @@ > > +// { dg-do compile { target c++17 } } > > + > > +template<typename T> > > +struct Cont; > > + > > +template<typename T> > > +struct Base > > +{ > > +private: > > + using type = T; > > + friend Cont<T>; > > +}; > > + > > +template<typename T> > > +struct Cont > > +{ > > + using argument_type = typename Base<T>::type; > > + > > + Cont(T, argument_type) { } > > +}; > > + > > +Cont c(1, 1); > > diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction91.C > > b/gcc/testsuite/g++.dg/cpp1z/class-deduction91.C > > new file mode 100644 > > index 00000000000..f474c8e35ec > > --- /dev/null > > +++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction91.C > > @@ -0,0 +1,16 @@ > > +// PR c++/101174 > > +// { dg-do compile { target c++17 } } > > + > > +struct S { using type = int; }; > > + > > +template<class T = int, class U = S> > > +struct multiset { > > + using type = typename U::type; > > + multiset(T); > > + multiset(U); > > +}; > > + > > +template<class T> > > +multiset(T) -> multiset<T>; > > + > > +multiset c(42); > > diff --git a/libstdc++-v3/testsuite/23_containers/multiset/cons/deduction.cc > > b/libstdc++-v3/testsuite/23_containers/multiset/cons/deduction.cc > > index a4ccc6fa467..8b7a16042a4 100644 > > --- a/libstdc++-v3/testsuite/23_containers/multiset/cons/deduction.cc > > +++ b/libstdc++-v3/testsuite/23_containers/multiset/cons/deduction.cc > > @@ -19,11 +19,9 @@ static_assert(std::is_same_v< > > decltype(std::multiset{{1, 2, 3}, std::less<int>{}, {}}), > > std::multiset<int>>); > > -/* FIXME: GCC 12 rejects this due to PR c++/101174 > > static_assert(std::is_same_v< > > decltype(std::multiset{{1, 2, 3}, std::less<int>{}}), > > std::multiset<int>>); > > -*/ > > static_assert(std::is_same_v< > > decltype(std::multiset{{1, 2, 3}, SimpleAllocator<int>{}}), > > diff --git a/libstdc++-v3/testsuite/23_containers/set/cons/deduction.cc > > b/libstdc++-v3/testsuite/23_containers/set/cons/deduction.cc > > index 0ae4c2a5c5f..14f36b7c05d 100644 > > --- a/libstdc++-v3/testsuite/23_containers/set/cons/deduction.cc > > +++ b/libstdc++-v3/testsuite/23_containers/set/cons/deduction.cc > > @@ -20,12 +20,10 @@ static_assert(std::is_same_v< > > std::less<int>{}, {}}), > > std::set<int>>); > > -/* FIXME: GCC 12 rejects this due to PR c++/101174 > > static_assert(std::is_same_v< > > decltype(std::set{{1, 2, 3}, > > std::less<int>{}}), > > std::set<int>>); > > -*/ > > static_assert(std::is_same_v< > > decltype(std::set{{1, 2, 3}, > > > >