https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127559
--- Comment #15 from GCC Commits <cvs-commit at gcc dot gnu.org> --- The master branch has been updated by Jakub Jelinek <[email protected]>: https://gcc.gnu.org/g:84d5fecd2694ad70f391a20451d43d82fde37eb5 commit r17-5272-g84d5fecd2694ad70f391a20451d43d82fde37eb5 Author: Jakub Jelinek <[email protected]> Date: Sat Oct 17 10:15:58 2026 +0200 openmp c++: Temporary fix for some lambda mapping problems [PR127559] The handling of lambda mapping in the C++ FE is IMHO misplaced, I think it shouldn't be based on target region's body search, but done during clause processing at gimplification time like declare mapper (though, haven't verified whether declare mapper is handled there). Basically, any time we map some lambda (determined by a target hook), perform as a magic intrinsic declare mapper for that class the extra required steps for mapping references or pointers inside of that class (and obviously it needs to be recursive, because aggregates without explicit declare mapper are mapped as if mapping each of its direct subobjects), and in a loop that will deal if this maps further lambdas or aggregates with lambdas as subobjects (e.g. if some lambda contains a reference to a structure containing another lambda). The PR contains some testcases and examples how to construct various aggregates for testing. What e.g. the current walking of body can't handle is template <typename T> struct S { T x; int y; }; template <typename T> int bar (T &x) { return x.x (); } void foo (int x) { auto b = [&] { return x; }; S <decltype (b)> c = { b, 42 }; #pragma omp target if (bar (c) != 42) __builtin_abort (); } int main () { foo (42); } Here the walk doesn't see any expression with LAMBDA_TYPE_P type in the body. I don't have cycles to rewrite this, so here is just a temporary workaround, fix some problems in the current FE handling. The first change is just an optimization, we really don't care about TYPE_DECLs, CONST_DECLs, FUNCTION_DECLs, USING_DECLs etc. inside of local_decls, so limit that to VAR_DECLs, PARM_DECLs and RESULT_DECLs. The second change is to remove *walk_subtrees = 0;, e.g. if we have TARGET_EXPR <D.1234, b> which is used e.g. when passing a lambda by value to a function, we do want to walk the TARGET_EXPR_INITIAL. We just want to handle the TARGET_EXPR_SLOT as a local decl (hopefully TARGET_EXPRs from outside of the target region shouldn't appear inside of the target region). Also, we really can't map arbitrary expressions, say a function returning a lambda, or returning a pointer/reference to a lambda, ... This patch limits the mapping to VAR_DECLs, PARM_DECLs, RESULT_DECLs (and checks if they aren't local_decls), or their COMPONENT_REFs/ARRAY_REFs, that is something the previous code handled (just didn't verify the base is not a local decl). Even handling ARRAY_REFs like this isn't fully correct, if array index is constant, it is fine, if array index is some VAR_DECL firstprivatized in the target region, it will work too, but if it is arbitrary expression e.g. using vars from the target region, doing function calls, other side-effects in the target region, it will be wrong-code or ICE. 2026-10-17 Jakub Jelinek <[email protected]> PR c++/127559 * semantics.cc (finish_omp_target_clauses_r): Only record in local_decls VAR_DECLs, PARM_DECLs and RESULT_DECLs. For TARGET_EXPR with lambda type mark TARGET_EXPR_SLOT in local_decls too. Never *walk_subtrees = 0; for lambdas. Don't add arbitrary expressions of lambda type to lambda_objects_accessed, only VAR_DECLs, PARM_DECLs or RESULT_DECLs possibly with COMPONENT_REFs or ARRAY_REFs around those. If it is handled component case, check in local_decls the base variable rather than whole expression. * testsuite/libgomp.c++/target-lambda-5.C: New test. * testsuite/libgomp.c++/target-lambda-6.C: New test.
