diff mbox series

c++: excessive instantiation during CTAD [PR101174]

Message ID 20210623181856.2158285-1-ppalka@redhat.com
State New
Headers show
Series c++: excessive instantiation during CTAD [PR101174] | expand

Commit Message

Patrick Palka June 23, 2021, 6:18 p.m. UTC
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

Comments

Jason Merrill June 23, 2021, 7:55 p.m. UTC | #1
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.

>     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},
>
Patrick Palka June 23, 2021, 8:49 p.m. UTC | #2
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},
> > 
> 
>
Jason Merrill June 23, 2021, 9:06 p.m. UTC | #3
On 6/23/21 4:49 PM, Patrick Palka wrote:
> 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.

Ah, true.  Your patch is OK, then.

>>>      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},
>>>
>>
>>
>
diff mbox series

Patch

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