OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / gcc / fortran / array.c
index 3ffc397..d4e520b 100644 (file)
@@ -64,12 +64,13 @@ gfc_copy_array_ref (gfc_array_ref *src)
 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;
 
@@ -222,19 +223,48 @@ coarray:
 
   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;
        }
     }
@@ -265,7 +295,7 @@ gfc_free_array_spec (gfc_array_spec *as)
       gfc_free_expr (as->upper[i]);
     }
 
-  gfc_free (as);
+  free (as);
 }
 
 
@@ -282,10 +312,14 @@ resolve_array_bound (gfc_expr *e, int check_constant)
       || 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;
     }
 
@@ -415,16 +449,8 @@ gfc_match_array_spec (gfc_array_spec **asp, bool match_dim, bool match_codim)
   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;
@@ -441,6 +467,12 @@ gfc_match_array_spec (gfc_array_spec **asp, bool match_dim, bool match_codim)
       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)
@@ -453,6 +485,15 @@ gfc_match_array_spec (gfc_array_spec **asp, bool match_dim, bool match_codim)
          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)
              {
@@ -491,6 +532,12 @@ gfc_match_array_spec (gfc_array_spec **asp, bool match_dim, bool match_codim)
            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;
          }
@@ -535,6 +582,13 @@ coarray:
       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++;
@@ -548,6 +602,7 @@ coarray:
       else
        switch (as->cotype)
          { /* See how current spec meshes with the existing.  */
+           case AS_IMPLIED_SHAPE:
            case AS_UNKNOWN:
              goto cleanup;
 
@@ -602,7 +657,7 @@ coarray:
          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);
@@ -715,7 +770,7 @@ gfc_set_array_spec (gfc_symbol *sym, gfc_array_spec *as, locus *error_loc)
        }
     }
 
-  gfc_free (as);
+  free (as);
   return SUCCESS;
 }
 
@@ -999,6 +1054,13 @@ gfc_match_array_constructor (gfc_expr **result)
          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;
+           }
        }
     }
 
@@ -1185,7 +1247,7 @@ gfc_check_iter_variable (gfc_expr *expr)
 
   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;
 
@@ -1266,6 +1328,7 @@ typedef struct
 
   mpz_t *offset;
   gfc_component *component;
+  mpz_t *repeat;
 
   gfc_try (*expand_work_function) (gfc_expr *);
 }
@@ -1500,6 +1563,7 @@ expand_constructor (gfc_constructor_base base)
          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;
@@ -1545,7 +1609,7 @@ gfc_get_array_element (gfc_expr *array, int element)
    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;
@@ -1557,6 +1621,15 @@ gfc_expand_constructor (gfc_expr *e)
   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;
     }
 
@@ -1798,7 +1871,7 @@ got_charlen:
              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);
            }
@@ -1909,10 +1982,11 @@ spec_size (gfc_array_spec *as, mpz_t *result)
 }
 
 
-/* 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;
@@ -1985,6 +2059,15 @@ gfc_ref_dimen_size (gfc_array_ref *ar, int dimen, mpz_t *result)
        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);
@@ -2009,7 +2092,7 @@ ref_size (gfc_array_ref *ar, mpz_t *result)
 
   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;
@@ -2034,6 +2117,9 @@ gfc_array_dimen_size (gfc_expr *array, int dimen, mpz_t *result)
   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");
 
@@ -2055,7 +2141,7 @@ gfc_array_dimen_size (gfc_expr *array, int dimen, mpz_t *result)
                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);
            }
        }
 
@@ -2112,6 +2198,9 @@ gfc_array_size (gfc_expr *array, mpz_t *result)
   int i;
   gfc_try t;
 
+  if (array->ts.type == BT_CLASS)
+    return FAILURE;
+
   switch (array->expr_type)
     {
     case EXPR_ARRAY:
@@ -2191,7 +2280,7 @@ gfc_array_ref_shape (gfc_array_ref *ar, mpz_t *shape)
        {
          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++;
            }
@@ -2204,9 +2293,7 @@ gfc_array_ref_shape (gfc_array_ref *ar, mpz_t *shape)
     }
 
 cleanup:
-  for (d--; d >= 0; d--)
-    mpz_clear (shape[d]);
-
+  gfc_clear_shape (shape, d);
   return FAILURE;
 }
 
@@ -2221,8 +2308,7 @@ gfc_find_array_ref (gfc_expr *e)
 
   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)