diff options
author | Thomas Schwinge <tschwinge@baylibre.com> | 2024-03-11 22:51:28 +0100 |
---|---|---|
committer | Thomas Schwinge <tschwinge@baylibre.com> | 2024-03-11 22:51:28 +0100 |
commit | a95e21151a6366e7344d0f1983f99e318c5a7097 (patch) | |
tree | 11d987406d9ce8399ec1736477d971ef09344df2 /gcc/fortran | |
parent | 02d394b2736afa9a24ab3e1b8ad56fd6ac37e0f4 (diff) | |
parent | af4bb221153359f5948da917d5ef2df738bb1e61 (diff) | |
download | gcc-a95e21151a6366e7344d0f1983f99e318c5a7097.zip gcc-a95e21151a6366e7344d0f1983f99e318c5a7097.tar.gz gcc-a95e21151a6366e7344d0f1983f99e318c5a7097.tar.bz2 |
Merge commit 'af4bb221153359f5948da917d5ef2df738bb1e61' into HEAD
Diffstat (limited to 'gcc/fortran')
-rw-r--r-- | gcc/fortran/ChangeLog | 108 | ||||
-rw-r--r-- | gcc/fortran/decl.cc | 4 | ||||
-rw-r--r-- | gcc/fortran/error.cc | 14 | ||||
-rw-r--r-- | gcc/fortran/frontend-passes.cc | 2 | ||||
-rw-r--r-- | gcc/fortran/gfortran.h | 1 | ||||
-rw-r--r-- | gcc/fortran/intrinsic.texi | 27 | ||||
-rw-r--r-- | gcc/fortran/invoke.texi | 6 | ||||
-rw-r--r-- | gcc/fortran/match.cc | 9 | ||||
-rw-r--r-- | gcc/fortran/openmp.cc | 64 | ||||
-rw-r--r-- | gcc/fortran/options.cc | 9 | ||||
-rw-r--r-- | gcc/fortran/parse.cc | 30 | ||||
-rw-r--r-- | gcc/fortran/scanner.cc | 4 | ||||
-rw-r--r-- | gcc/fortran/trans-array.cc | 44 | ||||
-rw-r--r-- | gcc/fortran/trans-decl.cc | 126 | ||||
-rw-r--r-- | gcc/fortran/trans-expr.cc | 40 | ||||
-rw-r--r-- | gcc/fortran/trans-openmp.cc | 77 |
16 files changed, 476 insertions, 89 deletions
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 657dc91..e753eb9 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,111 @@ +2023-10-17 Harald Anlauf <anlauf@gmx.de> + + PR fortran/111837 + * frontend-passes.cc (traverse_io_block): Dependency check of loop + nest shall be triangular, not banded. + +2023-10-17 Tobias Burnus <tobias@codesourcery.com> + + * intrinsic.texi (signal): Mention that the argument + passed to the signal handler procedure is passed by reference. + Extend example. + +2023-10-15 Tobias Burnus <tobias@codesourcery.com> + + * scanner.cc (skip_free_comments, skip_fixed_comments): Remove + leftover 'OpenACC' from comments about OpenMP's conditional + compilation sentinel. + +2023-10-14 Tobias Burnus <tobias@codesourcery.com> + + * gfortran.h (ext_attr_t): Add omp_allocate flag. + * match.cc (gfc_free_omp_namelist): Void deleting same + u2.allocator multiple times now that a sequence can use + the same one. + * openmp.cc (gfc_match_omp_clauses, gfc_match_omp_allocate): Use + same allocator expr multiple times. + (is_predefined_allocator): Make static. + (gfc_resolve_omp_allocate): Update/extend restriction checks; + remove sorry message. + (resolve_omp_clauses): Reject corarrays in allocate/allocators + directive. + * parse.cc (check_omp_allocate_stmt): Permit procedure pointers + here (rejected later) for less misleading diagnostic. + * trans-array.cc (gfc_trans_auto_array_allocation): Propagate + size for GOMP_alloc and location to which it should be added to. + * trans-decl.cc (gfc_trans_deferred_vars): Handle 'omp allocate' + for stack variables; sorry for static variables/common blocks. + * trans-openmp.cc (gfc_trans_omp_clauses): Evaluate 'allocate' + clause's allocator only once; fix adding expressions to the + block. + (gfc_trans_omp_single): Pass a block to gfc_trans_omp_clauses. + +2023-10-13 Harald Anlauf <anlauf@gmx.de> + + PR fortran/104351 + * decl.cc (get_proc_name): Extend name conflict detection between + internal procedure and previous declaration also to derived type. + +2023-10-13 Harald Anlauf <anlauf@gmx.de> + + PR fortran/110957 + * invoke.texi: Update documentation to reflect '-ffpe-trap=none'. + * options.cc (gfc_handle_fpe_option): Fix mixup up of error messages + for options -ffpe-trap and -ffpe-summary. Accept '-ffpe-trap=none' + to clear FPU traps previously set on command line. + +2023-10-13 Richard Biener <rguenther@suse.de> + + PR tree-optimization/111779 + * trans-expr.cc (gfc_trans_assignment_1): Initialize + lhs_caf_attr and rhs_caf_attr codimension flag to avoid + false positive -Wuninitialized. + +2023-10-12 Paul Thomas <pault@gcc.gnu.org> + + PR fortran/67740 + * trans-expr.cc (gfc_trans_pointer_assignment): Set the hidden + string length component for pointer assignment to character + pointer components. + +2023-10-08 Tobias Burnus <tobias@codesourcery.com> + + * parse.cc (parse_omp_structured_block): Make the user code end + up inside of BLOCK construct for strictly structured blocks; + fix fallout for 'section' and 'teams'. + * openmp.cc (resolve_omp_target): Fix changed BLOCK handling + for teams in target checking. + +2023-10-04 Paul Thomas <pault@gcc.gnu.org> + + PR fortran/37336 + PR fortran/111674 + * trans-expr.cc (gfc_trans_scalar_assign): Finalize components + on deallocation if derived type is not finalizable. + +2023-10-03 David Malcolm <dmalcolm@redhat.com> + + * error.cc (gfc_format_decoder): Update for "m_" prefixes to + text_info fields. + +2023-10-02 David Malcolm <dmalcolm@redhat.com> + + * error.cc (gfc_diagnostics_init): Update for change to start_span. + +2023-10-02 David Malcolm <dmalcolm@redhat.com> + + * error.cc (gfc_diagnostic_starter): Update for reorganization of + source-printing fields of diagnostic_context. + (gfc_diagnostics_init): Likewise. + (gfc_diagnostics_finish): Likewise. + +2023-09-29 Andre Vehreschild <vehre@gcc.gnu.org> + + PR fortran/37336 + * trans-array.cc (structure_alloc_comps): Deref coarray. + (gfc_trans_deferred_array): Add freeing of components after + check for allocated coarray. + 2023-09-24 Paul Thomas <pault@gcc.gnu.org> PR fortran/68155 diff --git a/gcc/fortran/decl.cc b/gcc/fortran/decl.cc index 4a3c5b8..bdd3be3 100644 --- a/gcc/fortran/decl.cc +++ b/gcc/fortran/decl.cc @@ -1404,7 +1404,9 @@ get_proc_name (const char *name, gfc_symbol **result, bool module_fcn_entry) /* Trap declarations of attributes in encompassing scope. The signature for this is that ts.kind is nonzero for no-CLASS entity. For a CLASS entity, ts.kind is zero. */ - if ((sym->ts.kind != 0 || sym->ts.type == BT_CLASS) + if ((sym->ts.kind != 0 + || sym->ts.type == BT_CLASS + || sym->ts.type == BT_DERIVED) && !sym->attr.implicit_type && sym->attr.proc == 0 && gfc_current_ns->parent != NULL diff --git a/gcc/fortran/error.cc b/gcc/fortran/error.cc index 6cae672..1b34619 100644 --- a/gcc/fortran/error.cc +++ b/gcc/fortran/error.cc @@ -1074,7 +1074,7 @@ gfc_format_decoder (pretty_printer *pp, text_info *text, const char *spec, if (*spec == 'C') loc = &gfc_current_locus; else - loc = va_arg (*text->args_ptr, locus *); + loc = va_arg (*text->m_args_ptr, locus *); gcc_assert (loc->nextc - loc->lb->line >= 0); unsigned int offset = loc->nextc - loc->lb->line; if (*spec == 'C' && *loc->nextc != '\0') @@ -1222,7 +1222,7 @@ gfc_diagnostic_starter (diagnostic_context *context, ? gfc_diagnostic_build_locus_prefix (context, s1) : gfc_diagnostic_build_locus_prefix (context, s1, s2); - if (!context->show_caret + if (!context->m_source_printing.enabled || diagnostic_location (diagnostic, 0) <= BUILTINS_LOCATION || diagnostic_location (diagnostic, 0) == context->last_location) { @@ -1637,11 +1637,11 @@ void gfc_diagnostics_init (void) { diagnostic_starter (global_dc) = gfc_diagnostic_starter; - global_dc->start_span = gfc_diagnostic_start_span; + global_dc->m_text_callbacks.start_span = gfc_diagnostic_start_span; diagnostic_finalizer (global_dc) = gfc_diagnostic_finalizer; diagnostic_format_decoder (global_dc) = gfc_format_decoder; - global_dc->caret_chars[0] = '1'; - global_dc->caret_chars[1] = '2'; + global_dc->m_source_printing.caret_chars[0] = '1'; + global_dc->m_source_printing.caret_chars[1] = '2'; pp_warning_buffer = new (XNEW (output_buffer)) output_buffer (); pp_warning_buffer->flush_p = false; /* pp_error_buffer is statically allocated. This simplifies memory @@ -1658,6 +1658,6 @@ gfc_diagnostics_finish (void) defaults. */ diagnostic_starter (global_dc) = gfc_diagnostic_starter; diagnostic_finalizer (global_dc) = gfc_diagnostic_finalizer; - global_dc->caret_chars[0] = '^'; - global_dc->caret_chars[1] = '^'; + global_dc->m_source_printing.caret_chars[0] = '^'; + global_dc->m_source_printing.caret_chars[1] = '^'; } diff --git a/gcc/fortran/frontend-passes.cc b/gcc/fortran/frontend-passes.cc index 136a292..536884b 100644 --- a/gcc/fortran/frontend-passes.cc +++ b/gcc/fortran/frontend-passes.cc @@ -1326,7 +1326,7 @@ traverse_io_block (gfc_code *code, bool *has_reached, gfc_code *prev) if (iters[i]) { gfc_expr *var = iters[i]->var; - for (int j = i - 1; j < i; j++) + for (int j = 0; j < i; j++) { if (iters[j] && (var_in_expr (var, iters[j]->start) diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h index 6caf776..88f33b0 100644 --- a/gcc/fortran/gfortran.h +++ b/gcc/fortran/gfortran.h @@ -1000,6 +1000,7 @@ typedef struct unsigned omp_declare_target:1; unsigned omp_declare_target_link:1; ENUM_BITFIELD (gfc_omp_device_type) omp_device_type:2; + unsigned omp_allocate:1; /* Mentioned in OACC DECLARE. */ unsigned oacc_declare_create:1; diff --git a/gcc/fortran/intrinsic.texi b/gcc/fortran/intrinsic.texi index 6c7ad03..d140718 100644 --- a/gcc/fortran/intrinsic.texi +++ b/gcc/fortran/intrinsic.texi @@ -13168,10 +13168,10 @@ end program test_sign @table @asis @item @emph{Description}: @code{SIGNAL(NUMBER, HANDLER [, STATUS])} causes external subroutine -@var{HANDLER} to be executed with a single integer argument when signal -@var{NUMBER} occurs. If @var{HANDLER} is an integer, it can be used to -turn off handling of signal @var{NUMBER} or revert to its default -action. See @code{signal(2)}. +@var{HANDLER} to be executed with a single integer argument passed by +value when signal @var{NUMBER} occurs. If @var{HANDLER} is an integer, +it can be used to turn off handling of signal @var{NUMBER} or revert to +its default action. See @code{signal(2)}. If @code{SIGNAL} is called as a subroutine and the @var{STATUS} argument is supplied, it is set to the value returned by @code{signal(2)}. @@ -13197,19 +13197,26 @@ Subroutine, function @item @var{STATUS} @tab (Optional) @var{STATUS} shall be a scalar integer. It has @code{INTENT(OUT)}. @end multitable -@c TODO: What should the interface of the handler be? Does it take arguments? @item @emph{Return value}: The @code{SIGNAL} function returns the value returned by @code{signal(2)}. @item @emph{Example}: @smallexample +module m_handler +contains + ! POSIX.1-2017: void (*func)(int) + subroutine handler_print(signum) bind(C) + use iso_c_binding, only: c_int + integer(c_int), value :: signum + print *, 'handler_print invoked with signum =', signum + end subroutine +end module program test_signal - intrinsic signal - external handler_print - - call signal (12, handler_print) - call signal (10, 1) + use m_handler + intrinsic :: signal, sleep + call signal (12, handler_print) ! 12 = SIGUSR2 (on some systems) + call signal (10, 1) ! 10 = SIGUSR1 and 1 = SIG_IGN (on some systems) call sleep (30) end program test_signal diff --git a/gcc/fortran/invoke.texi b/gcc/fortran/invoke.texi index 38150b1..10387e3 100644 --- a/gcc/fortran/invoke.texi +++ b/gcc/fortran/invoke.texi @@ -1294,7 +1294,8 @@ Specify a list of floating point exception traps to enable. On most systems, if a floating point exception occurs and the trap for that exception is enabled, a SIGFPE signal will be sent and the program being aborted, producing a core file useful for debugging. @var{list} -is a (possibly empty) comma-separated list of the following +is a (possibly empty) comma-separated list of either @samp{none} (to +clear the set of exceptions to be trapped), or of the following exceptions: @samp{invalid} (invalid floating point operation, such as @code{SQRT(-1.0)}), @samp{zero} (division by zero), @samp{overflow} (overflow in a floating point operation), @samp{underflow} (underflow @@ -1314,7 +1315,8 @@ If the option is used more than once in the command line, the lists will be joined: '@code{ffpe-trap=}@var{list1} @code{ffpe-trap=}@var{list2}' is equivalent to @code{ffpe-trap=}@var{list1},@var{list2}. -Note that once enabled an exception cannot be disabled (no negative form). +Note that once enabled an exception cannot be disabled (no negative form), +except by clearing all traps by specifying @samp{none}. Many, if not most, floating point operations incur loss of precision due to rounding, and hence the @code{ffpe-trap=inexact} is likely to diff --git a/gcc/fortran/match.cc b/gcc/fortran/match.cc index c926f38..148a86b 100644 --- a/gcc/fortran/match.cc +++ b/gcc/fortran/match.cc @@ -5541,6 +5541,7 @@ gfc_free_omp_namelist (gfc_omp_namelist *name, bool free_ns, bool free_mem_traits_space) { gfc_omp_namelist *n; + gfc_expr *last_allocator = NULL; for (; name; name = n) { @@ -5552,7 +5553,13 @@ gfc_free_omp_namelist (gfc_omp_namelist *name, bool free_ns, if (free_ns) gfc_free_namespace (name->u2.ns); else if (free_align_allocator) - gfc_free_expr (name->u2.allocator); + { + if (last_allocator != name->u2.allocator) + { + last_allocator = name->u2.allocator; + gfc_free_expr (name->u2.allocator); + } + } else if (free_mem_traits_space) { } /* name->u2.traits_sym: shall not call gfc_free_symbol here. */ else if (name->u2.udr) diff --git a/gcc/fortran/openmp.cc b/gcc/fortran/openmp.cc index dc0c801..1cc65d7 100644 --- a/gcc/fortran/openmp.cc +++ b/gcc/fortran/openmp.cc @@ -2032,11 +2032,9 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask, for (gfc_omp_namelist *n = *head; n; n = n->next) { - n->u2.allocator = ((allocator) - ? gfc_copy_expr (allocator) : NULL); + n->u2.allocator = allocator; n->u.align = (align) ? gfc_copy_expr (align) : NULL; } - gfc_free_expr (allocator); gfc_free_expr (align); continue; } @@ -4547,9 +4545,8 @@ gfc_match_omp_allocate (void) for (; vars; vars = vars->next) { vars->u.align = (align) ? gfc_copy_expr (align) : NULL; - vars->u2.allocator = ((allocator) ? gfc_copy_expr (allocator) : NULL); + vars->u2.allocator = allocator; } - gfc_free_expr (allocator); gfc_free_expr (align); } return MATCH_YES; @@ -7191,7 +7188,7 @@ resolve_omp_udr_clause (gfc_omp_namelist *n, gfc_namespace *ns, /* Assume that a constant expression in the range 1 (omp_default_mem_alloc) to 8 (omp_thread_mem_alloc) range is fine. The original symbol name is already lost during matching via gfc_match_expr. */ -bool +static bool is_predefined_allocator (gfc_expr *expr) { return (gfc_resolve_expr (expr) @@ -7210,9 +7207,19 @@ void gfc_resolve_omp_allocate (gfc_namespace *ns, gfc_omp_namelist *list) { for (gfc_omp_namelist *n = list; n; n = n->next) - n->sym->mark = 0; - for (gfc_omp_namelist *n = list; n; n = n->next) { + if (n->sym->attr.result || n->sym->result == n->sym) + { + gfc_error ("Unexpected function-result variable %qs at %L in " + "declarative !$OMP ALLOCATE", n->sym->name, &n->where); + continue; + } + if (ns->omp_allocate->sym->attr.proc_pointer) + { + gfc_error ("Procedure pointer %qs not supported with !$OMP " + "ALLOCATE at %L", n->sym->name, &n->where); + continue; + } if (n->sym->attr.flavor != FL_VARIABLE) { gfc_error ("Argument %qs at %L to declarative !$OMP ALLOCATE " @@ -7220,8 +7227,7 @@ gfc_resolve_omp_allocate (gfc_namespace *ns, gfc_omp_namelist *list) &n->where); continue; } - if (ns != n->sym->ns || n->sym->attr.use_assoc - || n->sym->attr.host_assoc || n->sym->attr.imported) + if (ns != n->sym->ns || n->sym->attr.use_assoc || n->sym->attr.imported) { gfc_error ("Argument %qs at %L to declarative !$OMP ALLOCATE shall be" " in the same scope as the variable declaration", @@ -7234,7 +7240,13 @@ gfc_resolve_omp_allocate (gfc_namespace *ns, gfc_omp_namelist *list) "declarative !$OMP ALLOCATE", n->sym->name, &n->where); continue; } - if (n->sym->mark) + if (n->sym->attr.codimension) + { + gfc_error ("Unexpected coarray argument %qs as argument at %L to " + "declarative !$OMP ALLOCATE", n->sym->name, &n->where); + continue; + } + if (n->sym->attr.omp_allocate) { if (n->sym->attr.in_common) { @@ -7249,7 +7261,28 @@ gfc_resolve_omp_allocate (gfc_namespace *ns, gfc_omp_namelist *list) n->sym->name, &n->where); continue; } - n->sym->mark = 1; + /* For 'equivalence(a,b)', a 'union_type {<type> a,b} equiv.0' is created + with a value expression for 'a' as 'equiv.0.a' (likewise for b); while + this can be handled, EQUIVALENCE is marked as obsolescent since Fortran + 2018 and also not widely used. However, it could be supported, + if needed. */ + if (n->sym->attr.in_equivalence) + { + gfc_error ("Sorry, EQUIVALENCE object %qs not supported with !$OMP " + "ALLOCATE at %L", n->sym->name, &n->where); + continue; + } + /* Similar for Cray pointer/pointee - they could be implemented but as + common vendor extension but nowadays rarely used and requiring + -fcray-pointer, there is no need to support them. */ + if (n->sym->attr.cray_pointer || n->sym->attr.cray_pointee) + { + gfc_error ("Sorry, Cray pointers and pointees such as %qs are not " + "supported with !$OMP ALLOCATE at %L", + n->sym->name, &n->where); + continue; + } + n->sym->attr.omp_allocate = 1; if ((n->sym->ts.type == BT_CLASS && n->sym->attr.class_ok && CLASS_DATA (n->sym)->attr.allocatable) || (n->sym->ts.type != BT_CLASS && n->sym->attr.allocatable)) @@ -7307,8 +7340,6 @@ gfc_resolve_omp_allocate (gfc_namespace *ns, gfc_omp_namelist *list) "%<omp_allocator_handle_kind%> kind at %L", &n->u2.allocator->where); } - gfc_error ("Sorry, declarative !$OMP ALLOCATE at %L not yet supported", - &list->where); } /* Resolve ASSUME's and ASSUMES' assumption clauses. Note that absent/contains @@ -7897,6 +7928,9 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses, { if (n->sym == NULL) continue; + if (n->sym->attr.codimension) + gfc_error ("Unexpected coarray %qs in %<allocate%> at %L", + n->sym->name, &n->where); for (a = code->block->next->ext.alloc.list; a; a = a->next) if (a->expr->expr_type == EXPR_VARIABLE && a->expr->symtree->n.sym == n->sym) @@ -11245,6 +11279,8 @@ resolve_omp_target (gfc_code *code) if (!code->ext.omp_clauses->contains_teams_construct) return; gfc_code *c = code->block->next; + if (c->op == EXEC_BLOCK) + c = c->ext.block.ns->code; if (code->ext.omp_clauses->target_first_st_is_teams && ((GFC_IS_TEAMS_CONSTRUCT (c->op) && c->next == NULL) || (c->op == EXEC_BLOCK diff --git a/gcc/fortran/options.cc b/gcc/fortran/options.cc index 27311961..2ad2247 100644 --- a/gcc/fortran/options.cc +++ b/gcc/fortran/options.cc @@ -555,9 +555,12 @@ gfc_handle_fpe_option (const char *arg, bool trap) pos++; result = 0; - if (!trap && strncmp ("none", arg, pos) == 0) + if (strncmp ("none", arg, pos) == 0) { - gfc_option.fpe_summary = 0; + if (trap) + gfc_option.fpe = 0; + else + gfc_option.fpe_summary = 0; arg += pos; pos = 0; continue; @@ -586,7 +589,7 @@ gfc_handle_fpe_option (const char *arg, bool trap) break; } } - if (!result && !trap) + if (!result && trap) gfc_fatal_error ("Argument to %<-ffpe-trap%> is not valid: %s", arg); else if (!result) gfc_fatal_error ("Argument to %<-ffpe-summary%> is not valid: %s", arg); diff --git a/gcc/fortran/parse.cc b/gcc/fortran/parse.cc index 5838680..e103ebe 100644 --- a/gcc/fortran/parse.cc +++ b/gcc/fortran/parse.cc @@ -833,18 +833,18 @@ check_omp_allocate_stmt (locus *loc) &n->expr->where, gfc_ascii_statement (ST_OMP_ALLOCATE)); return false; } + /* Procedure pointers are not allocatable; hence, we do not regard them as + pointers here - and reject them later in gfc_resolve_omp_allocate. */ bool alloc_ptr; if (n->sym->ts.type == BT_CLASS && n->sym->attr.class_ok) alloc_ptr = (CLASS_DATA (n->sym)->attr.allocatable || CLASS_DATA (n->sym)->attr.class_pointer); else - alloc_ptr = (n->sym->attr.allocatable || n->sym->attr.pointer - || n->sym->attr.proc_pointer); + alloc_ptr = n->sym->attr.allocatable || n->sym->attr.pointer; if (alloc_ptr || (n->sym->ns && n->sym->ns->proc_name && (n->sym->ns->proc_name->attr.allocatable - || n->sym->ns->proc_name->attr.pointer - || n->sym->ns->proc_name->attr.proc_pointer))) + || n->sym->ns->proc_name->attr.pointer))) has_allocatable = true; else has_non_allocatable = true; @@ -5814,7 +5814,7 @@ parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only) { gfc_statement st, omp_end_st, first_st; gfc_code *cp, *np; - gfc_state_data s; + gfc_state_data s, s2; accept_statement (omp_st); @@ -5915,13 +5915,21 @@ parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only) gfc_notify_std (GFC_STD_F2008, "BLOCK construct at %C"); my_ns = gfc_build_block_ns (gfc_current_ns); - gfc_current_ns = my_ns; - my_parent = my_ns->parent; - new_st.op = EXEC_BLOCK; new_st.ext.block.ns = my_ns; new_st.ext.block.assoc = NULL; accept_statement (ST_BLOCK); + + push_state (&s2, COMP_BLOCK, my_ns->proc_name); + gfc_current_ns = my_ns; + my_parent = my_ns->parent; + if (omp_st == ST_OMP_SECTIONS + || omp_st == ST_OMP_PARALLEL_SECTIONS) + { + np = new_level (cp); + np->op = cp->op; + } + first_st = next_statement (); st = parse_spec (first_st); } @@ -5937,6 +5945,8 @@ parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only) case ST_OMP_TEAMS_LOOP: { gfc_state_data *stk = gfc_state_stack->previous; + if (stk->state == COMP_OMP_STRICTLY_STRUCTURED_BLOCK) + stk = stk->previous; stk->tail->ext.omp_clauses->target_first_st_is_teams = true; break; } @@ -6035,8 +6045,10 @@ parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only) else if (block_construct && st == ST_END_BLOCK) { accept_statement (st); + gfc_current_ns->code = gfc_state_stack->head; gfc_current_ns = my_parent; - pop_state (); + pop_state (); /* Inner BLOCK */ + pop_state (); /* Outer COMP_OMP_STRICTLY_STRUCTURED_BLOCK */ st = next_statement (); if (st == omp_end_st) diff --git a/gcc/fortran/scanner.cc b/gcc/fortran/scanner.cc index 9f0d9a7..e2a25a1 100644 --- a/gcc/fortran/scanner.cc +++ b/gcc/fortran/scanner.cc @@ -877,7 +877,7 @@ skip_free_comments (void) /* If -fopenmp/-fopenacc, we need to handle here 2 things: 1) don't treat !$omp/!$acc as comments, but directives - 2) handle OpenMP/OpenACC conditional compilation, where + 2) handle OpenMP conditional compilation, where !$ should be treated as 2 spaces (for initial lines only if followed by space). */ if (at_bol) @@ -1106,7 +1106,7 @@ skip_fixed_comments (void) /* If -fopenmp/-fopenacc, we need to handle here 2 things: 1) don't treat !$omp/!$acc|c$omp/c$acc|*$omp / *$acc as comments, but directives - 2) handle OpenMP/OpenACC conditional compilation, where + 2) handle OpenMP conditional compilation, where !$|c$|*$ should be treated as 2 spaces if the characters in columns 3 to 6 are valid fixed form label columns characters. */ diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc index e0fc8eb..bbb81f4 100644 --- a/gcc/fortran/trans-array.cc +++ b/gcc/fortran/trans-array.cc @@ -82,6 +82,9 @@ along with GCC; see the file COPYING3. If not see #include "tree.h" #include "gfortran.h" #include "gimple-expr.h" +#include "tree-iterator.h" +#include "stringpool.h" /* Required by "attribs.h". */ +#include "attribs.h" /* For lookup_attribute. */ #include "trans.h" #include "fold-const.h" #include "constructor.h" @@ -6770,6 +6773,15 @@ gfc_trans_auto_array_allocation (tree decl, gfc_symbol * sym, gimplifier to allocate storage, and all that good stuff. */ tmp = fold_build1_loc (input_location, DECL_EXPR, TREE_TYPE (decl), decl); gfc_add_expr_to_block (&init, tmp); + if (sym->attr.omp_allocate) + { + /* Save location of size calculation to ensure GOMP_alloc is placed + after it. */ + tree omp_alloc = lookup_attribute ("omp allocate", + DECL_ATTRIBUTES (decl)); + TREE_CHAIN (TREE_CHAIN (TREE_VALUE (omp_alloc))) + = build_tree_list (NULL_TREE, tsi_stmt (tsi_last (init.head))); + } } if (onstack) @@ -6798,8 +6810,22 @@ gfc_trans_auto_array_allocation (tree decl, gfc_symbol * sym, gfc_add_init_cleanup (block, gfc_finish_block (&init), NULL_TREE); return; } + if (sym->attr.omp_allocate) + { + /* The size is the number of elements in the array, so multiply by the + size of an element to get the total size. */ + tmp = TYPE_SIZE_UNIT (gfc_get_element_type (type)); + size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type, + size, fold_convert (gfc_array_index_type, tmp)); + size = gfc_evaluate_now (size, &init); - if (flag_stack_arrays) + tree omp_alloc = lookup_attribute ("omp allocate", + DECL_ATTRIBUTES (decl)); + TREE_CHAIN (TREE_CHAIN (TREE_VALUE (omp_alloc))) + = build_tree_list (size, NULL_TREE); + space = NULL_TREE; + } + else if (flag_stack_arrays) { gcc_assert (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE); space = build_decl (gfc_get_location (&sym->declared_at), @@ -9320,6 +9346,12 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl, tree dest, gfc_add_expr_to_block (&fnblock, tmp); } + /* Still having a descriptor array of rank == 0 here, indicates an + allocatable coarrays. Dereference it correctly. */ + if (GFC_DESCRIPTOR_TYPE_P (decl_type)) + { + decl = build_fold_indirect_ref (gfc_conv_array_data (decl)); + } /* Otherwise, act on the components or recursively call self to act on a chain of components. */ for (c = der_type->components; c; c = c->next) @@ -11507,7 +11539,11 @@ gfc_trans_deferred_array (gfc_symbol * sym, gfc_wrapped_block * block) { int rank; rank = sym->as ? sym->as->rank : 0; - tmp = gfc_deallocate_alloc_comp (sym->ts.u.derived, descriptor, rank); + tmp = gfc_deallocate_alloc_comp (sym->ts.u.derived, descriptor, rank, + (sym->attr.codimension + && flag_coarray == GFC_FCOARRAY_LIB) + ? GFC_STRUCTURE_CAF_MODE_IN_COARRAY + : 0); gfc_add_expr_to_block (&cleanup, tmp); } @@ -11521,9 +11557,11 @@ gfc_trans_deferred_array (gfc_symbol * sym, gfc_wrapped_block * block) NULL_TREE, NULL_TREE, true, e, sym->attr.codimension ? GFC_CAF_COARRAY_DEREGISTER - : GFC_CAF_COARRAY_NOCOARRAY); + : GFC_CAF_COARRAY_NOCOARRAY, + NULL_TREE, gfc_finish_block (&cleanup)); if (e) gfc_free_expr (e); + gfc_init_block (&cleanup); gfc_add_expr_to_block (&cleanup, tmp); } diff --git a/gcc/fortran/trans-decl.cc b/gcc/fortran/trans-decl.cc index b0fd25e..a3f037b 100644 --- a/gcc/fortran/trans-decl.cc +++ b/gcc/fortran/trans-decl.cc @@ -48,6 +48,7 @@ along with GCC; see the file COPYING3. If not see #include "gimplify.h" #include "omp-general.h" #include "attr-fnspec.h" +#include "tree-iterator.h" #define MAX_LABEL_VALUE 99999 @@ -4652,6 +4653,36 @@ gfc_trans_deferred_vars (gfc_symbol * proc_sym, gfc_wrapped_block * block) init_intent_out_dt (proc_sym, block); gfc_restore_backend_locus (&loc); + /* For some reasons, internal procedures point to the parent's + namespace. Top-level procedure and variables inside BLOCK are fine. */ + gfc_namespace *omp_ns = proc_sym->ns; + if (proc_sym->ns->proc_name != proc_sym) + for (omp_ns = proc_sym->ns->contained; omp_ns; + omp_ns = omp_ns->sibling) + if (omp_ns->proc_name == proc_sym) + break; + + /* Add 'omp allocate' attribute for gfc_trans_auto_array_allocation and + unset attr.omp_allocate for 'omp allocate allocator(omp_default_mem_alloc), + which has the normal codepath except for an invalid-use check in the ME. + The main processing happens later in this function. */ + for (struct gfc_omp_namelist *n = omp_ns ? omp_ns->omp_allocate : NULL; + n; n = n->next) + if (!TREE_STATIC (n->sym->backend_decl)) + { + /* Add empty entries - described and to be filled below. */ + tree tmp = build_tree_list (NULL_TREE, NULL_TREE); + TREE_CHAIN (tmp) = build_tree_list (NULL_TREE, NULL_TREE); + DECL_ATTRIBUTES (n->sym->backend_decl) + = tree_cons (get_identifier ("omp allocate"), tmp, + DECL_ATTRIBUTES (n->sym->backend_decl)); + if (n->u.align == NULL + && n->u2.allocator != NULL + && n->u2.allocator->expr_type == EXPR_CONSTANT + && mpz_cmp_si (n->u2.allocator->value.integer, 1) == 0) + n->sym->attr.omp_allocate = 0; + } + for (sym = proc_sym->tlink; sym != proc_sym; sym = sym->tlink) { bool alloc_comp_or_fini = (sym->ts.type == BT_DERIVED) @@ -5105,6 +5136,101 @@ gfc_trans_deferred_vars (gfc_symbol * proc_sym, gfc_wrapped_block * block) gcc_unreachable (); } + /* Handle 'omp allocate'. This has to be after the block above as + gfc_add_init_cleanup (..., init, ...) puts 'init' of later calls + before earlier calls. The code is a bit more complex as gfortran does + not really work with bind expressions / BIND_EXPR_VARS properly, i.e. + gimplify_bind_expr needs some help for placing the GOMP_alloc. Thus, + we pass on the location of the allocate-assignment expression and, + if the size is not constant, the size variable if Fortran computes this + differently. We also might add an expression location after which the + code has to be added, e.g. for character len expressions, which affect + the UNIT_SIZE. */ + gfc_expr *last_allocator = NULL; + if (omp_ns && omp_ns->omp_allocate) + { + if (!block->init || TREE_CODE (block->init) != STATEMENT_LIST) + { + tree tmp = build1_v (LABEL_EXPR, gfc_build_label_decl (NULL_TREE)); + append_to_statement_list (tmp, &block->init); + } + if (!block->cleanup || TREE_CODE (block->cleanup) != STATEMENT_LIST) + { + tree tmp = build1_v (LABEL_EXPR, gfc_build_label_decl (NULL_TREE)); + append_to_statement_list (tmp, &block->cleanup); + } + } + tree init_stmtlist = block->init; + tree cleanup_stmtlist = block->cleanup; + se.expr = NULL_TREE; + for (struct gfc_omp_namelist *n = omp_ns ? omp_ns->omp_allocate : NULL; + n; n = n->next) + if (!TREE_STATIC (n->sym->backend_decl)) + { + tree align = (n->u.align ? gfc_conv_constant_to_tree (n->u.align) + : NULL_TREE); + if (last_allocator != n->u2.allocator) + { + location_t loc = input_location; + gfc_init_se (&se, NULL); + if (n->u2.allocator) + { + input_location = gfc_get_location (&n->u2.allocator->where); + gfc_conv_expr (&se, n->u2.allocator); + } + /* We need to evalulate non-constants - also to find the location + after which the GOMP_alloc has to be added to - also as BLOCK + does not yield a new BIND_EXPR_BODY. */ + if (n->u2.allocator + && (!(CONSTANT_CLASS_P (se.expr) && DECL_P (se.expr)) + || se.pre.head || se.post.head)) + { + stmtblock_t tmpblock; + gfc_init_block (&tmpblock); + se.expr = gfc_evaluate_now (se.expr, &tmpblock); + /* First post then pre because the new code is inserted + at the top. */ + gfc_add_init_cleanup (block, gfc_finish_block (&se.post), NULL); + gfc_add_init_cleanup (block, gfc_finish_block (&tmpblock), + NULL); + gfc_add_init_cleanup (block, gfc_finish_block (&se.pre), NULL); + } + last_allocator = n->u2.allocator; + input_location = loc; + } + + /* 'omp allocate( {purpose: allocator, value: align}, + {purpose: init-stmtlist, value: cleanup-stmtlist}, + {purpose: size-var, value: last-size-expr}} + where init-stmt/cleanup-stmt is the STATEMENT list to find the + try-final block; last-size-expr is to find the location after + which to add the code and 'size-var' is for the proper size, cf. + gfc_trans_auto_array_allocation - either or both of the latter + can be NULL. */ + tree tmp = lookup_attribute ("omp allocate", + DECL_ATTRIBUTES (n->sym->backend_decl)); + tmp = TREE_VALUE (tmp); + TREE_PURPOSE (tmp) = se.expr; + TREE_VALUE (tmp) = align; + TREE_PURPOSE (TREE_CHAIN (tmp)) = init_stmtlist; + TREE_VALUE (TREE_CHAIN (tmp)) = cleanup_stmtlist; + } + else if (n->sym->attr.in_common) + { + gfc_error ("Sorry, !$OMP allocate for COMMON block variable %qs at %L " + "not supported", n->sym->common_block->name, + &n->sym->common_block->where); + break; + } + else + { + gfc_error ("Sorry, !$OMP allocate for variable %qs at %L with SAVE " + "attribute not yet implemented", n->sym->name, + &n->sym->declared_at); + /* FIXME: Remember to handle last_allocator. */ + break; + } + gfc_init_block (&tmpblock); for (f = gfc_sym_get_dummy_args (proc_sym); f; f = f->next) diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc index cca2f4e..1b8be08 100644 --- a/gcc/fortran/trans-expr.cc +++ b/gcc/fortran/trans-expr.cc @@ -10403,11 +10403,36 @@ gfc_trans_pointer_assignment (gfc_expr * expr1, gfc_expr * expr2) } if (expr1->ts.type == BT_CHARACTER - && expr1->symtree->n.sym->ts.deferred - && expr1->symtree->n.sym->ts.u.cl->backend_decl - && VAR_P (expr1->symtree->n.sym->ts.u.cl->backend_decl)) + && expr1->ts.deferred) { - tmp = expr1->symtree->n.sym->ts.u.cl->backend_decl; + gfc_symbol *psym = expr1->symtree->n.sym; + tmp = NULL_TREE; + if (psym->ts.type == BT_CHARACTER) + { + gcc_assert (psym->ts.u.cl->backend_decl + && VAR_P (psym->ts.u.cl->backend_decl)); + tmp = psym->ts.u.cl->backend_decl; + } + else if (expr1->ts.u.cl->backend_decl + && VAR_P (expr1->ts.u.cl->backend_decl)) + tmp = expr1->ts.u.cl->backend_decl; + else if (TREE_CODE (lse.expr) == COMPONENT_REF) + { + gfc_ref *ref = expr1->ref; + for (;ref; ref = ref->next) + { + if (ref->type == REF_COMPONENT + && ref->u.c.component->ts.type == BT_CHARACTER + && gfc_deferred_strlen (ref->u.c.component, &tmp)) + tmp = fold_build3_loc (input_location, COMPONENT_REF, + TREE_TYPE (tmp), + TREE_OPERAND (lse.expr, 0), + tmp, NULL_TREE); + } + } + + gcc_assert (tmp); + if (expr2->expr_type != EXPR_NULL) gfc_add_modify (&block, tmp, fold_convert (TREE_TYPE (tmp), strlen_rhs)); @@ -10723,7 +10748,7 @@ gfc_trans_scalar_assign (gfc_se * lse, gfc_se * rse, gfc_typespec ts, { tmp_var = gfc_evaluate_now (lse->expr, &lse->pre); tmp = gfc_deallocate_alloc_comp_no_caf (ts.u.derived, tmp_var, - 0, true); + 0, gfc_may_be_finalized (ts)); if (deep_copy) tmp = build3_v (COND_EXPR, cond, build_empty_stmt (input_location), tmp); @@ -11990,7 +12015,10 @@ gfc_trans_assignment_1 (gfc_expr * expr1, gfc_expr * expr2, bool init_flag, && !is_runtime_conformable (expr1, expr2); /* Only analyze the expressions for coarray properties, when in coarray-lib - mode. */ + mode. Avoid false-positive uninitialized diagnostics with initializing + the codimension flag unconditionally. */ + lhs_caf_attr.codimension = false; + rhs_caf_attr.codimension = false; if (flag_coarray == GFC_FCOARRAY_LIB) { lhs_caf_attr = gfc_caf_attr (expr1, false, &lhs_refs_comp); diff --git a/gcc/fortran/trans-openmp.cc b/gcc/fortran/trans-openmp.cc index 2f116fd..7930f2f 100644 --- a/gcc/fortran/trans-openmp.cc +++ b/gcc/fortran/trans-openmp.cc @@ -2739,34 +2739,48 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses, } break; case OMP_LIST_ALLOCATE: - for (; n != NULL; n = n->next) - if (n->sym->attr.referenced) - { - tree t = gfc_trans_omp_variable (n->sym, false); - if (t != error_mark_node) - { - tree node = build_omp_clause (input_location, - OMP_CLAUSE_ALLOCATE); - OMP_CLAUSE_DECL (node) = t; - if (n->u2.allocator) - { - tree allocator_; - gfc_init_se (&se, NULL); - gfc_conv_expr (&se, n->u2.allocator); - allocator_ = gfc_evaluate_now (se.expr, block); - OMP_CLAUSE_ALLOCATE_ALLOCATOR (node) = allocator_; - } - if (n->u.align) - { - tree align_; - gfc_init_se (&se, NULL); - gfc_conv_expr (&se, n->u.align); - align_ = gfc_evaluate_now (se.expr, block); - OMP_CLAUSE_ALLOCATE_ALIGN (node) = align_; - } - omp_clauses = gfc_trans_add_clause (node, omp_clauses); - } - } + { + tree allocator_ = NULL_TREE; + gfc_expr *alloc_expr = NULL; + for (; n != NULL; n = n->next) + if (n->sym->attr.referenced) + { + tree t = gfc_trans_omp_variable (n->sym, false); + if (t != error_mark_node) + { + tree node = build_omp_clause (input_location, + OMP_CLAUSE_ALLOCATE); + OMP_CLAUSE_DECL (node) = t; + if (n->u2.allocator) + { + if (alloc_expr != n->u2.allocator) + { + gfc_init_se (&se, NULL); + gfc_conv_expr (&se, n->u2.allocator); + gfc_add_block_to_block (block, &se.pre); + allocator_ = gfc_evaluate_now (se.expr, block); + gfc_add_block_to_block (block, &se.post); + } + OMP_CLAUSE_ALLOCATE_ALLOCATOR (node) = allocator_; + } + alloc_expr = n->u2.allocator; + if (n->u.align) + { + tree align_; + gfc_init_se (&se, NULL); + gfc_conv_expr (&se, n->u.align); + gcc_assert (CONSTANT_CLASS_P (se.expr) + && se.pre.head == NULL + && se.post.head == NULL); + align_ = se.expr; + OMP_CLAUSE_ALLOCATE_ALIGN (node) = align_; + } + omp_clauses = gfc_trans_add_clause (node, omp_clauses); + } + } + else + alloc_expr = n->u2.allocator; + } break; case OMP_LIST_LINEAR: { @@ -7184,11 +7198,14 @@ gfc_trans_omp_sections (gfc_code *code, gfc_omp_clauses *clauses) static tree gfc_trans_omp_single (gfc_code *code, gfc_omp_clauses *clauses) { - tree omp_clauses = gfc_trans_omp_clauses (NULL, clauses, code->loc); + stmtblock_t block; + gfc_start_block (&block); + tree omp_clauses = gfc_trans_omp_clauses (&block, clauses, code->loc); tree stmt = gfc_trans_omp_code (code->block->next, true); stmt = build2_loc (gfc_get_location (&code->loc), OMP_SINGLE, void_type_node, stmt, omp_clauses); - return stmt; + gfc_add_expr_to_block (&block, stmt); + return gfc_finish_block (&block); } static tree |