[PATCH] c++: excessive instantiation during CTAD [PR101174]

Patrick Palka ppalka@redhat.com
Wed Jun 23 20:49:53 GMT 2021


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},
> > 
> 
> 



More information about the Gcc-patches mailing list