aboutsummaryrefslogtreecommitdiff
path: root/gcc/fortran/resolve.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/fortran/resolve.cc')
-rw-r--r--gcc/fortran/resolve.cc141
1 files changed, 115 insertions, 26 deletions
diff --git a/gcc/fortran/resolve.cc b/gcc/fortran/resolve.cc
index f03708e..e51f83b 100644
--- a/gcc/fortran/resolve.cc
+++ b/gcc/fortran/resolve.cc
@@ -11484,6 +11484,109 @@ resolve_lock_unlock_event (gfc_code *code)
}
}
+static void
+resolve_team_argument (gfc_expr *team)
+{
+ gfc_resolve_expr (team);
+ if (team->rank != 0 || team->ts.type != BT_DERIVED
+ || team->ts.u.derived->from_intmod != INTMOD_ISO_FORTRAN_ENV
+ || team->ts.u.derived->intmod_sym_id != ISOFORTRAN_TEAM_TYPE)
+ {
+ gfc_error ("TEAM argument at %L must be a scalar expression "
+ "of type TEAM_TYPE from the intrinsic module ISO_FORTRAN_ENV",
+ &team->where);
+ }
+}
+
+static void
+resolve_scalar_variable_as_arg (const char *name, bt exp_type, int exp_kind,
+ gfc_expr *e)
+{
+ gfc_resolve_expr (e);
+ if (e
+ && (e->ts.type != exp_type || e->ts.kind < exp_kind || e->rank != 0
+ || e->expr_type != EXPR_VARIABLE))
+ gfc_error ("%s argument at %L must be a scalar %s variable of at least "
+ "kind %d", name, &e->where, gfc_basic_typename (exp_type),
+ exp_kind);
+}
+
+void
+gfc_resolve_sync_stat (struct sync_stat *sync_stat)
+{
+ resolve_scalar_variable_as_arg ("STAT=", BT_INTEGER, 2, sync_stat->stat);
+ resolve_scalar_variable_as_arg ("ERRMSG=", BT_CHARACTER,
+ gfc_default_character_kind,
+ sync_stat->errmsg);
+}
+
+static void
+resolve_scalar_argument (const char *name, bt exp_type, int exp_kind,
+ gfc_expr *e)
+{
+ gfc_resolve_expr (e);
+ if (e
+ && (e->ts.type != exp_type || e->ts.kind < exp_kind || e->rank != 0))
+ gfc_error ("%s argument at %L must be a scalar %s of at least kind %d",
+ name, &e->where, gfc_basic_typename (exp_type), exp_kind);
+}
+
+static void
+resolve_form_team (gfc_code *code)
+{
+ resolve_scalar_argument ("TEAM NUMBER", BT_INTEGER, gfc_default_integer_kind,
+ code->expr1);
+ resolve_team_argument (code->expr2);
+ resolve_scalar_argument ("NEW_INDEX=", BT_INTEGER, gfc_default_integer_kind,
+ code->expr3);
+ gfc_resolve_sync_stat (&code->ext.sync_stat);
+}
+
+static void resolve_block_construct (gfc_code *);
+
+static void
+resolve_change_team (gfc_code *code)
+{
+ resolve_team_argument (code->expr1);
+ gfc_resolve_sync_stat (&code->ext.block.sync_stat);
+ resolve_block_construct (code);
+ /* Map the coarray bounds as selected. */
+ for (gfc_association_list *a = code->ext.block.assoc; a; a = a->next)
+ if (a->ar)
+ {
+ gfc_array_spec *src = a->ar->as, *dst;
+ if (a->st->n.sym->ts.type == BT_CLASS)
+ dst = CLASS_DATA (a->st->n.sym)->as;
+ else
+ dst = a->st->n.sym->as;
+ dst->corank = src->corank;
+ dst->cotype = src->cotype;
+ for (int i = 0; i < src->corank; ++i)
+ {
+ dst->lower[dst->rank + i] = src->lower[i];
+ dst->upper[dst->rank + i] = src->upper[i];
+ src->lower[i] = src->upper[i] = nullptr;
+ }
+ gfc_free_array_spec (src);
+ free (a->ar);
+ a->ar = nullptr;
+ dst->resolved = false;
+ gfc_resolve_array_spec (dst, 0);
+ }
+}
+
+static void
+resolve_sync_team (gfc_code *code)
+{
+ resolve_team_argument (code->expr1);
+ gfc_resolve_sync_stat (&code->ext.sync_stat);
+}
+
+static void
+resolve_end_team (gfc_code *code)
+{
+ gfc_resolve_sync_stat (&code->ext.sync_stat);
+}
static void
resolve_critical (gfc_code *code)
@@ -11493,6 +11596,8 @@ resolve_critical (gfc_code *code)
char name[GFC_MAX_SYMBOL_LEN];
static int serial = 0;
+ gfc_resolve_sync_stat (&code->ext.sync_stat);
+
if (flag_coarray != GFC_FCOARRAY_LIB)
return;
@@ -11616,8 +11721,8 @@ resolve_branch (gfc_st_label *label, gfc_code *code)
if (code->here == label)
{
- gfc_warning (0,
- "Branch at %L may result in an infinite loop", &code->loc);
+ gfc_warning (0, "Branch at %L may result in an infinite loop",
+ &code->loc);
return;
}
@@ -11640,6 +11745,10 @@ resolve_branch (gfc_st_label *label, gfc_code *code)
&& bitmap_bit_p (stack->reachable_labels, label->value))
gfc_error ("GOTO statement at %L leaves DO CONCURRENT construct "
"for label at %L", &code->loc, &label->where);
+ else if (stack->current->op == EXEC_CHANGE_TEAM
+ && bitmap_bit_p (stack->reachable_labels, label->value))
+ gfc_error ("GOTO statement at %L leaves CHANGE TEAM construct "
+ "for label at %L", &code->loc, &label->where);
}
return;
@@ -13276,23 +13385,6 @@ deferred_op_assign (gfc_code **code, gfc_namespace *ns)
}
-static bool
-check_team (gfc_expr *team, const char *intrinsic)
-{
- if (team->rank != 0
- || team->ts.type != BT_DERIVED
- || team->ts.u.derived->from_intmod != INTMOD_ISO_FORTRAN_ENV
- || team->ts.u.derived->intmod_sym_id != ISOFORTRAN_TEAM_TYPE)
- {
- gfc_error ("TEAM argument to %qs at %L must be a scalar expression "
- "of type TEAM_TYPE", intrinsic, &team->where);
- return false;
- }
-
- return true;
-}
-
-
/* Given a block of code, recursively resolve everything pointed to by this
code block. */
@@ -13481,22 +13573,19 @@ start:
break;
case EXEC_FORM_TEAM:
- if (code->expr1 != NULL
- && (code->expr1->ts.type != BT_INTEGER || code->expr1->rank))
- gfc_error ("TEAM NUMBER argument to FORM TEAM at %L must be "
- "a scalar INTEGER", &code->expr1->where);
- check_team (code->expr2, "FORM TEAM");
+ resolve_form_team (code);
break;
case EXEC_CHANGE_TEAM:
- check_team (code->expr1, "CHANGE TEAM");
+ resolve_change_team (code);
break;
case EXEC_END_TEAM:
+ resolve_end_team (code);
break;
case EXEC_SYNC_TEAM:
- check_team (code->expr1, "SYNC TEAM");
+ resolve_sync_team (code);
break;
case EXEC_ENTRY: