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 <ppa...@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>();

Reply via email to