https://gcc.gnu.org/g:e0246616020e95e74afa9d504c8848e6e905fab4
commit e0246616020e95e74afa9d504c8848e6e905fab4 Author: Tobias Burnus <tbur...@baylibre.com> Date: Mon Feb 17 22:52:34 2025 +0100 OpenMP/Fortran: extend 'adjust_args' clause, fixes for it and declare variant [PR115271] On the extension side, it implements OpenMP 6.0's numeric values/ranges for the adjust_args arguments, including 'omp_num_args'. And it adds parser support for need_device_addr. It also implements the post-OpenMP-6.0 clarification of OpenMP spec Issue #4443 regarding type(c_ptr) with dimension being invalid for need_device_ptr. To be done: Adding full support for need_device_addr (optional, array descriptor, ...). On the invalid side, it removed a bogus c_ptr check that went through all adjust_args without checking for need_device_ptr and the current scope. And it finally also processes 'declare variant' in an INTERFACE block, which is part of PR115271, but it does not handle .mod file yet - the main issue tracked in that PR. PR fortran/115271 gcc/fortran/ChangeLog: * gfortran.h (gfc_omp_namelist): Change need_device_ptr to adj_args union and add more flags. * openmp.cc (gfc_match_omp_declare_variant, gfc_resolve_omp_declare): For adjust_args, handle need_device_addr and numeric values/ranges besides dummy argument names. (resolve_omp_dispatch): Remove bogus a adjust_args check. * trans-decl.cc (gfc_handle_omp_declare_variant): New. (gfc_generate_module_vars, gfc_generate_function_code): Call it. * trans-openmp.cc (gfc_trans_omp_declare_variant): Handle numeric values/ranges besides dummy argument names. gcc/testsuite/ChangeLog: * gfortran.dg/gomp/adjust-args-1.f90: Update dg-.* expectations. * gfortran.dg/gomp/adjust-args-2.f90: Likewise. * gfortran.dg/gomp/adjust-args-2a.f90: Likewise. * gfortran.dg/gomp/adjust-args-3.f90: Likewise. * gfortran.dg/gomp/adjust-args-4.f90: Remove array from c_ptr. * gfortran.dg/gomp/adjust-args-5.f90: Likewise. * gfortran.dg/gomp/adjust-args-11.f90: Likewise. Add check that INTERFACE is now handled in subroutines and in modules. * gfortran.dg/gomp/adjust-args-13.f90: New test. * gfortran.dg/gomp/adjust-args-14.f90: New test. * gfortran.dg/gomp/adjust-args-15.f90: New test. * gfortran.dg/gomp/declare-variant-21.f90: New test. (cherry picked from commit 8268c8256dd430174e89142be9ee77b036d6310d) Diff: --- gcc/fortran/ChangeLog.omp | 17 ++ gcc/fortran/gfortran.h | 10 +- gcc/fortran/openmp.cc | 243 +++++++++++++++++---- gcc/fortran/trans-decl.cc | 23 ++ gcc/fortran/trans-openmp.cc | 212 ++++++++++++++---- gcc/testsuite/ChangeLog.omp | 19 ++ gcc/testsuite/gfortran.dg/gomp/adjust-args-1.f90 | 8 +- gcc/testsuite/gfortran.dg/gomp/adjust-args-11.f90 | 77 ++++++- gcc/testsuite/gfortran.dg/gomp/adjust-args-13.f90 | 18 ++ gcc/testsuite/gfortran.dg/gomp/adjust-args-14.f90 | 85 +++++++ gcc/testsuite/gfortran.dg/gomp/adjust-args-15.f90 | 35 +++ gcc/testsuite/gfortran.dg/gomp/adjust-args-2.f90 | 3 +- gcc/testsuite/gfortran.dg/gomp/adjust-args-2a.f90 | 8 +- gcc/testsuite/gfortran.dg/gomp/adjust-args-3.f90 | 4 +- gcc/testsuite/gfortran.dg/gomp/adjust-args-4.f90 | 8 +- gcc/testsuite/gfortran.dg/gomp/adjust-args-5.f90 | 8 +- .../gfortran.dg/gomp/declare-variant-21.f90 | 20 ++ 17 files changed, 692 insertions(+), 106 deletions(-) diff --git a/gcc/fortran/ChangeLog.omp b/gcc/fortran/ChangeLog.omp index 56c8ee2b2fc0..f0a2a48f7cf7 100644 --- a/gcc/fortran/ChangeLog.omp +++ b/gcc/fortran/ChangeLog.omp @@ -1,3 +1,20 @@ +2025-02-18 Tobias Burnus <tbur...@baylibre.com> + + Backported from master: + 2025-02-17 Tobias Burnus <tbur...@baylibre.com> + + PR fortran/115271 + * gfortran.h (gfc_omp_namelist): Change need_device_ptr to adj_args + union and add more flags. + * openmp.cc (gfc_match_omp_declare_variant, + gfc_resolve_omp_declare): For adjust_args, handle need_device_addr + and numeric values/ranges besides dummy argument names. + (resolve_omp_dispatch): Remove bogus a adjust_args check. + * trans-decl.cc (gfc_handle_omp_declare_variant): New. + (gfc_generate_module_vars, gfc_generate_function_code): Call it. + * trans-openmp.cc (gfc_trans_omp_declare_variant): Handle numeric + values/ranges besides dummy argument names. + 2025-02-12 Tobias Burnus <tbur...@baylibre.com> Backported from master: diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h index 5ef66173e696..40711fcec52f 100644 --- a/gcc/fortran/gfortran.h +++ b/gcc/fortran/gfortran.h @@ -1397,7 +1397,15 @@ typedef struct gfc_omp_namelist bool target; bool targetsync; } init; - bool need_device_ptr; + struct + { + bool need_ptr:1; + bool need_addr:1; + bool range_start:1; + bool omp_num_args_plus:1; + bool omp_num_args_minus:1; + bool error_p:1; + } adj_args; } u; union { diff --git a/gcc/fortran/openmp.cc b/gcc/fortran/openmp.cc index 71f148e45c2f..16b255ec1062 100644 --- a/gcc/fortran/openmp.cc +++ b/gcc/fortran/openmp.cc @@ -6988,21 +6988,21 @@ gfc_match_omp_declare_variant (void) enum clause { - match, - adjust_args, - append_args + clause_match, + clause_adjust_args, + clause_append_args } ccode; if (gfc_match ("match") == MATCH_YES) - ccode = match; + ccode = clause_match; else if (gfc_match ("adjust_args") == MATCH_YES) { - ccode = adjust_args; + ccode = clause_adjust_args; adjust_args_loc = gfc_current_locus; } else if (gfc_match ("append_args") == MATCH_YES) { - ccode = append_args; + ccode = clause_append_args; append_args_loc = gfc_current_locus; } else @@ -7011,13 +7011,13 @@ gfc_match_omp_declare_variant (void) break; } - if (gfc_match (" (") != MATCH_YES) + if (gfc_match (" ( ") != MATCH_YES) { gfc_error ("expected %<(%> at %C"); return MATCH_ERROR; } - if (ccode == match) + if (ccode == clause_match) { if (has_match) { @@ -7036,32 +7036,156 @@ gfc_match_omp_declare_variant (void) return MATCH_ERROR; } } - else if (ccode == adjust_args) + else if (ccode == clause_adjust_args) { has_adjust_args = true; - bool need_device_ptr_p; - if (gfc_match (" nothing") == MATCH_YES) - need_device_ptr_p = false; - else if (gfc_match (" need_device_ptr") == MATCH_YES) + bool need_device_ptr_p = false; + bool need_device_addr_p = false; + if (gfc_match ("nothing ") == MATCH_YES) + ; + else if (gfc_match ("need_device_ptr ") == MATCH_YES) need_device_ptr_p = true; + else if (gfc_match ("need_device_addr ") == MATCH_YES) + need_device_addr_p = true; else { - gfc_error ("expected %<nothing%> or %<need_device_ptr%> at %C"); + gfc_error ("expected %<nothing%>, %<need_device_ptr%> or " + "%<need_device_addr%> at %C"); return MATCH_ERROR; } - gfc_omp_namelist **head = NULL; - if (gfc_match_omp_variable_list (" :", &odv->adjust_args_list, false, - NULL, &head) - != MATCH_YES) + if (gfc_match (": ") != MATCH_YES) { - gfc_error ("expected argument list at %C"); + gfc_error ("expected %<:%> at %C"); return MATCH_ERROR; } - if (need_device_ptr_p) - for (gfc_omp_namelist *n = *head; n != NULL; n = n->next) - n->u.need_device_ptr = true; + gfc_omp_namelist *tail = NULL; + bool need_range = false, have_range = false; + while (true) + { + gfc_omp_namelist *p = gfc_get_omp_namelist (); + p->where = gfc_current_locus; + p->u.adj_args.need_ptr = need_device_ptr_p; + p->u.adj_args.need_addr = need_device_addr_p; + if (tail) + { + tail->next = p; + tail = tail->next; + } + else + { + gfc_omp_namelist **q = &odv->adjust_args_list; + if (*q) + { + for (; (*q)->next; q = &(*q)->next) + ; + (*q)->next = p; + } + else + *q = p; + tail = p; + } + if (gfc_match (": ") == MATCH_YES) + { + if (have_range) + { + gfc_error ("unexpected %<:%> at %C"); + return MATCH_ERROR; + } + p->u.adj_args.range_start = have_range = true; + need_range = false; + continue; + } + if (have_range && gfc_match (", ") == MATCH_YES) + { + have_range = false; + continue; + } + if (have_range && gfc_match (") ") == MATCH_YES) + break; + locus saved_loc = gfc_current_locus; + + /* Without ranges, only arg names or integer literals permitted; + handle literals here as gfc_match_expr simplifies the expr. */ + if (gfc_match_literal_constant (&p->expr, true) == MATCH_YES) + { + gfc_gobble_whitespace (); + char c = gfc_peek_ascii_char (); + if (c != ')' && c != ',' && c != ':') + { + gfc_free_expr (p->expr); + p->expr = NULL; + gfc_current_locus = saved_loc; + } + } + if (!p->expr && gfc_match ("omp_num_args") == MATCH_YES) + { + if (!have_range) + p->u.adj_args.range_start = need_range = true; + else + need_range = false; + + locus saved_loc2 = gfc_current_locus; + gfc_gobble_whitespace (); + char c = gfc_peek_ascii_char (); + if (c == '+' || c == '-') + { + if (gfc_match ("+ %e", &p->expr) == MATCH_YES) + p->u.adj_args.omp_num_args_plus = true; + else if (gfc_match ("- %e", &p->expr) == MATCH_YES) + p->u.adj_args.omp_num_args_minus = true; + else if (!gfc_error_check ()) + { + gfc_error ("expected constant integer expression " + "at %C"); + p->u.adj_args.error_p = true; + return MATCH_ERROR; + } + p->where = saved_loc; + } + else + { + p->where = saved_loc; + p->u.adj_args.omp_num_args_plus = true; + } + } + else if (!p->expr) + { + match m = gfc_match_expr (&p->expr); + if (m != MATCH_YES) + { + gfc_error ("expected dummy parameter name, " + "%<omp_num_args%> or constant positive integer" + " at %C"); + p->u.adj_args.error_p = true; + return MATCH_ERROR; + } + if (p->expr->expr_type == EXPR_CONSTANT && !have_range) + need_range = true; /* Constant expr but not literal. */ + p->where = p->expr->where; + } + else + p->where = p->expr->where; + gfc_gobble_whitespace (); + match m = gfc_match (": "); + if (need_range && m != MATCH_YES) + { + gfc_error ("expected %<:%> at %C"); + return MATCH_ERROR; + } + if (m == MATCH_YES) + { + p->u.adj_args.range_start = have_range = true; + need_range = false; + continue; + } + need_range = have_range = false; + if (gfc_match (", ") == MATCH_YES) + continue; + if (gfc_match (") ") == MATCH_YES) + break; + } } - else if (ccode == append_args) + else if (ccode == clause_append_args) { if (has_append_args) { @@ -13115,18 +13239,6 @@ resolve_omp_dispatch (gfc_code *code) gfc_error ("%<OMP DISPATCH%> directive at %L cannot be followed by a " "procedure pointer", &code->loc); - - gfc_omp_declare_variant *odv = gfc_current_ns->omp_declare_variant; - if (odv != NULL) - for (gfc_omp_namelist *n = odv->adjust_args_list; n != NULL; n = n->next) - if (n->sym->ts.type != BT_DERIVED || !n->sym->ts.u.derived->ts.is_iso_c - || (n->sym->ts.u.derived->intmod_sym_id != ISOCBINDING_PTR)) - { - gfc_error ( - "argument list item %qs in %<need_device_ptr%> at %L must be of " - "TYPE(C_PTR)", - n->sym->name, &n->where); - } } /* Resolve OpenMP directive clauses and check various requirements @@ -13275,18 +13387,59 @@ gfc_resolve_omp_declare (gfc_namespace *ns) } gfc_omp_declare_variant *odv; + gfc_omp_namelist *range_begin = NULL; for (odv = ns->omp_declare_variant; odv; odv = odv->next) for (gfc_omp_namelist *n = odv->adjust_args_list; n != NULL; n = n->next) - if (n->u.need_device_ptr - && (!gfc_resolve_expr (n->expr) || n->sym->ts.type != BT_DERIVED - || !n->sym->ts.u.derived->ts.is_iso_c - || (n->sym->ts.u.derived->intmod_sym_id != ISOCBINDING_PTR))) - { - gfc_error ( - "argument list item %qs in %<need_device_ptr%> at %L must be of " - "TYPE(C_PTR)", - n->sym->name, &n->where); - } + { + if ((n->expr == NULL + && (range_begin + || n->u.adj_args.range_start + || n->u.adj_args.omp_num_args_plus + || n->u.adj_args.omp_num_args_minus)) + || n->u.adj_args.error_p) + { + } + else if (range_begin + || n->u.adj_args.range_start + || n->u.adj_args.omp_num_args_plus + || n->u.adj_args.omp_num_args_minus) + { + if (!n->expr + || !gfc_resolve_expr (n->expr) + || n->expr->expr_type != EXPR_CONSTANT + || n->expr->ts.type != BT_INTEGER + || n->expr->rank != 0 + || mpz_sgn (n->expr->value.integer) < 0 + || ((n->u.adj_args.omp_num_args_plus + || n->u.adj_args.omp_num_args_minus) + && mpz_sgn (n->expr->value.integer) == 0)) + { + if (n->u.adj_args.omp_num_args_plus + || n->u.adj_args.omp_num_args_minus) + gfc_error ("Expected constant non-negative scalar integer " + "offset expression at %L", &n->where); + else + gfc_error ("For range-based %<adjust_args%>, a constant " + "positive scalar integer expression is required " + "at %L", &n->where); + } + } + else if (n->expr + && n->expr->expr_type == EXPR_CONSTANT + && n->expr->ts.type == BT_INTEGER + && mpz_sgn (n->expr->value.integer) > 0) + { + } + else if (!n->expr + || !gfc_resolve_expr (n->expr) + || n->expr->expr_type != EXPR_VARIABLE) + gfc_error ("Expected dummy parameter name or a positive integer " + "at %L", &n->where); + else if (n->expr->expr_type == EXPR_VARIABLE) + n->sym = n->expr->symtree->n.sym; + + range_begin = n->u.adj_args.range_start ? n : NULL; + } } struct omp_udr_callback_data diff --git a/gcc/fortran/trans-decl.cc b/gcc/fortran/trans-decl.cc index 7e88ecc42fcb..7bd05ccc5c60 100644 --- a/gcc/fortran/trans-decl.cc +++ b/gcc/fortran/trans-decl.cc @@ -5991,6 +5991,19 @@ create_module_nml_decl (gfc_symbol *sym) } } +static void +gfc_handle_omp_declare_variant (gfc_symbol * sym) +{ + if (sym->attr.external + && sym->formal_ns + && sym->formal_ns->omp_declare_variant) + { + gfc_namespace *ns = gfc_current_ns; + gfc_current_ns = sym->ns; + gfc_get_symbol_decl (sym); + gfc_current_ns = ns; + } +} /* Generate all the required code for module variables. */ @@ -6015,6 +6028,11 @@ gfc_generate_module_vars (gfc_namespace * ns) if (flag_coarray == GFC_FCOARRAY_LIB && has_coarray_vars) generate_coarray_init (ns); + /* For OpenMP, ensure that declare variant in INTERFACE is is processed + especially as some late diagnostic is only done on tree level. */ + if (flag_openmp) + gfc_traverse_ns (ns, gfc_handle_omp_declare_variant); + cur_module = NULL; gfc_trans_use_stmts (ns); @@ -7870,6 +7888,11 @@ gfc_generate_function_code (gfc_namespace * ns) saved_parent_function_decls = dm_saved_parent_function_decls; } + /* For OpenMP, ensure that declare variant in INTERFACE is is processed + especially as some late diagnostic is only done on tree level. */ + if (flag_openmp) + gfc_traverse_ns (ns, gfc_handle_omp_declare_variant); + gfc_generate_contained_functions (ns); has_coarray_vars = false; diff --git a/gcc/fortran/trans-openmp.cc b/gcc/fortran/trans-openmp.cc index 09d237617b44..3292f0b2c7bf 100644 --- a/gcc/fortran/trans-openmp.cc +++ b/gcc/fortran/trans-openmp.cc @@ -11459,6 +11459,7 @@ gfc_trans_omp_declare_variant (gfc_namespace *ns) NULL_TREE, false)) { tree need_device_ptr_list = NULL_TREE; + tree need_device_addr_list = NULL_TREE; tree append_args_tree = NULL_TREE; tree id = get_identifier ("omp declare variant base"); tree variant = gfc_get_symbol_decl (variant_proc_sym); @@ -11472,13 +11473,14 @@ gfc_trans_omp_declare_variant (gfc_namespace *ns) if (ns->proc_name->ts.type == BT_CHARACTER) arg_idx_offset++; } + int nargs = 0; + for (gfc_formal_arglist *arg + = gfc_sym_get_dummy_args (ns->proc_name); + arg; arg = arg->next) + nargs++; if (odv->append_args_list) { - int append_arg_no = arg_idx_offset; - gfc_formal_arglist *arg; - for (arg = gfc_sym_get_dummy_args (ns->proc_name); arg; - arg = arg->next) - append_arg_no++; + int append_arg_no = arg_idx_offset + nargs; tree last_arg = NULL_TREE; for (gfc_omp_namelist *n = odv->append_args_list; n != NULL; n = n->next) @@ -11511,59 +11513,191 @@ gfc_trans_omp_declare_variant (gfc_namespace *ns) else append_args_tree = last_arg = t; } - /* Store as (purpose = arg number to be used for inserting - and value = list of interop items. */ + /* Store as 'purpose' = arg number to be used for inserting + and 'value' = list of interop items. */ append_args_tree = build_tree_list ( build_int_cst (integer_type_node, append_arg_no), append_args_tree); } - - if (odv->adjust_args_list) - need_device_ptr_list = make_node (TREE_LIST); vec<gfc_symbol *> adjust_args_list = vNULL; for (gfc_omp_namelist *arg_list = odv->adjust_args_list; arg_list != NULL; arg_list = arg_list->next) { - if (!arg_list->sym->attr.dummy) + int from, to; + if (arg_list->expr == NULL || arg_list->sym) + from = ((arg_list->u.adj_args.omp_num_args_minus + || arg_list->u.adj_args.omp_num_args_plus) + ? nargs : 1); + else { - gfc_error ( - "list item %qs at %L is not a dummy argument", - arg_list->sym->name, &arg_list->where); - continue; + if (arg_list->u.adj_args.omp_num_args_plus) + mpz_add_ui (arg_list->expr->value.integer, + arg_list->expr->value.integer, nargs); + if (arg_list->u.adj_args.omp_num_args_minus) + mpz_ui_sub (arg_list->expr->value.integer, nargs, + arg_list->expr->value.integer); + if (mpz_sgn (arg_list->expr->value.integer) <= 0) + { + gfc_warning (OPT_Wopenmp, + "Expected positive argument index " + "at %L", &arg_list->where); + from = 1; + } + else + from + = (mpz_fits_sint_p (arg_list->expr->value.integer) + ? mpz_get_si (arg_list->expr->value.integer) + : INT_MAX); + if (from > nargs) + gfc_warning (OPT_Wopenmp, + "Argument index at %L exceeds number " + "of arguments %d", &arg_list->where, + nargs); } - if (adjust_args_list.contains (arg_list->sym)) + locus loc = arg_list->where; + if (!arg_list->u.adj_args.range_start) + to = from; + else { - gfc_error ("%qs at %L is specified more than once", - arg_list->sym->name, &arg_list->where); - continue; + loc = arg_list->next->where; + if (arg_list->next->expr == NULL) + to = nargs; + else + { + if (arg_list->next->u.adj_args.omp_num_args_plus) + mpz_add_ui (arg_list->next->expr->value.integer, + arg_list->next->expr->value.integer, + nargs); + if (arg_list->next->u.adj_args.omp_num_args_minus) + mpz_ui_sub (arg_list->next->expr->value.integer, + nargs, + arg_list->next->expr->value.integer); + if (mpz_sgn (arg_list->next->expr->value.integer) + <= 0) + { + gfc_warning (OPT_Wopenmp, + "Expected positive argument " + "index at %L", &loc); + to = 0; + } + else + to = mpz_get_si ( + arg_list->next->expr->value.integer); + } + if (from > to && to != 0) + gfc_warning (OPT_Wopenmp, + "Upper argument index smaller than " + "lower one at %L", &loc); + if (to > nargs) + to = nargs; + arg_list = arg_list->next; } - adjust_args_list.safe_push (arg_list->sym); - if (arg_list->u.need_device_ptr) + if (from > nargs) + continue; + /* Change to zero based index. */ + from--; to--; + gfc_formal_arglist *arg = ns->proc_name->formal; + if (!arg_list->sym && to >= from) + for (int idx = 0; idx < from; idx++) + arg = arg->next; + for (int idx = from; idx <= to; idx++) { - int idx; - gfc_formal_arglist *arg; - for (arg = ns->proc_name->formal, idx = 0; - arg != NULL; arg = arg->next, idx++) - if (arg->sym == arg_list->sym) - break; - gcc_assert (arg != NULL); - // Store 0-based argument index, - // as in gimplify_call_expr - need_device_ptr_list = chainon ( - need_device_ptr_list, - build_tree_list ( - NULL_TREE, - build_int_cst ( - integer_type_node, - idx + arg_idx_offset))); + if (idx > from) + arg = arg->next; + if (arg_list->sym) + { + for (arg = ns->proc_name->formal, idx = 0; + arg != NULL; arg = arg->next, idx++) + if (arg->sym == arg_list->sym) + break; + if (!arg || !arg_list->sym->attr.dummy) + { + gfc_error ("List item %qs at %L, declared at " + "%L, is not a dummy argument", + arg_list->sym->name, &loc, + &arg_list->sym->declared_at); + continue; + } + } + if (arg_list->u.adj_args.need_ptr + && (arg->sym->ts.f90_type != BT_VOID + || !arg->sym->ts.u.derived->ts.is_iso_c + || (arg->sym->ts.u.derived->intmod_sym_id + != ISOCBINDING_PTR) + || arg->sym->attr.dimension)) + { + gfc_error ("Argument %qs at %L to list item in " + "%<need_device_ptr%> at %L must be a " + "scalar of TYPE(C_PTR)", + arg->sym->name, + &arg->sym->declared_at, &loc); + if (!arg->sym->attr.value) + inform (gfc_get_location (&loc), + "Consider using %<need_device_addr%> " + "instead"); + continue; + } + if (arg_list->u.adj_args.need_addr + && arg->sym->attr.value) + { + gfc_error ("Argument %qs at %L to list item in " + "%<need_device_addr%> at %L must not " + "have the VALUE attribute", + arg->sym->name, + &arg->sym->declared_at, &loc); + continue; + } + if (adjust_args_list.contains (arg->sym)) + { + gfc_error ("%qs at %L is specified more than " + "once", arg->sym->name, &loc); + continue; + } + adjust_args_list.safe_push (arg->sym); + + if (arg_list->u.adj_args.need_addr) + { + /* TODO: Has to to support OPTIONAL and array + descriptors; should check for CLASS, coarrays? + Reject "abc" and 123 as actual arguments (in + gimplify.cc or in the FE? Reject noncontiguous + actuals? Cf. also PR C++/118859. + Also check array-valued type(c_ptr). */ + static bool warned = false; + if (!warned) + sorry_at (gfc_get_location (&loc), + "%<need_device_addr%> not yet " + "supported"); + warned = true; + continue; + } + if (arg_list->u.adj_args.need_ptr + || arg_list->u.adj_args.need_addr) + { + // Store 0-based argument index, + // as in gimplify_call_expr + tree t + = build_tree_list ( + NULL_TREE, + build_int_cst (integer_type_node, + idx + arg_idx_offset)); + if (arg_list->u.adj_args.need_ptr) + need_device_ptr_list + = chainon (need_device_ptr_list, t); + else + need_device_addr_list + = chainon (need_device_addr_list, t); + } } } tree t = NULL_TREE; - if (need_device_ptr_list || append_args_tree) + if (need_device_ptr_list + || need_device_addr_list + || append_args_tree) { t = build_tree_list (need_device_ptr_list, - NULL_TREE /*need_device_addr */), + need_device_addr_list), TREE_CHAIN (t) = append_args_tree; DECL_ATTRIBUTES (variant) = tree_cons ( get_identifier ("omp declare variant variant args"), t, diff --git a/gcc/testsuite/ChangeLog.omp b/gcc/testsuite/ChangeLog.omp index 6a13a2810636..c9548f594caa 100644 --- a/gcc/testsuite/ChangeLog.omp +++ b/gcc/testsuite/ChangeLog.omp @@ -1,3 +1,22 @@ +2025-02-18 Tobias Burnus <tbur...@baylibre.com> + + Backported from master: + 2025-02-17 Tobias Burnus <tbur...@baylibre.com> + + PR fortran/115271 + * gfortran.dg/gomp/adjust-args-1.f90: Update dg-.* expectations. + * gfortran.dg/gomp/adjust-args-2.f90: Likewise. + * gfortran.dg/gomp/adjust-args-2a.f90: Likewise. + * gfortran.dg/gomp/adjust-args-3.f90: Likewise. + * gfortran.dg/gomp/adjust-args-4.f90: Remove array from c_ptr. + * gfortran.dg/gomp/adjust-args-5.f90: Likewise. + * gfortran.dg/gomp/adjust-args-11.f90: Likewise. Add check that + INTERFACE is now handled in subroutines and in modules. + * gfortran.dg/gomp/adjust-args-13.f90: New test. + * gfortran.dg/gomp/adjust-args-14.f90: New test. + * gfortran.dg/gomp/adjust-args-15.f90: New test. + * gfortran.dg/gomp/declare-variant-21.f90: New test. + 2025-02-12 Tobias Burnus <tbur...@baylibre.com> Backported from master: diff --git a/gcc/testsuite/gfortran.dg/gomp/adjust-args-1.f90 b/gcc/testsuite/gfortran.dg/gomp/adjust-args-1.f90 index c0c06e7f8fdf..39824c297019 100644 --- a/gcc/testsuite/gfortran.dg/gomp/adjust-args-1.f90 +++ b/gcc/testsuite/gfortran.dg/gomp/adjust-args-1.f90 @@ -21,7 +21,7 @@ module main integer function f3 (a) import c_ptr type(c_ptr), intent(inout) :: a - !$omp declare variant (f1) match (construct={dispatch}) adjust_args (other: a) ! { dg-error "expected 'nothing' or 'need_device_ptr' at .1." } + !$omp declare variant (f1) match (construct={dispatch}) adjust_args (other: a) ! { dg-error "expected 'nothing', 'need_device_ptr' or 'need_device_addr' at .1." } end function integer function f4 (a) import c_ptr @@ -30,15 +30,15 @@ module main end function integer function f5 (i) integer, intent(inout) :: i - !$omp declare variant (f1) match (construct={dispatch}) adjust_args () ! { dg-error "expected 'nothing' or 'need_device_ptr' at .1." } + !$omp declare variant (f1) match (construct={dispatch}) adjust_args () ! { dg-error "expected 'nothing', 'need_device_ptr' or 'need_device_addr' at .1." } end function integer function f6 (i) integer, intent(inout) :: i - !$omp declare variant (f1) match (construct={dispatch}) adjust_args (nothing) ! { dg-error "expected argument list at .1." } + !$omp declare variant (f1) match (construct={dispatch}) adjust_args (nothing) ! { dg-error "expected ':' at .1." } end function integer function f7 (i) integer, intent(inout) :: i - !$omp declare variant (f1) match (construct={dispatch}) adjust_args (nothing:) ! { dg-error "expected argument list at .1." } + !$omp declare variant (f1) match (construct={dispatch}) adjust_args (nothing:) ! { dg-error "expected dummy parameter name, 'omp_num_args' or constant positive integer at .1." } end function end interface diff --git a/gcc/testsuite/gfortran.dg/gomp/adjust-args-11.f90 b/gcc/testsuite/gfortran.dg/gomp/adjust-args-11.f90 index d2eb7c1d72cc..6586abc661c3 100644 --- a/gcc/testsuite/gfortran.dg/gomp/adjust-args-11.f90 +++ b/gcc/testsuite/gfortran.dg/gomp/adjust-args-11.f90 @@ -18,13 +18,13 @@ module main import c_ptr integer, intent(in) :: a type(c_ptr), intent(inout) :: b - type(c_ptr), intent(out) :: c(:) + type(c_ptr), intent(out) :: c end function integer function f0(a, b, c) import c_ptr integer, intent(in) :: a type(c_ptr), intent(inout) :: b - type(c_ptr), intent(out) :: c(:) + type(c_ptr), intent(out) :: c !$omp declare variant (f), match (construct={dispatch}) , & !$omp& adjust_args (nothing: a) ,adjust_args (need_device_ptr: b),adjust_args (need_device_ptr: c) end function @@ -43,3 +43,76 @@ subroutine test end subroutine end module + +module other + use iso_c_binding, only: c_ptr + implicit none + + interface + integer function g(a, b, c) + import c_ptr + integer, intent(in) :: a + type(c_ptr), intent(inout) :: b + type(c_ptr), intent(out) :: c(:) + end function + integer function g0(a, b, c) ! { dg-error "Argument 'c' at .1. to list item in 'need_device_ptr' at .2. must be a scalar of TYPE\\(C_PTR\\)" } + import c_ptr + integer, intent(in) :: a + type(c_ptr), intent(inout) :: b + type(c_ptr), intent(out) :: c(:) + !$omp declare variant (g), match (construct={dispatch}) , & + !$omp& adjust_args (nothing: a) ,adjust_args (need_device_ptr: b),adjust_args (need_device_ptr: c) ! { dg-error "Argument 'c' at .1. to list item in 'need_device_ptr' at .2. must be a scalar of TYPE\\(C_PTR\\)" } +! { dg-note "Consider using 'need_device_addr' instead" "" { target *-*-* } .-1 } + end function + end interface +end module + +subroutine foobar + use iso_c_binding, only: c_ptr + implicit none + + interface + integer function h(a, b, c) + import c_ptr + integer, intent(in) :: a + type(c_ptr), intent(inout) :: b + type(c_ptr), intent(out) :: c(:) + end function + integer function h0(a, b, c) ! { dg-error "Argument 'c' at .1. to list item in 'need_device_ptr' at .2. must be a scalar of TYPE\\(C_PTR\\)" } + import c_ptr + integer, intent(in) :: a + type(c_ptr), intent(inout) :: b + type(c_ptr), intent(out) :: c(:) + !$omp declare variant (h), match (construct={dispatch}) , & + !$omp& adjust_args (nothing: a) ,adjust_args (need_device_ptr: b),adjust_args (need_device_ptr: c) ! { dg-error "Argument 'c' at .1. to list item in 'need_device_ptr' at .2. must be a scalar of TYPE\\(C_PTR\\)" } +! { dg-note "Consider using 'need_device_addr' instead" "" { target *-*-* } .-1 } + end function + end interface +end + + +subroutine outer +contains +subroutine inner + use iso_c_binding, only: c_ptr + implicit none + + interface + integer function st(a, b, c) + import c_ptr + integer, intent(in) :: a + type(c_ptr), intent(inout) :: b + type(c_ptr), intent(out) :: c(:) + end function + integer function st0(a, b, c) ! { dg-error "Argument 'c' at .1. to list item in 'need_device_ptr' at .2. must be a scalar of TYPE\\(C_PTR\\)" } + import c_ptr + integer, intent(in) :: a + type(c_ptr), intent(inout) :: b + type(c_ptr), intent(out) :: c(:) + !$omp declare variant (st), match (construct={dispatch}) , & + !$omp& adjust_args (nothing: a) ,adjust_args (need_device_ptr: b),adjust_args (need_device_ptr: c) ! { dg-error "Argument 'c' at .1. to list item in 'need_device_ptr' at .2. must be a scalar of TYPE\\(C_PTR\\)" } +! { dg-note "Consider using 'need_device_addr' instead" "" { target *-*-* } .-1 } + end function + end interface +end subroutine inner +end subroutine outer diff --git a/gcc/testsuite/gfortran.dg/gomp/adjust-args-13.f90 b/gcc/testsuite/gfortran.dg/gomp/adjust-args-13.f90 new file mode 100644 index 000000000000..319a0076d1c9 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/adjust-args-13.f90 @@ -0,0 +1,18 @@ +! This failed with a bogus: +! 'must be of TYPE(C_PTR)' +module m + implicit none +contains + subroutine q() + end + subroutine one(x) + integer :: x + end + subroutine two(x) + !$omp declare variant(one) match(construct={dispatch}) adjust_args(nothing: x) + integer :: x + + !$omp dispatch + call q + end +end diff --git a/gcc/testsuite/gfortran.dg/gomp/adjust-args-14.f90 b/gcc/testsuite/gfortran.dg/gomp/adjust-args-14.f90 new file mode 100644 index 000000000000..313e4e65f9f2 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/adjust-args-14.f90 @@ -0,0 +1,85 @@ +module m + implicit none +contains + subroutine f(x,y,z) + integer:: x, y, z + value :: y + end subroutine + subroutine f0(x,y,z) + !$omp declare variant(f) adjust_args ( need_device_addr : : omp_num_args-1) & + !$omp& adjust_args ( need_device_ptr : z) & + !$omp& match ( construct = { dispatch } ) + integer:: x, y, z + value :: y + +! { dg-error "19: Argument 'y' at .1. to list item in 'need_device_addr' at .2. must not have the VALUE attribute" "" { target *-*-* } 8 } +! { dg-error "64: Argument 'y' at .1. to list item in 'need_device_addr' at .2. must not have the VALUE attribute" "" { target *-*-* } 9 } +! { dg-message "sorry, unimplemented: 'need_device_addr' not yet supported" "" { target *-*-* } 9 } + +! { dg-error "Argument 'z' at .1. to list item in 'need_device_ptr' at .2. must be a scalar of TYPE\\(C_PTR\\)" "" { target *-*-* } 8 } +! { dg-error "Argument 'z' at .1. to list item in 'need_device_ptr' at .2. must be a scalar of TYPE\\(C_PTR\\)" "" { target *-*-* } 10 } +! { dg-note "Consider using 'need_device_addr' instead" "" { target *-*-* } 10 } + end subroutine +end module m + +module m2 + use iso_c_binding, only: c_ptr + implicit none + interface + subroutine f(x,y,z) + import + type(c_ptr) :: x, y, z + end subroutine + subroutine f0(x,y,z) + import + type(c_ptr) :: x, y, z + !$omp declare variant(f) adjust_args ( need_device_ptr : : ) & + !$omp& adjust_args ( nothing : 2, 4) & + !$omp& match ( construct = { dispatch } ) + +! { dg-error "54: 'y' at .1. is specified more than once" "" { target *-*-* } 37 } +! { dg-warning "57: Argument index at .1. exceeds number of arguments 3 \\\[-Wopenmp\\\]" "" { target *-*-* } 37 } + end subroutine + end interface +end module m2 + +module m3 + use iso_c_binding, only: c_ptr + implicit none + interface + subroutine f(x,y,z) + import + type(c_ptr) :: x, y, z + end subroutine + subroutine f0(x,y,z) + import + type(c_ptr) :: x, y, z + !$omp declare variant(f) adjust_args ( need_device_addr : omp_num_args -4 :, 3 : 2) & + !$omp& match ( construct = { dispatch } ) +! { dg-warning "62: Expected positive argument index at .1. \\\[-Wopenmp\\\]" "" { target *-*-* } .-2 } +! { dg-warning "86: Upper argument index smaller than lower one at .1. \\\[-Wopenmp\\\]" "" { target *-*-* } .-3 } + end subroutine + end interface +end module m3 + +module m4 + use iso_c_binding, only: c_ptr + implicit none + interface + subroutine f(x,y,z) + import + type(c_ptr) :: x, y, z + end subroutine + subroutine f0(x,y,z) + import + type(c_ptr) :: x, y, z + !$omp declare variant(f) adjust_args ( need_device_addr : x, y, omp_num_args -2 : omp_num_args -1) & + !$omp& adjust_args ( need_device_addr : z) & + !$omp& adjust_args ( need_device_addr : omp_num_args : 3) & + !$omp& match ( construct = { dispatch } ) +! { dg-error "86: 'x' at .1. is specified more than once" "" { target *-*-* } .-4 } +! { dg-error "86: 'y' at .1. is specified more than once" "" { target *-*-* } .-5 } +! { dg-error "78: 'z' at .1. is specified more than once" "" { target *-*-* } .-4 } + end subroutine + end interface +end module m4 diff --git a/gcc/testsuite/gfortran.dg/gomp/adjust-args-15.f90 b/gcc/testsuite/gfortran.dg/gomp/adjust-args-15.f90 new file mode 100644 index 000000000000..d1001c183184 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/adjust-args-15.f90 @@ -0,0 +1,35 @@ +module m3 + use iso_c_binding, only: c_ptr + implicit none + interface + subroutine f(x,y,z) + import + type(c_ptr) :: x, y, z + end subroutine + subroutine f0(x,y,z) + import + type(c_ptr) :: x, y, z + !$omp declare variant(f) adjust_args ( need_device_addr : -1 : omp_num_args + 10 ) & ! { dg-error "64: For range-based 'adjust_args', a constant positive scalar integer expression is required" } + !$omp& adjust_args ( nothing : 1+1) & ! { dg-error "expected ':'" } + !$omp& match ( construct = { dispatch } ) + end subroutine + end interface +end module m3 + +module m4 + use iso_c_binding, only: c_ptr + implicit none + interface + subroutine f(x,y,z) + import + type(c_ptr) :: x, y, z + end subroutine + subroutine f0(x,y,z) + import + type(c_ptr) :: x, y, z + !$omp declare variant(f) adjust_args ( need_device_addr : 3.3 ) & ! { dg-error "Expected dummy parameter name or a positive integer" } + !$omp& adjust_args ( nothing : 1 : y ) & ! { dg-error "For range-based 'adjust_args', a constant positive scalar integer expression is required" } + !$omp& match ( construct = { dispatch } ) + end subroutine + end interface +end module m4 diff --git a/gcc/testsuite/gfortran.dg/gomp/adjust-args-2.f90 b/gcc/testsuite/gfortran.dg/gomp/adjust-args-2.f90 index c65a4839ca5d..35acf82a7fe9 100644 --- a/gcc/testsuite/gfortran.dg/gomp/adjust-args-2.f90 +++ b/gcc/testsuite/gfortran.dg/gomp/adjust-args-2.f90 @@ -12,7 +12,8 @@ contains subroutine f3 (i) integer, intent(inout) :: i - !$omp declare variant (f1) match (construct={dispatch}) adjust_args (nothing: z) ! { dg-error "Symbol 'z' at .1. has no IMPLICIT type" } + !$omp declare variant (f1) match (construct={dispatch}) adjust_args (nothing: z) ! { dg-error "Symbol 'z' at .1. has no IMPLICIT type" } +! { dg-error "Expected dummy parameter name or a positive integer at .1." "" { target *-*-* } .-1 } end subroutine end module diff --git a/gcc/testsuite/gfortran.dg/gomp/adjust-args-2a.f90 b/gcc/testsuite/gfortran.dg/gomp/adjust-args-2a.f90 index 9a32d2b7d92f..d4244ce14e62 100644 --- a/gcc/testsuite/gfortran.dg/gomp/adjust-args-2a.f90 +++ b/gcc/testsuite/gfortran.dg/gomp/adjust-args-2a.f90 @@ -15,13 +15,13 @@ module main end interface contains - subroutine f9 (i) + subroutine f9 (i) ! { dg-error "Argument 'i' at .1. to list item in 'need_device_ptr' at .2. must be a scalar of TYPE\\(C_PTR\\)" } integer, intent(inout) :: i - !$omp declare variant (f1) match (construct={dispatch}) adjust_args (need_device_ptr: i) ! { dg-error "argument list item 'i' in 'need_device_ptr' at .1. must be of TYPE.C_PTR." } + !$omp declare variant (f1) match (construct={dispatch}) adjust_args (need_device_ptr: i) ! { dg-error "Argument 'i' at .1. to list item in 'need_device_ptr' at .2. must be a scalar of TYPE\\(C_PTR\\)" } end subroutine - subroutine f13 (a) + subroutine f13 (a) ! { dg-error "Argument 'a' at .1. to list item in 'need_device_ptr' at .2. must be a scalar of TYPE\\(C_PTR\\)" } type(c_funptr), intent(inout) :: a - !$omp declare variant (h) match (construct={dispatch}) adjust_args (need_device_ptr: a) ! { dg-error "argument list item 'a' in 'need_device_ptr' at .1. must be of TYPE.C_PTR." } + !$omp declare variant (h) match (construct={dispatch}) adjust_args (need_device_ptr: a) ! { dg-error "Argument 'a' at .1. to list item in 'need_device_ptr' at .2. must be a scalar of TYPE\\(C_PTR\\)" } end subroutine subroutine test diff --git a/gcc/testsuite/gfortran.dg/gomp/adjust-args-3.f90 b/gcc/testsuite/gfortran.dg/gomp/adjust-args-3.f90 index 9033221cc5c2..4ad64c22d6fa 100644 --- a/gcc/testsuite/gfortran.dg/gomp/adjust-args-3.f90 +++ b/gcc/testsuite/gfortran.dg/gomp/adjust-args-3.f90 @@ -4,7 +4,7 @@ module main use iso_c_binding, only: c_ptr implicit none - type(c_ptr) :: b + type(c_ptr) :: b ! { dg-error "List item 'b' at .1., declared at .2., is not a dummy argument" } contains subroutine base2 (a) @@ -17,7 +17,7 @@ contains end subroutine subroutine base4 (a) type(c_ptr), intent(inout) :: a - !$omp declare variant (variant2) match (construct={dispatch}) adjust_args (need_device_ptr: b) ! { dg-error "list item 'b' at .1. is not a dummy argument" } + !$omp declare variant (variant2) match (construct={dispatch}) adjust_args (need_device_ptr: b) ! { dg-error "List item 'b' at .1., declared at .2., is not a dummy argument" } end subroutine subroutine variant2 (a) diff --git a/gcc/testsuite/gfortran.dg/gomp/adjust-args-4.f90 b/gcc/testsuite/gfortran.dg/gomp/adjust-args-4.f90 index 2f44c0026dbf..7452e12ff0cd 100644 --- a/gcc/testsuite/gfortran.dg/gomp/adjust-args-4.f90 +++ b/gcc/testsuite/gfortran.dg/gomp/adjust-args-4.f90 @@ -15,13 +15,13 @@ module main import c_ptr integer, intent(in) :: a type(c_ptr), intent(inout) :: b - type(c_ptr), intent(out) :: c(:) + type(c_ptr), intent(out) :: c end function integer function f0(a, b, c) import c_ptr integer, intent(in) :: a type(c_ptr), intent(inout) :: b - type(c_ptr), intent(out) :: c(:) + type(c_ptr), intent(out) :: c !$omp declare variant (f) match (construct={dispatch}) & !$omp& adjust_args (nothing: a) adjust_args (need_device_ptr: b, c) end function @@ -29,7 +29,7 @@ module main import c_ptr integer, intent(in) :: a type(c_ptr), intent(inout) :: b - type(c_ptr), intent(out) :: c(:) + type(c_ptr), intent(out) :: c !$omp declare variant (f) match (construct={dispatch}) & !$omp& adjust_args (nothing: a) adjust_args (need_device_ptr: b) adjust_args (need_device_ptr: c) end function @@ -54,5 +54,5 @@ end subroutine end module ! { dg-final { scan-tree-dump-times "__builtin_omp_get_default_device \\(\\);" 2 "gimple" } } -! { dg-final { scan-tree-dump-times "D\.\[0-9]+ = __builtin_omp_get_mapped_ptr \\(parm\.\[0-9]+, D\.\[0-9]+\\);" 2 "gimple" } } +! { dg-final { scan-tree-dump-times "D\.\[0-9]+ = __builtin_omp_get_mapped_ptr \\(c, D\.\[0-9]+\\);" 2 "gimple" } } ! { dg-final { scan-tree-dump-times "D\.\[0-9]+ = __builtin_omp_get_mapped_ptr \\(b\.\[0-9]+, D\.\[0-9]+\\);" 2 "gimple" } } diff --git a/gcc/testsuite/gfortran.dg/gomp/adjust-args-5.f90 b/gcc/testsuite/gfortran.dg/gomp/adjust-args-5.f90 index 2f44c0026dbf..7452e12ff0cd 100644 --- a/gcc/testsuite/gfortran.dg/gomp/adjust-args-5.f90 +++ b/gcc/testsuite/gfortran.dg/gomp/adjust-args-5.f90 @@ -15,13 +15,13 @@ module main import c_ptr integer, intent(in) :: a type(c_ptr), intent(inout) :: b - type(c_ptr), intent(out) :: c(:) + type(c_ptr), intent(out) :: c end function integer function f0(a, b, c) import c_ptr integer, intent(in) :: a type(c_ptr), intent(inout) :: b - type(c_ptr), intent(out) :: c(:) + type(c_ptr), intent(out) :: c !$omp declare variant (f) match (construct={dispatch}) & !$omp& adjust_args (nothing: a) adjust_args (need_device_ptr: b, c) end function @@ -29,7 +29,7 @@ module main import c_ptr integer, intent(in) :: a type(c_ptr), intent(inout) :: b - type(c_ptr), intent(out) :: c(:) + type(c_ptr), intent(out) :: c !$omp declare variant (f) match (construct={dispatch}) & !$omp& adjust_args (nothing: a) adjust_args (need_device_ptr: b) adjust_args (need_device_ptr: c) end function @@ -54,5 +54,5 @@ end subroutine end module ! { dg-final { scan-tree-dump-times "__builtin_omp_get_default_device \\(\\);" 2 "gimple" } } -! { dg-final { scan-tree-dump-times "D\.\[0-9]+ = __builtin_omp_get_mapped_ptr \\(parm\.\[0-9]+, D\.\[0-9]+\\);" 2 "gimple" } } +! { dg-final { scan-tree-dump-times "D\.\[0-9]+ = __builtin_omp_get_mapped_ptr \\(c, D\.\[0-9]+\\);" 2 "gimple" } } ! { dg-final { scan-tree-dump-times "D\.\[0-9]+ = __builtin_omp_get_mapped_ptr \\(b\.\[0-9]+, D\.\[0-9]+\\);" 2 "gimple" } } diff --git a/gcc/testsuite/gfortran.dg/gomp/declare-variant-21.f90 b/gcc/testsuite/gfortran.dg/gomp/declare-variant-21.f90 new file mode 100644 index 000000000000..da53c1f1fa36 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/declare-variant-21.f90 @@ -0,0 +1,20 @@ +! { dg-additional-options "-fdump-tree-gimple" } +! { dg-final { scan-tree-dump-not "g \\(\\)" "gimple" } } +! { dg-final { scan-tree-dump "i = f \\(\\);" "gimple" } } + +! PR fortran/115271 + +module m +interface + integer function f () + end + integer function g () + !$omp declare variant(f) match(construct={dispatch}) + end +end interface +end + +use m +!$omp dispatch + i = g() +end