c++: alias of decltype(lambda) is opaque [PR116714, PR107390]
Here for using type = decltype([]{}); static_assert(is_same_v<type, type>); we strip the alias ahead of time during template argument coercion which effectively transforms the template-id into is_same_v<decltype([]{}), decltype([]{})> which is wrong because later substitution into the template-id will produce two new lambdas with distinct types and cause is_same_v to return false. This demonstrates that such aliases should be considered opaque (a notion that we recently introduced in r15-2331-g523836716137d0). (An alternative solution might be to consider memoizing lambda-expr substitution rather than always producing a new lambda, but this is much simpler.) 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. Reviewed-by: Jason Merrill <jason@redhat.com>
This commit is contained in:
parent
fe1ed68000
commit
82c2acd0bc
2 changed files with 48 additions and 2 deletions
11
gcc/cp/pt.cc
11
gcc/cp/pt.cc
|
@ -6759,8 +6759,15 @@ 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)))
|
||||
/* Treat a dependent decltype(lambda) alias as opaque so that we
|
||||
don't prematurely strip it when used as a template argument.
|
||||
Otherwise substitution into each occurrence of the (stripped)
|
||||
alias would incorrectly yield a distinct lambda type. */
|
||||
|| (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. */
|
||||
|
|
39
gcc/testsuite/g++.dg/cpp2a/lambda-uneval18.C
Normal file
39
gcc/testsuite/g++.dg/cpp2a/lambda-uneval18.C
Normal file
|
@ -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>();
|
Loading…
Add table
Reference in a new issue