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