diff mbox series

c++: alias of decltype(lambda) is opaque [PR116714]

Message ID 20240916151139.3570776-1-ppalka@redhat.com
State New
Headers show
Series c++: alias of decltype(lambda) is opaque [PR116714] | expand

Commit Message

Patrick Palka Sept. 16, 2024, 3:11 p.m. UTC
Bootstrapped and regtested on x86_64-pc-linuxgnu, does this look
OK for trunk?  Sadly the prerequisity patch r15-2331-g523836716137d0
probably isn't suitable for backporting, so I reckon this should be
trunk-only.

-- >8 --

Here we're prematurely stripping the decltype(lambda) alias used inside
the template-id during ahead of time template argument coercion, which
means we treat it as if it were

  is_same_v<decltype([]{}), decltype([]{})>

which instead yields false since now we're substituting into the lambda
twice, and every such substitution yields a unique lambda.  This
demonstrates that such aliases should be considered opaque, a notion which
coincidentally we recently introduced in r15-2331-g523836716137d0.

	PR c++/116714

gcc/cp/ChangeLog:

	* pt.cc (dependent_opaque_alias_p): Also return true for a
	decltype(lambda) alias.

gcc/testsuite/ChangeLog:

	* g++.dg/cpp2a/lambda-uneval18.C: New test.
---
 gcc/cp/pt.cc                                 |  6 ++++--
 gcc/testsuite/g++.dg/cpp2a/lambda-uneval18.C | 20 ++++++++++++++++++++
 2 files changed, 24 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/lambda-uneval18.C

Comments

Andrew Pinski Sept. 16, 2024, 10:36 p.m. UTC | #1
On Mon, Sep 16, 2024 at 8:12 AM Patrick Palka <ppalka@redhat.com> wrote:
>
> Bootstrapped and regtested on x86_64-pc-linuxgnu, does this look
> OK for trunk?  Sadly the prerequisity patch r15-2331-g523836716137d0
> probably isn't suitable for backporting, so I reckon this should be
> trunk-only.
>
> -- >8 --
>
> Here we're prematurely stripping the decltype(lambda) alias used inside
> the template-id during ahead of time template argument coercion, which
> means we treat it as if it were
>
>   is_same_v<decltype([]{}), decltype([]{})>
>
> which instead yields false since now we're substituting into the lambda
> twice, and every such substitution yields a unique lambda.  This
> demonstrates that such aliases should be considered opaque, a notion which
> coincidentally we recently introduced in r15-2331-g523836716137d0.

I wonder if this fixes https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106221  too.
While https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107390 looks it
would be fixed here too.

Thanks,
Andrew

>
>         PR c++/116714
>
> gcc/cp/ChangeLog:
>
>         * pt.cc (dependent_opaque_alias_p): Also return true for a
>         decltype(lambda) alias.
>
> gcc/testsuite/ChangeLog:
>
>         * g++.dg/cpp2a/lambda-uneval18.C: New test.
> ---
>  gcc/cp/pt.cc                                 |  6 ++++--
>  gcc/testsuite/g++.dg/cpp2a/lambda-uneval18.C | 20 ++++++++++++++++++++
>  2 files changed, 24 insertions(+), 2 deletions(-)
>  create mode 100644 gcc/testsuite/g++.dg/cpp2a/lambda-uneval18.C
>
> diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
> index 04987f66746..a72a1eadbc7 100644
> --- a/gcc/cp/pt.cc
> +++ b/gcc/cp/pt.cc
> @@ -6764,8 +6764,10 @@ dependent_opaque_alias_p (const_tree t)
>  {
>    return (TYPE_P (t)
>           && typedef_variant_p (t)
> -         && any_dependent_type_attributes_p (DECL_ATTRIBUTES
> -                                             (TYPE_NAME (t))));
> +         && (any_dependent_type_attributes_p (DECL_ATTRIBUTES
> +                                              (TYPE_NAME (t)))
> +             || (TREE_CODE (t) == DECLTYPE_TYPE
> +                 && TREE_CODE (DECLTYPE_TYPE_EXPR (t)) == LAMBDA_EXPR)));
>  }
>
>  /* Return the number of innermost template parameters in TMPL.  */
> diff --git a/gcc/testsuite/g++.dg/cpp2a/lambda-uneval18.C b/gcc/testsuite/g++.dg/cpp2a/lambda-uneval18.C
> new file mode 100644
> index 00000000000..2942f8305c7
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp2a/lambda-uneval18.C
> @@ -0,0 +1,20 @@
> +// PR c++/116714
> +// { dg-do compile { target c++20 } }
> +
> +template<class T, class U>
> +inline constexpr bool is_same_v = __is_same(T, U);
> +
> +template<class T, class U>
> +struct is_same { static constexpr bool value = false; };
> +
> +template<class T>
> +struct is_same<T, T> { static constexpr bool value = true; };
> +
> +template<class>
> +void f() {
> +  using type = decltype([]{});
> +  static_assert(is_same_v<type, type>);
> +  static_assert(is_same<type, type>::value);
> +};
> +
> +template void f<int>();
> --
> 2.46.1.506.ged155187b4
>
Patrick Palka Sept. 16, 2024, 10:49 p.m. UTC | #2
On Mon, 16 Sep 2024, Andrew Pinski wrote:

> On Mon, Sep 16, 2024 at 8:12 AM Patrick Palka <ppalka@redhat.com> wrote:
> >
> > Bootstrapped and regtested on x86_64-pc-linuxgnu, does this look
> > OK for trunk?  Sadly the prerequisity patch r15-2331-g523836716137d0
> > probably isn't suitable for backporting, so I reckon this should be
> > trunk-only.
> >
> > -- >8 --
> >
> > Here we're prematurely stripping the decltype(lambda) alias used inside
> > the template-id during ahead of time template argument coercion, which
> > means we treat it as if it were
> >
> >   is_same_v<decltype([]{}), decltype([]{})>
> >
> > which instead yields false since now we're substituting into the lambda
> > twice, and every such substitution yields a unique lambda.  This
> > demonstrates that such aliases should be considered opaque, a notion which
> > coincidentally we recently introduced in r15-2331-g523836716137d0.
> 
> I wonder if this fixes https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106221  too.
> While https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107390 looks it
> would be fixed here too.

Ah thanks, seems 107390 gets fixed but not 106221..

> 
> Thanks,
> Andrew
> 
> >
> >         PR c++/116714
> >
> > gcc/cp/ChangeLog:
> >
> >         * pt.cc (dependent_opaque_alias_p): Also return true for a
> >         decltype(lambda) alias.
> >
> > gcc/testsuite/ChangeLog:
> >
> >         * g++.dg/cpp2a/lambda-uneval18.C: New test.
> > ---
> >  gcc/cp/pt.cc                                 |  6 ++++--
> >  gcc/testsuite/g++.dg/cpp2a/lambda-uneval18.C | 20 ++++++++++++++++++++
> >  2 files changed, 24 insertions(+), 2 deletions(-)
> >  create mode 100644 gcc/testsuite/g++.dg/cpp2a/lambda-uneval18.C
> >
> > diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
> > index 04987f66746..a72a1eadbc7 100644
> > --- a/gcc/cp/pt.cc
> > +++ b/gcc/cp/pt.cc
> > @@ -6764,8 +6764,10 @@ dependent_opaque_alias_p (const_tree t)
> >  {
> >    return (TYPE_P (t)
> >           && typedef_variant_p (t)
> > -         && any_dependent_type_attributes_p (DECL_ATTRIBUTES
> > -                                             (TYPE_NAME (t))));
> > +         && (any_dependent_type_attributes_p (DECL_ATTRIBUTES
> > +                                              (TYPE_NAME (t)))
> > +             || (TREE_CODE (t) == DECLTYPE_TYPE
> > +                 && TREE_CODE (DECLTYPE_TYPE_EXPR (t)) == LAMBDA_EXPR)));
> >  }
> >
> >  /* Return the number of innermost template parameters in TMPL.  */
> > diff --git a/gcc/testsuite/g++.dg/cpp2a/lambda-uneval18.C b/gcc/testsuite/g++.dg/cpp2a/lambda-uneval18.C
> > new file mode 100644
> > index 00000000000..2942f8305c7
> > --- /dev/null
> > +++ b/gcc/testsuite/g++.dg/cpp2a/lambda-uneval18.C
> > @@ -0,0 +1,20 @@
> > +// PR c++/116714
> > +// { dg-do compile { target c++20 } }
> > +
> > +template<class T, class U>
> > +inline constexpr bool is_same_v = __is_same(T, U);
> > +
> > +template<class T, class U>
> > +struct is_same { static constexpr bool value = false; };
> > +
> > +template<class T>
> > +struct is_same<T, T> { static constexpr bool value = true; };
> > +
> > +template<class>
> > +void f() {
> > +  using type = decltype([]{});
> > +  static_assert(is_same_v<type, type>);
> > +  static_assert(is_same<type, type>::value);
> > +};
> > +
> > +template void f<int>();
> > --
> > 2.46.1.506.ged155187b4
> >
> 
>
Patrick Palka Sept. 17, 2024, 1:22 p.m. UTC | #3
On Mon, 16 Sep 2024, Patrick Palka wrote:

> On Mon, 16 Sep 2024, Andrew Pinski wrote:
> 
> > On Mon, Sep 16, 2024 at 8:12 AM Patrick Palka <ppalka@redhat.com> wrote:
> > >
> > > Bootstrapped and regtested on x86_64-pc-linuxgnu, does this look
> > > OK for trunk?  Sadly the prerequisity patch r15-2331-g523836716137d0
> > > probably isn't suitable for backporting, so I reckon this should be
> > > trunk-only.
> > >
> > > -- >8 --
> > >
> > > Here we're prematurely stripping the decltype(lambda) alias used inside
> > > the template-id during ahead of time template argument coercion, which
> > > means we treat it as if it were
> > >
> > >   is_same_v<decltype([]{}), decltype([]{})>
> > >
> > > which instead yields false since now we're substituting into the lambda
> > > twice, and every such substitution yields a unique lambda.  This
> > > demonstrates that such aliases should be considered opaque, a notion which
> > > coincidentally we recently introduced in r15-2331-g523836716137d0.
> > 
> > I wonder if this fixes https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106221  too.
> > While https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107390 looks it
> > would be fixed here too.
> 
> Ah thanks, seems 107390 gets fixed but not 106221..

Here's v2 which extends the testcase slightly to also subsume the
PR107390 testcase.

It also slightly refines the predicate to treat ty2 in

  using ty1 = decltype([]{});
  using ty2 = ty1;

as _not_ opaque (unlike ty1), since we should be able to strip it to
ty1.  I don't know if this makes a difference but it seems the
conceptually right thing to do.

-- >8 --

Subject: [PATCH] c++: alias of decltype(lambda) is opaque [PR116714, PR107390]

	PR c++/116714
	PR c++/107390

gcc/cp/ChangeLog:

	* pt.cc (dependent_opaque_alias_p): Also return true for a
	decltype(lambda) alias.

gcc/testsuite/ChangeLog:

	* g++.dg/cpp2a/lambda-uneval18.C: New test.
---
 gcc/cp/pt.cc                                 |  7 +++-
 gcc/testsuite/g++.dg/cpp2a/lambda-uneval18.C | 39 ++++++++++++++++++++
 2 files changed, 44 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/lambda-uneval18.C

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 04987f66746..b29ea164a91 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -6764,8 +6764,11 @@ dependent_opaque_alias_p (const_tree t)
 {
   return (TYPE_P (t)
 	  && typedef_variant_p (t)
-	  && any_dependent_type_attributes_p (DECL_ATTRIBUTES
-					      (TYPE_NAME (t))));
+	  && (any_dependent_type_attributes_p (DECL_ATTRIBUTES
+					       (TYPE_NAME (t)))
+	      || (TREE_CODE (t) == DECLTYPE_TYPE
+		  && TREE_CODE (DECLTYPE_TYPE_EXPR (t)) == LAMBDA_EXPR
+		  && !typedef_variant_p (DECL_ORIGINAL_TYPE (TYPE_NAME (t))))));
 }
 
 /* Return the number of innermost template parameters in TMPL.  */
diff --git a/gcc/testsuite/g++.dg/cpp2a/lambda-uneval18.C b/gcc/testsuite/g++.dg/cpp2a/lambda-uneval18.C
new file mode 100644
index 00000000000..b7d864c6245
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/lambda-uneval18.C
@@ -0,0 +1,39 @@
+// PR c++/116714
+// PR c++/107390
+// { dg-do compile { target c++20 } }
+
+template<class T, class U>
+inline constexpr bool is_same_v = __is_same(T, U);
+
+template<class T, class U>
+struct is_same { static constexpr bool value = false; };
+
+template<class T>
+struct is_same<T, T> { static constexpr bool value = true; };
+
+template<class>
+void f() {
+  using type = decltype([]{});
+  static_assert(is_same_v<type, type>);
+  static_assert(is_same<type, type>::value);
+};
+
+template<class>
+void g() {
+  using ty1 = decltype([]{});
+  using ty2 = ty1;
+  static_assert(is_same_v<ty1, ty2>);
+  static_assert(is_same<ty1, ty2>::value);
+};
+
+template<class>
+void h() {
+  using ty1 = decltype([]{});
+  using ty2 = decltype([]{});
+  static_assert(!is_same_v<ty1, ty2>);
+  static_assert(!is_same<ty1, ty2>::value);
+};
+
+template void f<int>();
+template void g<int>();
+template void h<int>();
Jason Merrill Sept. 17, 2024, 9:14 p.m. UTC | #4
On 9/17/24 3:22 PM, Patrick Palka wrote:
> On Mon, 16 Sep 2024, Patrick Palka wrote:
> 
>> On Mon, 16 Sep 2024, Andrew Pinski wrote:
>>
>>> On Mon, Sep 16, 2024 at 8:12 AM Patrick Palka <ppalka@redhat.com> wrote:
>>>>
>>>> Bootstrapped and regtested on x86_64-pc-linuxgnu, does this look
>>>> OK for trunk?  Sadly the prerequisity patch r15-2331-g523836716137d0
>>>> probably isn't suitable for backporting, so I reckon this should be
>>>> trunk-only.
>>>>
>>>> -- >8 --
>>>>
>>>> Here we're prematurely stripping the decltype(lambda) alias used inside
>>>> the template-id during ahead of time template argument coercion, which
>>>> means we treat it as if it were
>>>>
>>>>    is_same_v<decltype([]{}), decltype([]{})>
>>>>
>>>> which instead yields false since now we're substituting into the lambda
>>>> twice, and every such substitution yields a unique lambda.  This
>>>> demonstrates that such aliases should be considered opaque, a notion which
>>>> coincidentally we recently introduced in r15-2331-g523836716137d0.
>>>
>>> I wonder if this fixes https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106221  too.
>>> While https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107390 looks it
>>> would be fixed here too.
>>
>> Ah thanks, seems 107390 gets fixed but not 106221..
> 
> Here's v2 which extends the testcase slightly to also subsume the
> PR107390 testcase.
> 
> It also slightly refines the predicate to treat ty2 in
> 
>    using ty1 = decltype([]{});
>    using ty2 = ty1;
> 
> as _not_ opaque (unlike ty1), since we should be able to strip it to
> ty1.  I don't know if this makes a difference but it seems the
> conceptually right thing to do.

This seems a bit of a kludge, but a good one; easier than trying to 
reuse the previous lambda substitution in one case and not others.  But 
please add an explanatory comment.  OK with the comment.

> -- >8 --
> 
> Subject: [PATCH] c++: alias of decltype(lambda) is opaque [PR116714, PR107390]
> 
> 	PR c++/116714
> 	PR c++/107390
> 
> gcc/cp/ChangeLog:
> 
> 	* pt.cc (dependent_opaque_alias_p): Also return true for a
> 	decltype(lambda) alias.
> 
> gcc/testsuite/ChangeLog:
> 
> 	* g++.dg/cpp2a/lambda-uneval18.C: New test.
> ---
>   gcc/cp/pt.cc                                 |  7 +++-
>   gcc/testsuite/g++.dg/cpp2a/lambda-uneval18.C | 39 ++++++++++++++++++++
>   2 files changed, 44 insertions(+), 2 deletions(-)
>   create mode 100644 gcc/testsuite/g++.dg/cpp2a/lambda-uneval18.C
> 
> diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
> index 04987f66746..b29ea164a91 100644
> --- a/gcc/cp/pt.cc
> +++ b/gcc/cp/pt.cc
> @@ -6764,8 +6764,11 @@ dependent_opaque_alias_p (const_tree t)
>   {
>     return (TYPE_P (t)
>   	  && typedef_variant_p (t)
> -	  && any_dependent_type_attributes_p (DECL_ATTRIBUTES
> -					      (TYPE_NAME (t))));
> +	  && (any_dependent_type_attributes_p (DECL_ATTRIBUTES
> +					       (TYPE_NAME (t)))
> +	      || (TREE_CODE (t) == DECLTYPE_TYPE
> +		  && TREE_CODE (DECLTYPE_TYPE_EXPR (t)) == LAMBDA_EXPR
> +		  && !typedef_variant_p (DECL_ORIGINAL_TYPE (TYPE_NAME (t))))));
>   }
>   
>   /* Return the number of innermost template parameters in TMPL.  */
> diff --git a/gcc/testsuite/g++.dg/cpp2a/lambda-uneval18.C b/gcc/testsuite/g++.dg/cpp2a/lambda-uneval18.C
> new file mode 100644
> index 00000000000..b7d864c6245
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp2a/lambda-uneval18.C
> @@ -0,0 +1,39 @@
> +// PR c++/116714
> +// PR c++/107390
> +// { dg-do compile { target c++20 } }
> +
> +template<class T, class U>
> +inline constexpr bool is_same_v = __is_same(T, U);
> +
> +template<class T, class U>
> +struct is_same { static constexpr bool value = false; };
> +
> +template<class T>
> +struct is_same<T, T> { static constexpr bool value = true; };
> +
> +template<class>
> +void f() {
> +  using type = decltype([]{});
> +  static_assert(is_same_v<type, type>);
> +  static_assert(is_same<type, type>::value);
> +};
> +
> +template<class>
> +void g() {
> +  using ty1 = decltype([]{});
> +  using ty2 = ty1;
> +  static_assert(is_same_v<ty1, ty2>);
> +  static_assert(is_same<ty1, ty2>::value);
> +};
> +
> +template<class>
> +void h() {
> +  using ty1 = decltype([]{});
> +  using ty2 = decltype([]{});
> +  static_assert(!is_same_v<ty1, ty2>);
> +  static_assert(!is_same<ty1, ty2>::value);
> +};
> +
> +template void f<int>();
> +template void g<int>();
> +template void h<int>();
diff mbox series

Patch

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 04987f66746..a72a1eadbc7 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -6764,8 +6764,10 @@  dependent_opaque_alias_p (const_tree t)
 {
   return (TYPE_P (t)
 	  && typedef_variant_p (t)
-	  && any_dependent_type_attributes_p (DECL_ATTRIBUTES
-					      (TYPE_NAME (t))));
+	  && (any_dependent_type_attributes_p (DECL_ATTRIBUTES
+					       (TYPE_NAME (t)))
+	      || (TREE_CODE (t) == DECLTYPE_TYPE
+		  && TREE_CODE (DECLTYPE_TYPE_EXPR (t)) == LAMBDA_EXPR)));
 }
 
 /* Return the number of innermost template parameters in TMPL.  */
diff --git a/gcc/testsuite/g++.dg/cpp2a/lambda-uneval18.C b/gcc/testsuite/g++.dg/cpp2a/lambda-uneval18.C
new file mode 100644
index 00000000000..2942f8305c7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/lambda-uneval18.C
@@ -0,0 +1,20 @@ 
+// PR c++/116714
+// { dg-do compile { target c++20 } }
+
+template<class T, class U>
+inline constexpr bool is_same_v = __is_same(T, U);
+
+template<class T, class U>
+struct is_same { static constexpr bool value = false; };
+
+template<class T>
+struct is_same<T, T> { static constexpr bool value = true; };
+
+template<class>
+void f() {
+  using type = decltype([]{});
+  static_assert(is_same_v<type, type>);
+  static_assert(is_same<type, type>::value);
+};
+
+template void f<int>();