static match
match_subscript (gfc_array_ref *ar, int init, bool match_star)
{
- match m;
+ match m = MATCH_ERROR;
bool star = false;
int i;
i = ar->dimen + ar->codimen;
+ gfc_gobble_whitespace ();
ar->c_where[i] = gfc_current_locus;
ar->start[i] = ar->end[i] = ar->stride[i] = NULL;
for (ar->codimen = 0; ar->codimen + ar->dimen < GFC_MAX_DIMENSIONS; ar->codimen++)
{
- m = match_subscript (ar, init, ar->codimen == (corank - 1));
+ m = match_subscript (ar, init, true);
if (m == MATCH_ERROR)
return MATCH_ERROR;
if (gfc_match_char (']') == MATCH_YES)
{
ar->codimen++;
+ if (ar->codimen < corank)
+ {
+ gfc_error ("Too few codimensions at %C, expected %d not %d",
+ corank, ar->codimen);
+ return MATCH_ERROR;
+ }
+ if (ar->codimen > corank)
+ {
+ gfc_error ("Too many codimensions at %C, expected %d not %d",
+ corank, ar->codimen);
+ return MATCH_ERROR;
+ }
return MATCH_YES;
}
if (gfc_match_char (',') != MATCH_YES)
{
- gfc_error ("Invalid form of coarray reference at %C");
+ if (gfc_match_char ('*') == MATCH_YES)
+ gfc_error ("Unexpected '*' for codimension %d of %d at %C",
+ ar->codimen + 1, corank);
+ else
+ gfc_error ("Invalid form of coarray reference at %C");
+ return MATCH_ERROR;
+ }
+ else if (ar->dimen_type[ar->codimen + ar->dimen] == DIMEN_STAR)
+ {
+ gfc_error ("Unexpected '*' for codimension %d of %d at %C",
+ ar->codimen + 1, corank);
+ return MATCH_ERROR;
+ }
+
+ if (ar->codimen >= corank)
+ {
+ gfc_error ("Invalid codimension %d at %C, only %d codimensions exist",
+ ar->codimen + 1, corank);
return MATCH_ERROR;
}
}
gfc_free_expr (as->upper[i]);
}
- gfc_free (as);
+ free (as);
}
|| gfc_specification_expr (e) == FAILURE)
return FAILURE;
- if (check_constant && gfc_is_constant_expr (e) == 0)
+ if (check_constant && !gfc_is_constant_expr (e))
{
- gfc_error ("Variable '%s' at %L in this context must be constant",
- e->symtree->n.sym->name, &e->where);
+ if (e->expr_type == EXPR_VARIABLE)
+ gfc_error ("Variable '%s' at %L in this context must be constant",
+ e->symtree->n.sym->name, &e->where);
+ else
+ gfc_error ("Expression at %L in this context must be constant",
+ &e->where);
return FAILURE;
}
array_type current_type;
gfc_array_spec *as;
int i;
-
- as = gfc_get_array_spec ();
- as->corank = 0;
- as->rank = 0;
- for (i = 0; i < GFC_MAX_DIMENSIONS; i++)
- {
- as->lower[i] = NULL;
- as->upper[i] = NULL;
- }
+ as = gfc_get_array_spec ();
if (!match_dim)
goto coarray;
as->rank++;
current_type = match_array_element_spec (as);
+ /* Note that current_type == AS_ASSUMED_SIZE for both assumed-size
+ and implied-shape specifications. If the rank is at least 2, we can
+ distinguish between them. But for rank 1, we currently return
+ ASSUMED_SIZE; this gets adjusted later when we know for sure
+ whether the symbol parsed is a PARAMETER or not. */
+
if (as->rank == 1)
{
if (current_type == AS_UNKNOWN)
case AS_UNKNOWN:
goto cleanup;
+ case AS_IMPLIED_SHAPE:
+ if (current_type != AS_ASSUMED_SHAPE)
+ {
+ gfc_error ("Bad array specification for implied-shape"
+ " array at %C");
+ goto cleanup;
+ }
+ break;
+
case AS_EXPLICIT:
if (current_type == AS_ASSUMED_SIZE)
{
goto cleanup;
case AS_ASSUMED_SIZE:
+ if (as->rank == 2 && current_type == AS_ASSUMED_SIZE)
+ {
+ as->type = AS_IMPLIED_SHAPE;
+ break;
+ }
+
gfc_error ("Bad specification for assumed size array at %C");
goto cleanup;
}
goto cleanup;
}
+ if (as->rank >= GFC_MAX_DIMENSIONS)
+ {
+ gfc_error ("Array specification at %C has more than %d "
+ "dimensions", GFC_MAX_DIMENSIONS);
+ goto cleanup;
+ }
+
for (;;)
{
as->corank++;
else
switch (as->cotype)
{ /* See how current spec meshes with the existing. */
+ case AS_IMPLIED_SHAPE:
case AS_UNKNOWN:
goto cleanup;
goto cleanup;
}
- if (as->corank >= GFC_MAX_DIMENSIONS)
+ if (as->rank + as->corank >= GFC_MAX_DIMENSIONS)
{
gfc_error ("Array specification at %C has more than %d "
"dimensions", GFC_MAX_DIMENSIONS);
}
}
- gfc_free (as);
+ free (as);
return SUCCESS;
}
if (gfc_notify_std (GFC_STD_F2003, "Fortran 2003: Array constructor "
"including type specification at %C") == FAILURE)
goto cleanup;
+
+ if (ts.deferred)
+ {
+ gfc_error ("Type-spec at %L cannot contain a deferred "
+ "type parameter", &where);
+ goto cleanup;
+ }
}
}
sym = expr->symtree->n.sym;
- for (c = base; c; c = c->previous)
+ for (c = base; c && c->iterator; c = c->previous)
if (sym == c->iterator->var->symtree->n.sym)
return SUCCESS;
mpz_t *offset;
gfc_component *component;
+ mpz_t *repeat;
gfc_try (*expand_work_function) (gfc_expr *);
}
return FAILURE;
}
current_expand.offset = &c->offset;
+ current_expand.repeat = &c->repeat;
current_expand.component = c->n.component;
if (current_expand.expand_work_function (e) == FAILURE)
return FAILURE;
constructor if they are small enough. */
gfc_try
-gfc_expand_constructor (gfc_expr *e)
+gfc_expand_constructor (gfc_expr *e, bool fatal)
{
expand_info expand_save;
gfc_expr *f;
if (f != NULL)
{
gfc_free_expr (f);
+ if (fatal)
+ {
+ gfc_error ("The number of elements in the array constructor "
+ "at %L requires an increase of the allowed %d "
+ "upper limit. See -fmax-array-constructor "
+ "option", &e->where,
+ gfc_option.flag_max_array_constructor);
+ return FAILURE;
+ }
return SUCCESS;
}
has_ts = (expr->ts.u.cl && expr->ts.u.cl->length_from_typespec);
if (! cl
- || (current_length != -1 && current_length < found_length))
+ || (current_length != -1 && current_length != found_length))
gfc_set_constant_character_len (found_length, p->expr,
has_ts ? -1 : found_length);
}
}
-/* Get the number of elements in an array section. */
+/* Get the number of elements in an array section. Optionally, also supply
+ the end value. */
gfc_try
-gfc_ref_dimen_size (gfc_array_ref *ar, int dimen, mpz_t *result)
+gfc_ref_dimen_size (gfc_array_ref *ar, int dimen, mpz_t *result, mpz_t *end)
{
mpz_t upper, lower, stride;
gfc_try t;
mpz_set_ui (*result, 0);
t = SUCCESS;
+ if (end)
+ {
+ mpz_init (*end);
+
+ mpz_sub_ui (*end, *result, 1UL);
+ mpz_mul (*end, *end, stride);
+ mpz_add (*end, *end, lower);
+ }
+
cleanup:
mpz_clear (upper);
mpz_clear (lower);
for (d = 0; d < ar->dimen; d++)
{
- if (gfc_ref_dimen_size (ar, d, &size) == FAILURE)
+ if (gfc_ref_dimen_size (ar, d, &size, NULL) == FAILURE)
{
mpz_clear (*result);
return FAILURE;
gfc_ref *ref;
int i;
+ if (array->ts.type == BT_CLASS)
+ return FAILURE;
+
if (dimen < 0 || array == NULL || dimen > array->rank - 1)
gfc_internal_error ("gfc_array_dimen_size(): Bad dimension");
if (ref->u.ar.dimen_type[i] != DIMEN_ELEMENT)
dimen--;
- return gfc_ref_dimen_size (&ref->u.ar, i - 1, result);
+ return gfc_ref_dimen_size (&ref->u.ar, i - 1, result, NULL);
}
}
int i;
gfc_try t;
+ if (array->ts.type == BT_CLASS)
+ return FAILURE;
+
switch (array->expr_type)
{
case EXPR_ARRAY:
{
if (ar->dimen_type[i] != DIMEN_ELEMENT)
{
- if (gfc_ref_dimen_size (ar, i, &shape[d]) == FAILURE)
+ if (gfc_ref_dimen_size (ar, i, &shape[d], NULL) == FAILURE)
goto cleanup;
d++;
}
}
cleanup:
- for (d--; d >= 0; d--)
- mpz_clear (shape[d]);
-
+ gfc_clear_shape (shape, d);
return FAILURE;
}
for (ref = e->ref; ref; ref = ref->next)
if (ref->type == REF_ARRAY
- && (ref->u.ar.type == AR_FULL || ref->u.ar.type == AR_SECTION
- || (ref->u.ar.type == AR_ELEMENT && ref->u.ar.dimen == 0)))
+ && (ref->u.ar.type == AR_FULL || ref->u.ar.type == AR_SECTION))
break;
if (ref == NULL)