aboutsummaryrefslogtreecommitdiff
path: root/gcc/fortran/parse.cc
diff options
context:
space:
mode:
authorPaul Thomas <pault@gcc.gnu.org>2023-06-02 08:41:45 +0100
committerPaul Thomas <pault@gcc.gnu.org>2023-06-02 08:41:45 +0100
commit3c2eba4b7a2355ed5099e35332388206c484744d (patch)
treee5dce6f0cdf6c624dae34c2797412f7ab3da46d7 /gcc/fortran/parse.cc
parenta06b9435b9652ea1b0d30e6fa176c91df314954f (diff)
downloadgcc-3c2eba4b7a2355ed5099e35332388206c484744d.zip
gcc-3c2eba4b7a2355ed5099e35332388206c484744d.tar.gz
gcc-3c2eba4b7a2355ed5099e35332388206c484744d.tar.bz2
Fortran: Fix some problems blocking associate meta-bug [PR87477]
2023-06-02 Paul Thomas <pault@gcc.gnu.org> gcc/fortran PR fortran/87477 * parse.cc (parse_associate): Replace the existing evaluation of the target rank with calls to gfc_resolve_ref and gfc_expression_rank. Identify untyped target function results with structure constructors by finding the appropriate derived type. * resolve.cc (resolve_symbol): Allow associate variables to be assumed shape. gcc/testsuite/ PR fortran/87477 * gfortran.dg/associate_54.f90 : Cope with extra error. PR fortran/102109 * gfortran.dg/pr102109.f90 : New test. PR fortran/102112 * gfortran.dg/pr102112.f90 : New test. PR fortran/102190 * gfortran.dg/pr102190.f90 : New test. PR fortran/102532 * gfortran.dg/pr102532.f90 : New test. PR fortran/109948 * gfortran.dg/pr109948.f90 : New test. PR fortran/99326 * gfortran.dg/pr99326.f90 : New test.
Diffstat (limited to 'gcc/fortran/parse.cc')
-rw-r--r--gcc/fortran/parse.cc61
1 files changed, 34 insertions, 27 deletions
diff --git a/gcc/fortran/parse.cc b/gcc/fortran/parse.cc
index 733294c..e53b7a4 100644
--- a/gcc/fortran/parse.cc
+++ b/gcc/fortran/parse.cc
@@ -5037,6 +5037,7 @@ parse_associate (void)
gfc_state_data s;
gfc_statement st;
gfc_association_list* a;
+ gfc_array_spec *as;
gfc_notify_std (GFC_STD_F2003, "ASSOCIATE construct at %C");
@@ -5052,8 +5053,7 @@ parse_associate (void)
for (a = new_st.ext.block.assoc; a; a = a->next)
{
gfc_symbol* sym;
- gfc_ref *ref;
- gfc_array_ref *array_ref;
+ gfc_expr *target;
if (gfc_get_sym_tree (a->name, NULL, &a->st, false))
gcc_unreachable ();
@@ -5070,6 +5070,7 @@ parse_associate (void)
for parsing component references on the associate-name
in case of association to a derived-type. */
sym->ts = a->target->ts;
+ target = a->target;
/* Don’t share the character length information between associate
variable and target if the length is not a compile-time constant,
@@ -5089,31 +5090,37 @@ parse_associate (void)
&& sym->ts.u.cl->length->expr_type == EXPR_CONSTANT))
sym->ts.u.cl = gfc_new_charlen (gfc_current_ns, NULL);
- /* Check if the target expression is array valued. This cannot always
- be done by looking at target.rank, because that might not have been
- set yet. Therefore traverse the chain of refs, looking for the last
- array ref and evaluate that. */
- array_ref = NULL;
- for (ref = a->target->ref; ref; ref = ref->next)
- if (ref->type == REF_ARRAY)
- array_ref = &ref->u.ar;
- if (array_ref || a->target->rank)
+ /* Check if the target expression is array valued. This cannot be done
+ by calling gfc_resolve_expr because the context is unavailable.
+ However, the references can be resolved and the rank of the target
+ expression set. */
+ if (target->ref && gfc_resolve_ref (target)
+ && target->expr_type != EXPR_ARRAY
+ && target->expr_type != EXPR_COMPCALL)
+ gfc_expression_rank (target);
+
+ /* Determine whether or not function expressions with unknown type are
+ structure constructors. If so, the function result can be converted
+ to be a derived type.
+ TODO: Deal with references to sibling functions that have not yet been
+ parsed (PRs 89645 and 99065). */
+ if (target->expr_type == EXPR_FUNCTION && target->ts.type == BT_UNKNOWN)
{
- gfc_array_spec *as;
- int dim, rank = 0;
- if (array_ref)
+ gfc_symbol *derived;
+ /* The derived type has a leading uppercase character. */
+ gfc_find_symbol (gfc_dt_upper_string (target->symtree->name),
+ my_ns->parent, 1, &derived);
+ if (derived && derived->attr.flavor == FL_DERIVED)
{
- a->rankguessed = 1;
- /* Count the dimension, that have a non-scalar extend. */
- for (dim = 0; dim < array_ref->dimen; ++dim)
- if (array_ref->dimen_type[dim] != DIMEN_ELEMENT
- && !(array_ref->dimen_type[dim] == DIMEN_UNKNOWN
- && array_ref->end[dim] == NULL
- && array_ref->start[dim] != NULL))
- ++rank;
+ sym->ts.type = BT_DERIVED;
+ sym->ts.u.derived = derived;
}
- else
- rank = a->target->rank;
+ }
+
+ if (target->rank)
+ {
+ int rank = 0;
+ rank = target->rank;
/* When the rank is greater than zero then sym will be an array. */
if (sym->ts.type == BT_CLASS && CLASS_DATA (sym))
{
@@ -5124,8 +5131,8 @@ parse_associate (void)
/* Don't just (re-)set the attr and as in the sym.ts,
because this modifies the target's attr and as. Copy the
data and do a build_class_symbol. */
- symbol_attribute attr = CLASS_DATA (a->target)->attr;
- int corank = gfc_get_corank (a->target);
+ symbol_attribute attr = CLASS_DATA (target)->attr;
+ int corank = gfc_get_corank (target);
gfc_typespec type;
if (rank || corank)
@@ -5160,7 +5167,7 @@ parse_associate (void)
as = gfc_get_array_spec ();
as->type = AS_DEFERRED;
as->rank = rank;
- as->corank = gfc_get_corank (a->target);
+ as->corank = gfc_get_corank (target);
sym->as = as;
sym->attr.dimension = 1;
if (as->corank)