mirror of
https://gcc.gnu.org/git/gcc.git
synced 2026-02-22 03:46:53 -05:00
c++: non-trivial by-value deducing this lambda [PR121500]
Here the lambda has a by-value capture of non-trivial type, which
in turn makes the closure type non-trivial. This means its by-value
'this' parameter, which gets deduced to the closure type, becomes an
invisiref parameter, and so when lowering the operator() body we need to
adjust uses of 'this' by adding implicit dereferences.
But the GIMPLE dump for operator() shows that we miss some adjustments:
bool main()::<lambda(this auto:1)>::operator()<main()::<lambda(this auto:1)> > (struct ._anon_0 & self)
{
bool D.3091;
struct ._anon_0 & self.1;
struct A a [value-expr: self.__a]; // should be self->__a
self.1 = self;
_1 = self.1.__a.n; // should be self.1->__a
D.3091 = _1 == 42;
return D.3091;
}
Apparently this is because cp_genericize_r, which is responsible for the
invisiref use adjustments, never walks DECL_VALUE_EXPR. This patch makes
us walk it. For GCC 16, restrict the walking to xobj lambdas.
PR c++/121500
gcc/cp/ChangeLog:
* cp-gimplify.cc (cp_genericize_r): Walk DECL_VALUE_EXPR within
an xobj lambda.
gcc/testsuite/ChangeLog:
* g++.dg/cpp23/explicit-obj-lambda20.C: New test.
Reviewed-by: Jason Merrill <jason@redhat.com>
This commit is contained in:
@@ -1922,6 +1922,22 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
if ((TREE_CODE (stmt) == VAR_DECL
|
||||
|| TREE_CODE (stmt) == PARM_DECL
|
||||
|| TREE_CODE (stmt) == RESULT_DECL)
|
||||
&& DECL_HAS_VALUE_EXPR_P (stmt)
|
||||
/* Walk DECL_VALUE_EXPR mainly for benefit of xobj lambdas so that we
|
||||
adjust any invisiref object parm uses within the capture proxies.
|
||||
TODO: For GCC 17 do this walking unconditionally. */
|
||||
&& current_function_decl
|
||||
&& DECL_XOBJ_MEMBER_FUNCTION_P (current_function_decl)
|
||||
&& LAMBDA_FUNCTION_P (current_function_decl))
|
||||
{
|
||||
tree ve = DECL_VALUE_EXPR (stmt);
|
||||
cp_walk_tree (&ve, cp_genericize_r, data, NULL);
|
||||
SET_DECL_VALUE_EXPR (stmt, ve);
|
||||
}
|
||||
|
||||
switch (TREE_CODE (stmt))
|
||||
{
|
||||
case ADDR_EXPR:
|
||||
|
||||
17
gcc/testsuite/g++.dg/cpp23/explicit-obj-lambda20.C
Normal file
17
gcc/testsuite/g++.dg/cpp23/explicit-obj-lambda20.C
Normal file
@@ -0,0 +1,17 @@
|
||||
// PR c++/121500
|
||||
// { dg-do run { target c++23 } }
|
||||
|
||||
struct A {
|
||||
A() = default;
|
||||
A(const A& other) : n(other.n) { }
|
||||
int n = 42;
|
||||
};
|
||||
|
||||
int main() {
|
||||
A a;
|
||||
auto l = [a](this auto self) {
|
||||
return a.n == 42;
|
||||
};
|
||||
if (!l())
|
||||
__builtin_abort();
|
||||
}
|
||||
Reference in New Issue
Block a user