https://gcc.gnu.org/g:e0b3eeb67f6d3bfe95591d8fb0c7dfd3f1b3b4ef

commit r15-8462-ge0b3eeb67f6d3bfe95591d8fb0c7dfd3f1b3b4ef
Author: Jakub Jelinek <ja...@redhat.com>
Date:   Thu Mar 20 09:06:17 2025 +0100

    openmp: Fix up cloning of dynamic C++ initializers for OpenMP target 
[PR119370]
    
    The following testcase ICEs, because we emit the dynamic initialization 
twice,
    once for host and once for target initialization, and although we use
    copy_tree_body_r to unshare it, e.g. for the array initializers it can 
contain
    TARGET_EXPRs with local temporaries (or local temporaries alone).
    Now, these temporaries were created when current_function_decl was NULL,
    they are outside of any particular function, so they have DECL_CONTEXT NULL.
    That is normally fine, gimple_add_tmp_var will set DECL_CONTEXT for them
    later on to the host __static_init* function into which they are gimplified.
    The problem is that the copy_tree_body_r cloning happens before that (and 
has
    to, gimplification is destructive and so we couldn't gimplify the same tree
    again in __omp_static_init* function) and uses auto_var_in_fn_p to see what
    needs to be remapped.  But that means it doesn't remap temporaries with
    NULL DECL_CONTEXT and having the same temporaries in two different functions
    results in ICEs (sure, one can e.g. use parent function's temporaries in a
    nested function).
    
    The following patch just arranges to set DECL_CONTEXT on the temporaries
    to the host dynamic initialization function, so that they get remapped.
    If gimplification cared whether DECL_CONTEXT is NULL or not, we could
    remember those that we've changed in a vector and undo it afterwards,
    but seems it doesn't really care.
    
    2025-03-20  Jakub Jelinek  <ja...@redhat.com>
    
            PR c++/119370
            * decl2.cc (set_context_for_auto_vars_r): New function.
            (emit_partial_init_fini_fn): Call walk_tree with that function
            on &init before walk_tree with copy_tree_body_r.
    
            * g++.dg/gomp/pr119370.C: New test.

Diff:
---
 gcc/cp/decl2.cc                      | 18 ++++++++++++++++++
 gcc/testsuite/g++.dg/gomp/pr119370.C | 10 ++++++++++
 2 files changed, 28 insertions(+)

diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc
index a3149f266030..4987987daed7 100644
--- a/gcc/cp/decl2.cc
+++ b/gcc/cp/decl2.cc
@@ -4603,6 +4603,23 @@ decomp_finalize_var_list (tree sl, int 
save_stmts_are_full_exprs_p)
     }
 }
 
+/* Helper for emit_partial_init_fini_fn OpenMP target handling, called via
+   walk_tree.  Set DECL_CONTEXT on any automatic temporaries which still
+   have it NULL to id->src_fn, so that later copy_tree_body_r can remap those.
+   Otherwise DECL_CONTEXT would be set only during gimplification of the host
+   fn and when copy_tree_body_r doesn't remap those, we'd ICE during the
+   target fn gimplification because the same automatic VAR_DECL can't be
+   used in multiple functions (with the exception of nested functions).  */
+
+static tree
+set_context_for_auto_vars_r (tree *tp, int *, void *data)
+{
+  copy_body_data *id = (copy_body_data *) data;
+  if (auto_var_in_fn_p (*tp, NULL_TREE) && DECL_ARTIFICIAL (*tp))
+    DECL_CONTEXT (*tp) = id->src_fn;
+  return NULL_TREE;
+}
+
 /* Generate code to do the initialization or destruction of the decls in VARS,
    a TREE_LIST of VAR_DECL with static storage duration.
    Whether initialization or destruction is performed is specified by INITP.  
*/
@@ -4661,6 +4678,7 @@ emit_partial_init_fini_fn (bool initp, unsigned priority, 
tree vars,
          id.transform_new_cfg = true;
          id.transform_return_to_modify = false;
          id.eh_lp_nr = 0;
+         walk_tree (&init, set_context_for_auto_vars_r, &id, NULL);
          walk_tree (&init, copy_tree_body_r, &id, NULL);
        }
       /* Do one initialization or destruction.  */
diff --git a/gcc/testsuite/g++.dg/gomp/pr119370.C 
b/gcc/testsuite/g++.dg/gomp/pr119370.C
new file mode 100644
index 000000000000..9ecc9b73db84
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/pr119370.C
@@ -0,0 +1,10 @@
+// PR c++/119370
+// { dg-do compile }
+
+#pragma omp declare target
+struct S {
+  int s;
+  S () : s (0) {}
+};
+S a[2];
+#pragma omp end declare target

Reply via email to