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>();