aboutsummaryrefslogtreecommitdiff
path: root/gcc/fortran
diff options
context:
space:
mode:
authorThomas Schwinge <tschwinge@baylibre.com>2024-03-11 22:51:28 +0100
committerThomas Schwinge <tschwinge@baylibre.com>2024-03-11 22:51:28 +0100
commita95e21151a6366e7344d0f1983f99e318c5a7097 (patch)
tree11d987406d9ce8399ec1736477d971ef09344df2 /gcc/fortran
parent02d394b2736afa9a24ab3e1b8ad56fd6ac37e0f4 (diff)
parentaf4bb221153359f5948da917d5ef2df738bb1e61 (diff)
downloadgcc-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/ChangeLog108
-rw-r--r--gcc/fortran/decl.cc4
-rw-r--r--gcc/fortran/error.cc14
-rw-r--r--gcc/fortran/frontend-passes.cc2
-rw-r--r--gcc/fortran/gfortran.h1
-rw-r--r--gcc/fortran/intrinsic.texi27
-rw-r--r--gcc/fortran/invoke.texi6
-rw-r--r--gcc/fortran/match.cc9
-rw-r--r--gcc/fortran/openmp.cc64
-rw-r--r--gcc/fortran/options.cc9
-rw-r--r--gcc/fortran/parse.cc30
-rw-r--r--gcc/fortran/scanner.cc4
-rw-r--r--gcc/fortran/trans-array.cc44
-rw-r--r--gcc/fortran/trans-decl.cc126
-rw-r--r--gcc/fortran/trans-expr.cc40
-rw-r--r--gcc/fortran/trans-openmp.cc77
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