* Re: [PATCH] [og12] OpenMP: Constructors and destructors for "declare target" static aggregates
2023-03-27 18:54 [PATCH] [og12] OpenMP: Constructors and destructors for "declare target" static aggregates Julian Brown
@ 2023-04-02 9:38 ` Thomas Schwinge
2023-04-05 12:31 ` Julian Brown
0 siblings, 1 reply; 3+ messages in thread
From: Thomas Schwinge @ 2023-04-02 9:38 UTC (permalink / raw)
To: Julian Brown, gcc-patches; +Cc: Jakub Jelinek, Tobias Burnus
[-- Attachment #1: Type: text/plain, Size: 26641 bytes --]
Hi Julian!
On 2023-03-27T18:54:30+0000, Julian Brown <julian@codesourcery.com> wrote:
> This patch adds support for running constructors and destructors for
> static (file-scope) aggregates for C++ objects which are marked with
> "declare target" directives on OpenMP offload targets.
>
> At present, space is allocated on the target for such aggregates, but
> nothing ever constructs them properly, so they end up zero-initialised.
So you've settled that on-device construction is the way to go, and not
on-host construction before host-to-device copy?
I now wonder if we didn't once have a similar issue with Fortran array
constructors, and how we solved that one. (I may be misremembering.)
> Tested with offloading to AMD GCN. I will apply to the og12 branch
> shortly.
I've pushed to devel/omp/gcc-12 branch
commit 472783f3137475b82baadac31cca31021b69aba9
"Resolve 'error: unused parameter' in 'gcc/cp/decl2.cc:one_static_initialization_or_destruction'",
see attached.
But glancing at test results, I also see a good number of ICEs. That's
with '--enable-checking=yes,extra,rtl'.
build-gcc/gcc/testsuite/g++/g++.sum | 924 ++++++++++++---------
.../libgomp/testsuite/libgomp.sum | 438 ++++++----
Those are mostly instances of:
internal compiler error: tree check: expected omp_clause, have tree_list in c_parse_final_cleanups, at cp/decl2.cc:5291
..., but also:
FAIL: libgomp.c++/static-aggr-constructor-destructor-1.C (internal compiler error: tree check: expected omp_clause, have tree_list in c_parse_final_cleanups, at cp/decl2.cc:5289)
FAIL: libgomp.c++/static-aggr-constructor-destructor-1.C (test for excess errors)
UNRESOLVED: libgomp.c++/static-aggr-constructor-destructor-1.C compilation failed to produce executable
FAIL: libgomp.c++/static-aggr-constructor-destructor-2.C (internal compiler error: tree check: expected omp_clause, have tree_list in c_parse_final_cleanups, at cp/decl2.cc:5289)
FAIL: libgomp.c++/static-aggr-constructor-destructor-2.C (test for excess errors)
UNRESOLVED: libgomp.c++/static-aggr-constructor-destructor-2.C compilation failed to produce executable
That's in new 'gcc/cp/decl2.cc' code that you've added:
5283 while (*fvarsp)
5284 {
5285 tree decl = TREE_VALUE (*fvarsp);
5286
5287 if (lookup_attribute ("omp declare target",
5288 DECL_ATTRIBUTES (decl)))
5289 fvarsp = &OMP_CLAUSE_CHAIN (*fvarsp);
5290 else
5291 *fvarsp = OMP_CLAUSE_CHAIN (*fvarsp);
5292 }
Please have a look.
Grüße
Thomas
> gcc/cp/
> * decl2.cc (priority_info): Add omp_tgt_initializations_p and
> omp_tgt_destructions_p.
> (start_objects, start_static_storage_duration_function,
> do_static_initialization_or_destruction,
> one_static_initialization_or_destruction,
> generate_ctor_or_dtor_function): Add 'omp_target' parameter. Support
> "declare target" decls. Update forward declarations.
> (OMP_SSDF_IDENTIFIER): New macro.
> (omp_tgt_ssdf_decls): New vec.
> (get_priority_info): Initialize omp_tgt_initializations_p and
> omp_tgt_destructions_p fields.
> (handle_tls_init): Update call to
> omp_static_initialization_or_destruction.
> (c_parse_final_cleanups): Support constructors/destructors on OpenMP
> offload targets.
>
> gcc/
> * omp-builtins.def (BUILT_IN_OMP_IS_INITIAL_DEVICE): New builtin.
> * tree.cc (get_file_function_name): Support names for on-target
> constructor/destructor functions.
>
> libgomp/
> * testsuite/libgomp.c++/static-aggr-constructor-destructor-1.C: New
> test.
> * testsuite/libgomp.c++/static-aggr-constructor-destructor-2.C: New
> test.
> ---
> gcc/cp/decl2.cc | 225 +++++++++++++++---
> gcc/omp-builtins.def | 2 +
> gcc/tree.cc | 6 +-
> .../static-aggr-constructor-destructor-1.C | 28 +++
> .../static-aggr-constructor-destructor-2.C | 31 +++
> 5 files changed, 257 insertions(+), 35 deletions(-)
> create mode 100644 libgomp/testsuite/libgomp.c++/static-aggr-constructor-destructor-1.C
> create mode 100644 libgomp/testsuite/libgomp.c++/static-aggr-constructor-destructor-2.C
>
> diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc
> index f1a6df375e8..042ae4df700 100644
> --- a/gcc/cp/decl2.cc
> +++ b/gcc/cp/decl2.cc
> @@ -65,16 +65,19 @@ typedef struct priority_info_s {
> /* Nonzero if there have been any destructions at this priority
> throughout the translation unit. */
> int destructions_p;
> + /* Again, but specifically for OpenMP "declare target" initializations. */
> + int omp_tgt_initializations_p;
> + int omp_tgt_destructions_p;
> } *priority_info;
>
> -static tree start_objects (int, int);
> +static tree start_objects (int, int, bool);
> static void finish_objects (int, int, tree);
> -static tree start_static_storage_duration_function (unsigned);
> +static tree start_static_storage_duration_function (unsigned, bool);
> static void finish_static_storage_duration_function (tree);
> static priority_info get_priority_info (int);
> -static void do_static_initialization_or_destruction (tree, bool);
> -static void one_static_initialization_or_destruction (tree, tree, bool);
> -static void generate_ctor_or_dtor_function (bool, int, location_t *);
> +static void do_static_initialization_or_destruction (tree, bool, bool);
> +static void one_static_initialization_or_destruction (tree, tree, bool, bool);
> +static void generate_ctor_or_dtor_function (bool, int, location_t *, bool);
> static int generate_ctor_and_dtor_functions_for_priority (splay_tree_node,
> void *);
> static tree prune_vars_needing_no_initialization (tree *);
> @@ -3791,7 +3794,7 @@ generate_tls_wrapper (tree fn)
> vtv_start_verification_constructor_init_function. */
>
> static tree
> -start_objects (int method_type, int initp)
> +start_objects (int method_type, int initp, bool omp_target = false)
> {
> /* Make ctor or dtor function. METHOD_TYPE may be 'I' or 'D'. */
> int module_init = 0;
> @@ -3806,7 +3809,16 @@ start_objects (int method_type, int initp)
> {
> char type[14];
>
> - unsigned len = sprintf (type, "sub_%c", method_type);
> + unsigned len;
> + if (omp_target)
> + /* Use "off_" signifying "offload" here. The name must be distinct
> + from the non-offload case. The format of the name is scanned in
> + tree.cc/get_file_function_name, so stick to the same length for
> + both name variants. */
> + len = sprintf (type, "off_%c", method_type);
> + else
> + len = sprintf (type, "sub_%c", method_type);
> +
> if (initp != DEFAULT_INIT_PRIORITY)
> {
> char joiner = '_';
> @@ -3821,6 +3833,17 @@ start_objects (int method_type, int initp)
>
> tree fntype = build_function_type (void_type_node, void_list_node);
> tree fndecl = build_lang_decl (FUNCTION_DECL, name, fntype);
> +
> + if (omp_target)
> + {
> + DECL_ATTRIBUTES (fndecl)
> + = tree_cons (get_identifier ("omp declare target"), NULL_TREE,
> + DECL_ATTRIBUTES (fndecl));
> + DECL_ATTRIBUTES (fndecl)
> + = tree_cons (get_identifier ("omp declare target nohost"), NULL_TREE,
> + DECL_ATTRIBUTES (fndecl));
> + }
> +
> DECL_CONTEXT (fndecl) = FROB_CONTEXT (global_namespace);
> if (module_init > 0)
> {
> @@ -3911,6 +3934,7 @@ finish_objects (int method_type, int initp, tree body)
> /* The name of the function we create to handle initializations and
> destructions for objects with static storage duration. */
> #define SSDF_IDENTIFIER "__static_initialization_and_destruction"
> +#define OMP_SSDF_IDENTIFIER "__omp_target_static_init_and_destruction"
>
> /* The declaration for the __INITIALIZE_P argument. */
> static GTY(()) tree initialize_p_decl;
> @@ -3925,6 +3949,9 @@ static GTY(()) tree ssdf_decl;
> translation unit. */
> static GTY(()) vec<tree, va_gc> *ssdf_decls;
>
> +/* Same, but specifically for offloaded OpenMP "declare target" functions. */
> +static GTY(()) vec<tree, va_gc> *omp_tgt_ssdf_decls;
> +
> /* A map from priority levels to information about that priority
> level. There may be many such levels, so efficient lookup is
> important. */
> @@ -3943,24 +3970,37 @@ static splay_tree priority_info_map;
> translation unit. */
>
> static tree
> -start_static_storage_duration_function (unsigned count)
> +start_static_storage_duration_function (unsigned count, bool omp_target)
> {
> tree type;
> tree body;
> - char id[sizeof (SSDF_IDENTIFIER) + 1 /* '\0' */ + 32];
> + tree name;
>
> - /* Create the identifier for this function. It will be of the form
> - SSDF_IDENTIFIER_<number>. */
> - sprintf (id, "%s_%u", SSDF_IDENTIFIER, count);
> + if (omp_target)
> + {
> + char id[sizeof (OMP_SSDF_IDENTIFIER) + 1 /* '\0' */ + 32];
> +
> + /* Create the identifier for this function. It will be of the form
> + SSDF_IDENTIFIER_<number>. */
> + sprintf (id, "%s_%u", OMP_SSDF_IDENTIFIER, count);
> + name = get_identifier (id);
> + }
> + else
> + {
> + char id[sizeof (SSDF_IDENTIFIER) + 1 /* '\0' */ + 32];
> +
> + /* Create the identifier for this function. It will be of the form
> + SSDF_IDENTIFIER_<number>. */
> + sprintf (id, "%s_%u", SSDF_IDENTIFIER, count);
> + name = get_identifier (id);
> + }
>
> type = build_function_type_list (void_type_node,
> integer_type_node, integer_type_node,
> NULL_TREE);
>
> /* Create the FUNCTION_DECL itself. */
> - ssdf_decl = build_lang_decl (FUNCTION_DECL,
> - get_identifier (id),
> - type);
> + ssdf_decl = build_lang_decl (FUNCTION_DECL, name, type);
> TREE_PUBLIC (ssdf_decl) = 0;
> DECL_ARTIFICIAL (ssdf_decl) = 1;
>
> @@ -3984,7 +4024,14 @@ start_static_storage_duration_function (unsigned count)
> get_priority_info (DEFAULT_INIT_PRIORITY);
> }
>
> - vec_safe_push (ssdf_decls, ssdf_decl);
> + if (omp_target && !omp_tgt_ssdf_decls)
> + /* Static constructors and destructors for "declare target" variables. */
> + vec_alloc (omp_tgt_ssdf_decls, 32);
> +
> + if (omp_target)
> + vec_safe_push (omp_tgt_ssdf_decls, ssdf_decl);
> + else
> + vec_safe_push (ssdf_decls, ssdf_decl);
>
> /* Create the argument list. */
> initialize_p_decl = cp_build_parm_decl
> @@ -3997,6 +4044,16 @@ start_static_storage_duration_function (unsigned count)
> DECL_CHAIN (initialize_p_decl) = priority_decl;
> DECL_ARGUMENTS (ssdf_decl) = initialize_p_decl;
>
> + if (omp_target)
> + {
> + DECL_ATTRIBUTES (ssdf_decl)
> + = tree_cons (get_identifier ("omp declare target"), NULL_TREE,
> + DECL_ATTRIBUTES (ssdf_decl));
> + DECL_ATTRIBUTES (ssdf_decl)
> + = tree_cons (get_identifier ("omp declare target nohost"), NULL_TREE,
> + DECL_ATTRIBUTES (ssdf_decl));
> + }
> +
> /* Put the function in the global scope. */
> pushdecl (ssdf_decl);
>
> @@ -4048,6 +4105,8 @@ get_priority_info (int priority)
> pi = XNEW (struct priority_info_s);
> pi->initializations_p = 0;
> pi->destructions_p = 0;
> + pi->omp_tgt_initializations_p = 0;
> + pi->omp_tgt_destructions_p = 0;
> splay_tree_insert (priority_info_map,
> (splay_tree_key) priority,
> (splay_tree_value) pi);
> @@ -4108,7 +4167,8 @@ fix_temporary_vars_context_r (tree *node,
> are destroying it. */
>
> static void
> -one_static_initialization_or_destruction (tree decl, tree init, bool initp)
> +one_static_initialization_or_destruction (tree decl, tree init, bool initp,
> + bool omp_target)
> {
> tree guard_if_stmt = NULL_TREE;
> tree guard;
> @@ -4255,7 +4315,7 @@ one_static_initialization_or_destruction (tree decl, tree init, bool initp)
> Whether initialization or destruction is performed is specified by INITP. */
>
> static void
> -do_static_initialization_or_destruction (tree vars, bool initp)
> +do_static_initialization_or_destruction (tree vars, bool initp, bool omp_target)
> {
> tree node, init_if_stmt, cond;
>
> @@ -4298,10 +4358,14 @@ do_static_initialization_or_destruction (tree vars, bool initp)
> priority. */
> priority = DECL_EFFECTIVE_INIT_PRIORITY (decl);
> pi = get_priority_info (priority);
> - if (initp)
> + if (initp && !omp_target)
> pi->initializations_p = 1;
> - else
> + else if (!omp_target)
> pi->destructions_p = 1;
> + else if (initp && omp_target)
> + pi->omp_tgt_initializations_p = 1;
> + else
> + pi->omp_tgt_destructions_p = 1;
>
> /* Conditionalize this initialization on being in the right priority
> and being initializing/finalizing appropriately. */
> @@ -4317,9 +4381,17 @@ do_static_initialization_or_destruction (tree vars, bool initp)
> for (; node
> && DECL_EFFECTIVE_INIT_PRIORITY (TREE_VALUE (node)) == priority;
> node = TREE_CHAIN (node))
> - /* Do one initialization or destruction. */
> - one_static_initialization_or_destruction (TREE_VALUE (node),
> - TREE_PURPOSE (node), initp);
> + {
> + tree decl = TREE_VALUE (node);
> + tree init = TREE_PURPOSE (node);
> + /* We will emit 'init' twice, and it is modified in-place during
> + gimplification. Make a copy here. */
> + if (omp_target)
> + init = copy_node (init);
> + /* Do one initialization or destruction. */
> + one_static_initialization_or_destruction (decl, init, initp,
> + omp_target);
> + }
>
> /* Finish up the priority if-stmt body. */
> finish_then_clause (priority_if_stmt);
> @@ -4419,7 +4491,7 @@ write_out_vars (tree vars)
>
> static void
> generate_ctor_or_dtor_function (bool constructor_p, int priority,
> - location_t *locus)
> + location_t *locus, bool omp_target)
> {
> input_location = *locus;
>
> @@ -4451,13 +4523,14 @@ generate_ctor_or_dtor_function (bool constructor_p, int priority,
> arguments. */
> tree fndecl;
> size_t i;
> - FOR_EACH_VEC_SAFE_ELT (ssdf_decls, i, fndecl)
> + vec<tree, va_gc> *walk_decls = omp_target ? omp_tgt_ssdf_decls : ssdf_decls;
> + FOR_EACH_VEC_SAFE_ELT (walk_decls, i, fndecl)
> {
> /* Calls to pure or const functions will expand to nothing. */
> if (! (flags_from_decl_or_type (fndecl) & (ECF_CONST | ECF_PURE)))
> {
> if (! body)
> - body = start_objects (function_key, priority);
> + body = start_objects (function_key, priority, omp_target);
>
> tree call = cp_build_function_call_nary (fndecl, tf_warning_or_error,
> build_int_cst (NULL_TREE,
> @@ -4487,9 +4560,17 @@ generate_ctor_and_dtor_functions_for_priority (splay_tree_node n, void * data)
> /* Generate the functions themselves, but only if they are really
> needed. */
> if (pi->initializations_p)
> - generate_ctor_or_dtor_function (/*constructor_p=*/true, priority, locus);
> + generate_ctor_or_dtor_function (/*constructor_p=*/true, priority, locus,
> + /*omp_target=*/false);
> if (pi->destructions_p)
> - generate_ctor_or_dtor_function (/*constructor_p=*/false, priority, locus);
> + generate_ctor_or_dtor_function (/*constructor_p=*/false, priority, locus,
> + /*omp_target=*/false);
> + if (pi->omp_tgt_initializations_p)
> + generate_ctor_or_dtor_function (/*constructor_p=*/true, priority, locus,
> + /*omp_target=*/true);
> + if (pi->omp_tgt_destructions_p)
> + generate_ctor_or_dtor_function (/*constructor_p=*/false, priority, locus,
> + /*omp_target=*/true);
>
> /* Keep iterating. */
> return 0;
> @@ -4773,7 +4854,7 @@ handle_tls_init (void)
> {
> tree var = TREE_VALUE (vars);
> tree init = TREE_PURPOSE (vars);
> - one_static_initialization_or_destruction (var, init, true);
> + one_static_initialization_or_destruction (var, init, true, false);
>
> /* Output init aliases even with -fno-extern-tls-init. */
> if (TARGET_SUPPORTS_ALIASES && TREE_PUBLIC (var))
> @@ -5087,6 +5168,7 @@ c_parse_final_cleanups (void)
>
> int retries = 0;
> unsigned ssdf_count = 0;
> + unsigned omp_target_ssdf_count = 0;
> for (bool reconsider = true; reconsider; retries++)
> {
> reconsider = false;
> @@ -5160,11 +5242,18 @@ c_parse_final_cleanups (void)
> /* Set the line and file, so that it is obviously not from
> the source file. */
> input_location = locus_at_end_of_parsing;
> - ssdf_body = start_static_storage_duration_function (ssdf_count);
> + ssdf_body
> + = start_static_storage_duration_function (ssdf_count, false);
>
> /* First generate code to do all the initializations. */
> if (vars)
> - do_static_initialization_or_destruction (vars, /*initp=*/true);
> + do_static_initialization_or_destruction (vars, /*initp=*/true,
> + /*omp_target=*/false);
> +
> + tree filtered_vars = NULL_TREE;
> +
> + if (flag_openmp)
> + filtered_vars = copy_list (vars);
>
> /* Then, generate code to do all the destructions. Do these
> in reverse order so that the most recently constructed
> @@ -5175,7 +5264,8 @@ c_parse_final_cleanups (void)
> if (!flag_use_cxa_atexit && vars)
> {
> vars = nreverse (vars);
> - do_static_initialization_or_destruction (vars, /*initp=*/false);
> + do_static_initialization_or_destruction (vars, /*initp=*/false,
> + /*omp_target=*/false);
> }
> else
> vars = NULL_TREE;
> @@ -5185,6 +5275,74 @@ c_parse_final_cleanups (void)
> input_location = locus_at_end_of_parsing;
> finish_static_storage_duration_function (ssdf_body);
>
> + if (flag_openmp)
> + {
> + /* Do all the above again for OpenMP "declare target" static
> + storage duration decls. */
> +
> + /* We're only interested in "declare target" variables now. */
> + tree *fvarsp = &filtered_vars;
> + while (*fvarsp)
> + {
> + tree decl = TREE_VALUE (*fvarsp);
> +
> + if (lookup_attribute ("omp declare target",
> + DECL_ATTRIBUTES (decl)))
> + fvarsp = &OMP_CLAUSE_CHAIN (*fvarsp);
> + else
> + *fvarsp = OMP_CLAUSE_CHAIN (*fvarsp);
> + }
> +
> + input_location = locus_at_end_of_parsing;
> + ssdf_body
> + = start_static_storage_duration_function (omp_target_ssdf_count,
> + /*omp_target=*/true);
> +
> + /* As above, first generate code to do all the
> + initializations. */
> + if (filtered_vars)
> + {
> + tree nonhost_if_stmt = NULL_TREE;
> + nonhost_if_stmt = begin_if_stmt ();
> +
> + /* We add an "omp declare target nohost" attribute, but (for
> + now) we still get a copy of the constructor/destructor on
> + the host. Make sure it does nothing unless we're on the
> + target device. */
> + tree fn
> + = builtin_decl_explicit (BUILT_IN_OMP_IS_INITIAL_DEVICE);
> + tree initial_dev = build_call_expr (fn, 0);
> + tree target_dev_p
> + = cp_build_binary_op (input_location, NE_EXPR, initial_dev,
> + build_int_cst (NULL_TREE, 1),
> + tf_warning_or_error);
> + finish_if_stmt_cond (target_dev_p, nonhost_if_stmt);
> +
> + do_static_initialization_or_destruction (filtered_vars,
> + /*initp=*/true,
> + /*omp_target=*/true);
> + if (!flag_use_cxa_atexit && filtered_vars)
> + {
> + filtered_vars = nreverse (filtered_vars);
> + do_static_initialization_or_destruction (filtered_vars,
> + /*initp=*/false,
> + /*omp_target=*/
> + false);
> + }
> + else
> + filtered_vars = NULL_TREE;
> +
> + /* Finish up nonhost if-stmt body. */
> + finish_then_clause (nonhost_if_stmt);
> + finish_if_stmt (nonhost_if_stmt);
> + }
> +
> + input_location = locus_at_end_of_parsing;
> + finish_static_storage_duration_function (ssdf_body);
> +
> + omp_target_ssdf_count++;
> + }
> +
> /* All those initializations and finalizations might cause
> us to need more inline functions, more template
> instantiations, etc. */
> @@ -5365,7 +5523,8 @@ c_parse_final_cleanups (void)
> || module_initializer_kind ())
> generate_ctor_or_dtor_function (/*constructor_p=*/true,
> DEFAULT_INIT_PRIORITY,
> - &locus_at_end_of_parsing);
> + &locus_at_end_of_parsing,
> + /*omp_target=*/false);
>
> /* We're done with the splay-tree now. */
> if (priority_info_map)
> diff --git a/gcc/omp-builtins.def b/gcc/omp-builtins.def
> index d257278b9e5..b3715b91cbb 100644
> --- a/gcc/omp-builtins.def
> +++ b/gcc/omp-builtins.def
> @@ -68,6 +68,8 @@ DEF_GOACC_BUILTIN_ONLY (BUILT_IN_GOACC_SINGLE_COPY_START, "GOACC_single_copy_sta
> DEF_GOACC_BUILTIN_ONLY (BUILT_IN_GOACC_SINGLE_COPY_END, "GOACC_single_copy_end",
> BT_FN_VOID_PTR, ATTR_NOTHROW_LEAF_LIST)
>
> +DEF_GOMP_BUILTIN (BUILT_IN_OMP_IS_INITIAL_DEVICE, "omp_is_initial_device",
> + BT_FN_INT, ATTR_CONST_NOTHROW_LEAF_LIST)
> DEF_GOMP_BUILTIN (BUILT_IN_OMP_GET_THREAD_NUM, "omp_get_thread_num",
> BT_FN_INT, ATTR_CONST_NOTHROW_LEAF_LIST)
> DEF_GOMP_BUILTIN (BUILT_IN_OMP_GET_NUM_THREADS, "omp_get_num_threads",
> diff --git a/gcc/tree.cc b/gcc/tree.cc
> index 13c23b67a43..aed566fcf0e 100644
> --- a/gcc/tree.cc
> +++ b/gcc/tree.cc
> @@ -8769,9 +8769,11 @@ get_file_function_name (const char *type)
> will be local to this file and the name is only necessary for
> debugging purposes.
> We also assign sub_I and sub_D sufixes to constructors called from
> - the global static constructors. These are always local. */
> + the global static constructors. These are always local.
> + OpenMP "declare target" offloaded constructors/destructors use "off_I" and
> + "off_D" for the same purpose. */
> else if (((type[0] == 'I' || type[0] == 'D') && targetm.have_ctors_dtors)
> - || (startswith (type, "sub_")
> + || ((startswith (type, "sub_") || startswith (type, "off_"))
> && (type[4] == 'I' || type[4] == 'D')))
> {
> const char *file = main_input_filename;
> diff --git a/libgomp/testsuite/libgomp.c++/static-aggr-constructor-destructor-1.C b/libgomp/testsuite/libgomp.c++/static-aggr-constructor-destructor-1.C
> new file mode 100644
> index 00000000000..91d8469a150
> --- /dev/null
> +++ b/libgomp/testsuite/libgomp.c++/static-aggr-constructor-destructor-1.C
> @@ -0,0 +1,28 @@
> +// { dg-do run }
> +
> +#include <cassert>
> +
> +#pragma omp declare target
> +
> +struct str {
> + str(int x) : _x(x) { }
> + int add(str o) { return _x + o._x; }
> + int _x;
> +} v1(5);
> +
> +#pragma omp end declare target
> +
> +int main()
> +{
> + int res = -1;
> + str v2(2);
> +
> +#pragma omp target map(from:res)
> + {
> + res = v1.add(v2);
> + }
> +
> + assert (res == 7);
> +
> + return 0;
> +}
> diff --git a/libgomp/testsuite/libgomp.c++/static-aggr-constructor-destructor-2.C b/libgomp/testsuite/libgomp.c++/static-aggr-constructor-destructor-2.C
> new file mode 100644
> index 00000000000..1bf3ee8e31c
> --- /dev/null
> +++ b/libgomp/testsuite/libgomp.c++/static-aggr-constructor-destructor-2.C
> @@ -0,0 +1,31 @@
> +// { dg-do run }
> +
> +#include <cassert>
> +
> +#pragma omp declare target
> +
> +template<typename T>
> +struct str {
> + str(T x) : _x(x) { }
> + T add(str o) { return _x + o._x; }
> + T _x;
> +};
> +
> +str<long> v1(5);
> +
> +#pragma omp end declare target
> +
> +int main()
> +{
> + long res = -1;
> + str<long> v2(2);
> +
> +#pragma omp target map(from:res)
> + {
> + res = v1.add(v2);
> + }
> +
> + assert (res == 7);
> +
> + return 0;
> +}
> --
> 2.29.2
-----------------
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht München, HRB 106955
[-- Attachment #2: 0001-Resolve-error-unused-parameter-in-gcc-cp-decl2.cc-on.patch --]
[-- Type: text/x-diff, Size: 3629 bytes --]
From 472783f3137475b82baadac31cca31021b69aba9 Mon Sep 17 00:00:00 2001
From: Thomas Schwinge <thomas@codesourcery.com>
Date: Sun, 2 Apr 2023 11:13:33 +0200
Subject: [PATCH] Resolve 'error: unused parameter' in
'gcc/cp/decl2.cc:one_static_initialization_or_destruction'
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
[...]/gcc/cp/decl2.cc: In function ‘void one_static_initialization_or_destruction(tree, tree, bool, bool)’:
[...]/gcc/cp/decl2.cc:4171:48: error: unused parameter ‘omp_target’ [-Werror=unused-parameter]
4171 | bool omp_target)
| ~~~~~^~~~~~~~~~
cc1plus: all warnings being treated as errors
make[3]: *** [cp/decl2.o] Error 1
Fix-up for og12 commit abcb5dbac666513c798e574808f849f76a1c0799
"[og12] OpenMP: Constructors and destructors for "declare target" static aggregates".
gcc/cp/
* decl2.cc (one_static_initialization_or_destruction): Remove
'omp_target' formal parameter. Adjust all users.
---
gcc/cp/ChangeLog.omp | 5 +++++
gcc/cp/decl2.cc | 10 ++++------
2 files changed, 9 insertions(+), 6 deletions(-)
diff --git a/gcc/cp/ChangeLog.omp b/gcc/cp/ChangeLog.omp
index e192ead4925..7a905bb577e 100644
--- a/gcc/cp/ChangeLog.omp
+++ b/gcc/cp/ChangeLog.omp
@@ -1,3 +1,8 @@
+2023-04-02 Thomas Schwinge <thomas@codesourcery.com>
+
+ * decl2.cc (one_static_initialization_or_destruction): Remove
+ 'omp_target' formal parameter. Adjust all users.
+
2023-03-27 Julian Brown <julian@codesourcery.com>
* decl2.cc (priority_info): Add omp_tgt_initializations_p and
diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc
index 042ae4df700..9c007043963 100644
--- a/gcc/cp/decl2.cc
+++ b/gcc/cp/decl2.cc
@@ -76,7 +76,7 @@ static tree start_static_storage_duration_function (unsigned, bool);
static void finish_static_storage_duration_function (tree);
static priority_info get_priority_info (int);
static void do_static_initialization_or_destruction (tree, bool, bool);
-static void one_static_initialization_or_destruction (tree, tree, bool, bool);
+static void one_static_initialization_or_destruction (tree, tree, bool);
static void generate_ctor_or_dtor_function (bool, int, location_t *, bool);
static int generate_ctor_and_dtor_functions_for_priority (splay_tree_node,
void *);
@@ -4167,8 +4167,7 @@ fix_temporary_vars_context_r (tree *node,
are destroying it. */
static void
-one_static_initialization_or_destruction (tree decl, tree init, bool initp,
- bool omp_target)
+one_static_initialization_or_destruction (tree decl, tree init, bool initp)
{
tree guard_if_stmt = NULL_TREE;
tree guard;
@@ -4389,8 +4388,7 @@ do_static_initialization_or_destruction (tree vars, bool initp, bool omp_target)
if (omp_target)
init = copy_node (init);
/* Do one initialization or destruction. */
- one_static_initialization_or_destruction (decl, init, initp,
- omp_target);
+ one_static_initialization_or_destruction (decl, init, initp);
}
/* Finish up the priority if-stmt body. */
@@ -4854,7 +4852,7 @@ handle_tls_init (void)
{
tree var = TREE_VALUE (vars);
tree init = TREE_PURPOSE (vars);
- one_static_initialization_or_destruction (var, init, true, false);
+ one_static_initialization_or_destruction (var, init, true);
/* Output init aliases even with -fno-extern-tls-init. */
if (TARGET_SUPPORTS_ALIASES && TREE_PUBLIC (var))
--
2.25.1
^ permalink raw reply [flat|nested] 3+ messages in thread