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.

Reply via email to