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 <jakub@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.
This commit is contained in:
parent
62a6cafd7f
commit
e0b3eeb67f
2 changed files with 28 additions and 0 deletions
|
@ -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. */
|
||||
|
|
10
gcc/testsuite/g++.dg/gomp/pr119370.C
Normal file
10
gcc/testsuite/g++.dg/gomp/pr119370.C
Normal file
|
@ -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
|
Loading…
Add table
Reference in a new issue