/* Array things
   Copyright (C) 2000-2022 Free Software Foundation, Inc.
   Contributed by Andy Vaught

This file is part of GCC.

GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.

GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.

You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3.  If not see
<http://www.gnu.org/licenses/>.  */

#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "options.h"
#include "gfortran.h"
#include "parse.h"
#include "match.h"
#include "constructor.h"

/**************** Array reference matching subroutines *****************/

/* Copy an array reference structure.  */

gfc_array_ref *
gfc_copy_array_ref (gfc_array_ref *src)
{
  gfc_array_ref *dest;
  int i;

  if (src == NULL)
    return NULL;

  dest = gfc_get_array_ref ();

  *dest = *src;

  for (i = 0; i < GFC_MAX_DIMENSIONS; i++)
    {
      dest->start[i] = gfc_copy_expr (src->start[i]);
      dest->end[i] = gfc_copy_expr (src->end[i]);
      dest->stride[i] = gfc_copy_expr (src->stride[i]);
    }

  return dest;
}


/* Match a single dimension of an array reference.  This can be a
   single element or an array section.  Any modifications we've made
   to the ar structure are cleaned up by the caller.  If the init
   is set, we require the subscript to be a valid initialization
   expression.  */

static match
match_subscript (gfc_array_ref *ar, int init, bool match_star)
{
  match m = MATCH_ERROR;
  bool star = false;
  int i;
  bool saw_boz = false;

  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;

  /* We can't be sure of the difference between DIMEN_ELEMENT and
     DIMEN_VECTOR until we know the type of the element itself at
     resolution time.  */

  ar->dimen_type[i] = DIMEN_UNKNOWN;

  if (gfc_match_char (':') == MATCH_YES)
    goto end_element;

  /* Get start element.  */
  if (match_star && (m = gfc_match_char ('*')) == MATCH_YES)
    star = true;

  if (!star && init)
    m = gfc_match_init_expr (&ar->start[i]);
  else if (!star)
    m = gfc_match_expr (&ar->start[i]);

  if (ar->start[i] && ar->start[i]->ts.type == BT_BOZ)
    {
      gfc_error ("Invalid BOZ literal constant used in subscript at %C");
      saw_boz = true;
    }

  if (m == MATCH_NO)
    gfc_error ("Expected array subscript at %C");
  if (m != MATCH_YES)
    return MATCH_ERROR;

  if (gfc_match_char (':') == MATCH_NO)
    goto matched;

  if (star)
    {
      gfc_error ("Unexpected %<*%> in coarray subscript at %C");
      return MATCH_ERROR;
    }

  /* Get an optional end element.  Because we've seen the colon, we
     definitely have a range along this dimension.  */
end_element:
  ar->dimen_type[i] = DIMEN_RANGE;

  if (match_star && (m = gfc_match_char ('*')) == MATCH_YES)
    star = true;
  else if (init)
    m = gfc_match_init_expr (&ar->end[i]);
  else
    m = gfc_match_expr (&ar->end[i]);

  if (ar->end[i] && ar->end[i]->ts.type == BT_BOZ)
    {
      gfc_error ("Invalid BOZ literal constant used in subscript at %C");
      saw_boz = true;
    }

  if (m == MATCH_ERROR)
    return MATCH_ERROR;

  if (star && ar->start[i] == NULL)
    {
      gfc_error ("Missing lower bound in assumed size "
		 "coarray specification at %C");
      return MATCH_ERROR;
    }

  /* See if we have an optional stride.  */
  if (gfc_match_char (':') == MATCH_YES)
    {
      if (star)
	{
	  gfc_error ("Strides not allowed in coarray subscript at %C");
	  return MATCH_ERROR;
	}

      m = init ? gfc_match_init_expr (&ar->stride[i])
	       : gfc_match_expr (&ar->stride[i]);

      if (ar->stride[i] && ar->stride[i]->ts.type == BT_BOZ)
	{
	  gfc_error ("Invalid BOZ literal constant used in subscript at %C");
	  saw_boz = true;
	}

      if (m == MATCH_NO)
	gfc_error ("Expected array subscript stride at %C");
      if (m != MATCH_YES)
	return MATCH_ERROR;
    }

matched:
  if (star)
    ar->dimen_type[i] = DIMEN_STAR;

  return (saw_boz ? MATCH_ERROR : MATCH_YES);
}


/* Match an array reference, whether it is the whole array or particular
   elements or a section.  If init is set, the reference has to consist
   of init expressions.  */

match
gfc_match_array_ref (gfc_array_ref *ar, gfc_array_spec *as, int init,
		     int corank)
{
  match m;
  bool matched_bracket = false;
  gfc_expr *tmp;
  bool stat_just_seen = false;
  bool team_just_seen = false;

  memset (ar, '\0', sizeof (*ar));

  ar->where = gfc_current_locus;
  ar->as = as;
  ar->type = AR_UNKNOWN;

  if (gfc_match_char ('[') == MATCH_YES)
    {
       matched_bracket = true;
       goto coarray;
    }

  if (gfc_match_char ('(') != MATCH_YES)
    {
      ar->type = AR_FULL;
      ar->dimen = 0;
      return MATCH_YES;
    }

  for (ar->dimen = 0; ar->dimen < GFC_MAX_DIMENSIONS; ar->dimen++)
    {
      m = match_subscript (ar, init, false);
      if (m == MATCH_ERROR)
	return MATCH_ERROR;

      if (gfc_match_char (')') == MATCH_YES)
	{
	  ar->dimen++;
	  goto coarray;
	}

      if (gfc_match_char (',') != MATCH_YES)
	{
	  gfc_error ("Invalid form of array reference at %C");
	  return MATCH_ERROR;
	}
    }

  if (ar->dimen >= 7
      && !gfc_notify_std (GFC_STD_F2008,
			  "Array reference at %C has more than 7 dimensions"))
    return MATCH_ERROR;

  gfc_error ("Array reference at %C cannot have more than %d dimensions",
	     GFC_MAX_DIMENSIONS);
  return MATCH_ERROR;

coarray:
  if (!matched_bracket && gfc_match_char ('[') != MATCH_YES)
    {
      if (ar->dimen > 0)
	return MATCH_YES;
      else
	return MATCH_ERROR;
    }

  if (flag_coarray == GFC_FCOARRAY_NONE)
    {
      gfc_fatal_error ("Coarrays disabled at %C, use %<-fcoarray=%> to enable");
      return MATCH_ERROR;
    }

  if (corank == 0)
    {
	gfc_error ("Unexpected coarray designator at %C");
	return MATCH_ERROR;
    }

  ar->stat = NULL;

  for (ar->codimen = 0; ar->codimen + ar->dimen < GFC_MAX_DIMENSIONS; ar->codimen++)
    {
      m = match_subscript (ar, init, true);
      if (m == MATCH_ERROR)
	return MATCH_ERROR;

      team_just_seen = false;
      stat_just_seen = false;
      if (gfc_match (" , team = %e", &tmp) == MATCH_YES && ar->team == NULL)
	{
	  ar->team = tmp;
	  team_just_seen = true;
	}

      if (ar->team && !team_just_seen)
	{
	  gfc_error ("TEAM= attribute in %C misplaced");
	  return MATCH_ERROR;
	}

      if (gfc_match (" , stat = %e",&tmp) == MATCH_YES && ar->stat == NULL)
	{
	  ar->stat = tmp;
	  stat_just_seen = true;
	}

      if (ar->stat && !stat_just_seen)
	{
	  gfc_error ("STAT= attribute in %C misplaced");
	  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)
	{
	  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_error ("Array reference at %C cannot have more than %d dimensions",
	     GFC_MAX_DIMENSIONS);
  return MATCH_ERROR;

}


/************** Array specification matching subroutines ***************/

/* Free all of the expressions associated with array bounds
   specifications.  */

void
gfc_free_array_spec (gfc_array_spec *as)
{
  int i;

  if (as == NULL)
    return;

  if (as->corank == 0)
    {
      for (i = 0; i < as->rank; i++)
	{
	  gfc_free_expr (as->lower[i]);
	  gfc_free_expr (as->upper[i]);
	}
    }
  else
    {
      int n = as->rank + as->corank - (as->cotype == AS_EXPLICIT ? 1 : 0);
      for (i = 0; i < n; i++)
	{
	  gfc_free_expr (as->lower[i]);
	  gfc_free_expr (as->upper[i]);
	}
    }

  free (as);
}


/* Take an array bound, resolves the expression, that make up the
   shape and check associated constraints.  */

static bool
resolve_array_bound (gfc_expr *e, int check_constant)
{
  if (e == NULL)
    return true;

  if (!gfc_resolve_expr (e)
      || !gfc_specification_expr (e))
    return false;

  if (check_constant && !gfc_is_constant_expr (e))
    {
      if (e->expr_type == EXPR_VARIABLE)
	gfc_error ("Variable %qs 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 false;
    }

  return true;
}


/* Takes an array specification, resolves the expressions that make up
   the shape and make sure everything is integral.  */

bool
gfc_resolve_array_spec (gfc_array_spec *as, int check_constant)
{
  gfc_expr *e;
  int i;

  if (as == NULL)
    return true;

  if (as->resolved)
    return true;

  for (i = 0; i < as->rank + as->corank; i++)
    {
      if (i == GFC_MAX_DIMENSIONS)
	return false;

      e = as->lower[i];
      if (!resolve_array_bound (e, check_constant))
	return false;

      e = as->upper[i];
      if (!resolve_array_bound (e, check_constant))
	return false;

      if ((as->lower[i] == NULL) || (as->upper[i] == NULL))
	continue;

      /* If the size is negative in this dimension, set it to zero.  */
      if (as->lower[i]->expr_type == EXPR_CONSTANT
	    && as->upper[i]->expr_type == EXPR_CONSTANT
	    && mpz_cmp (as->upper[i]->value.integer,
			as->lower[i]->value.integer) < 0)
	{
	  gfc_free_expr (as->upper[i]);
	  as->upper[i] = gfc_copy_expr (as->lower[i]);
	  mpz_sub_ui (as->upper[i]->value.integer,
		      as->upper[i]->value.integer, 1);
	}
    }

  as->resolved = true;

  return true;
}


/* Match a single array element specification.  The return values as
   well as the upper and lower bounds of the array spec are filled
   in according to what we see on the input.  The caller makes sure
   individual specifications make sense as a whole.


	Parsed       Lower   Upper  Returned
	------------------------------------
	  :           NULL    NULL   AS_DEFERRED (*)
	  x            1       x     AS_EXPLICIT
	  x:           x      NULL   AS_ASSUMED_SHAPE
	  x:y          x       y     AS_EXPLICIT
	  x:*          x      NULL   AS_ASSUMED_SIZE
	  *            1      NULL   AS_ASSUMED_SIZE

  (*) For non-pointer dummy arrays this is AS_ASSUMED_SHAPE.  This
  is fixed during the resolution of formal interfaces.

   Anything else AS_UNKNOWN.  */

static array_type
match_array_element_spec (gfc_array_spec *as)
{
  gfc_expr **upper, **lower;
  match m;
  int rank;

  rank = as->rank == -1 ? 0 : as->rank;
  lower = &as->lower[rank + as->corank - 1];
  upper = &as->upper[rank + as->corank - 1];

  if (gfc_match_char ('*') == MATCH_YES)
    {
      *lower = gfc_get_int_expr (gfc_default_integer_kind, NULL, 1);
      return AS_ASSUMED_SIZE;
    }

  if (gfc_match_char (':') == MATCH_YES)
    return AS_DEFERRED;

  m = gfc_match_expr (upper);
  if (m == MATCH_NO)
    gfc_error ("Expected expression in array specification at %C");
  if (m != MATCH_YES)
    return AS_UNKNOWN;
  if (!gfc_expr_check_typed (*upper, gfc_current_ns, false))
    return AS_UNKNOWN;

  gfc_try_simplify_expr (*upper, 0);

  if (((*upper)->expr_type == EXPR_CONSTANT
	&& (*upper)->ts.type != BT_INTEGER) ||
      ((*upper)->expr_type == EXPR_FUNCTION
	&& (*upper)->ts.type == BT_UNKNOWN
	&& (*upper)->symtree
	&& strcmp ((*upper)->symtree->name, "null") == 0))
    {
      gfc_error ("Expecting a scalar INTEGER expression at %C, found %s",
		 gfc_basic_typename ((*upper)->ts.type));
      return AS_UNKNOWN;
    }

  if (gfc_match_char (':') == MATCH_NO)
    {
      *lower = gfc_get_int_expr (gfc_default_integer_kind, NULL, 1);
      return AS_EXPLICIT;
    }

  *lower = *upper;
  *upper = NULL;

  if (gfc_match_char ('*') == MATCH_YES)
    return AS_ASSUMED_SIZE;

  m = gfc_match_expr (upper);
  if (m == MATCH_ERROR)
    return AS_UNKNOWN;
  if (m == MATCH_NO)
    return AS_ASSUMED_SHAPE;
  if (!gfc_expr_check_typed (*upper, gfc_current_ns, false))
    return AS_UNKNOWN;

  gfc_try_simplify_expr (*upper, 0);

  if (((*upper)->expr_type == EXPR_CONSTANT
	&& (*upper)->ts.type != BT_INTEGER) ||
      ((*upper)->expr_type == EXPR_FUNCTION
	&& (*upper)->ts.type == BT_UNKNOWN
	&& (*upper)->symtree
	&& strcmp ((*upper)->symtree->name, "null") == 0))
    {
      gfc_error ("Expecting a scalar INTEGER expression at %C, found %s",
		 gfc_basic_typename ((*upper)->ts.type));
      return AS_UNKNOWN;
    }

  return AS_EXPLICIT;
}


/* Matches an array specification, incidentally figuring out what sort
   it is.  Match either a normal array specification, or a coarray spec
   or both.  Optionally allow [:] for coarrays.  */

match
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 ();

  if (!match_dim)
    goto coarray;

  if (gfc_match_char ('(') != MATCH_YES)
    {
      if (!match_codim)
	goto done;
      goto coarray;
    }

  if (gfc_match (" .. )") == MATCH_YES)
    {
      as->type = AS_ASSUMED_RANK;
      as->rank = -1;

      if (!gfc_notify_std (GFC_STD_F2018, "Assumed-rank array at %C"))
	goto cleanup;

      if (!match_codim)
	goto done;
      goto coarray;
    }

  for (;;)
    {
      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)
	    goto cleanup;
	  as->type = current_type;
	}
      else
	switch (as->type)
	  {		/* See how current spec meshes with the existing.  */
	  case AS_UNKNOWN:
	    goto cleanup;

	  case AS_IMPLIED_SHAPE:
	    if (current_type != AS_ASSUMED_SIZE)
	      {
		gfc_error ("Bad array specification for implied-shape"
			   " array at %C");
		goto cleanup;
	      }
	    break;

	  case AS_EXPLICIT:
	    if (current_type == AS_ASSUMED_SIZE)
	      {
		as->type = AS_ASSUMED_SIZE;
		break;
	      }

	    if (current_type == AS_EXPLICIT)
	      break;

	    gfc_error ("Bad array specification for an explicitly shaped "
		       "array at %C");

	    goto cleanup;

	  case AS_ASSUMED_SHAPE:
	    if ((current_type == AS_ASSUMED_SHAPE)
		|| (current_type == AS_DEFERRED))
	      break;

	    gfc_error ("Bad array specification for assumed shape "
		       "array at %C");
	    goto cleanup;

	  case AS_DEFERRED:
	    if (current_type == AS_DEFERRED)
	      break;

	    if (current_type == AS_ASSUMED_SHAPE)
	      {
		as->type = AS_ASSUMED_SHAPE;
		break;
	      }

	    gfc_error ("Bad specification for deferred shape array at %C");
	    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;

	  case AS_ASSUMED_RANK:
	    gcc_unreachable ();
	  }

      if (gfc_match_char (')') == MATCH_YES)
	break;

      if (gfc_match_char (',') != MATCH_YES)
	{
	  gfc_error ("Expected another dimension in array declaration at %C");
	  goto cleanup;
	}

      if (as->rank + as->corank >= GFC_MAX_DIMENSIONS)
	{
	  gfc_error ("Array specification at %C has more than %d dimensions",
		     GFC_MAX_DIMENSIONS);
	  goto cleanup;
	}

      if (as->corank + as->rank >= 7
	  && !gfc_notify_std (GFC_STD_F2008, "Array specification at %C "
			      "with more than 7 dimensions"))
	goto cleanup;
    }

  if (!match_codim)
    goto done;

coarray:
  if (gfc_match_char ('[')  != MATCH_YES)
    goto done;

  if (!gfc_notify_std (GFC_STD_F2008, "Coarray declaration at %C"))
    goto cleanup;

  if (flag_coarray == GFC_FCOARRAY_NONE)
    {
      gfc_fatal_error ("Coarrays disabled at %C, use %<-fcoarray=%> to enable");
      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++;
      current_type = match_array_element_spec (as);

      if (current_type == AS_UNKNOWN)
	goto cleanup;

      if (as->corank == 1)
	as->cotype = current_type;
      else
	switch (as->cotype)
	  { /* See how current spec meshes with the existing.  */
	    case AS_IMPLIED_SHAPE:
	    case AS_UNKNOWN:
	      goto cleanup;

	    case AS_EXPLICIT:
	      if (current_type == AS_ASSUMED_SIZE)
		{
		  as->cotype = AS_ASSUMED_SIZE;
		  break;
		}

	      if (current_type == AS_EXPLICIT)
		break;

	      gfc_error ("Bad array specification for an explicitly "
			 "shaped array at %C");

	      goto cleanup;

	    case AS_ASSUMED_SHAPE:
	      if ((current_type == AS_ASSUMED_SHAPE)
		  || (current_type == AS_DEFERRED))
		break;

	      gfc_error ("Bad array specification for assumed shape "
			 "array at %C");
	      goto cleanup;

	    case AS_DEFERRED:
	      if (current_type == AS_DEFERRED)
		break;

	      if (current_type == AS_ASSUMED_SHAPE)
		{
		  as->cotype = AS_ASSUMED_SHAPE;
		  break;
		}

	      gfc_error ("Bad specification for deferred shape array at %C");
	      goto cleanup;

	    case AS_ASSUMED_SIZE:
	      gfc_error ("Bad specification for assumed size array at %C");
	      goto cleanup;

	    case AS_ASSUMED_RANK:
	      gcc_unreachable ();
	  }

      if (gfc_match_char (']') == MATCH_YES)
	break;

      if (gfc_match_char (',') != MATCH_YES)
	{
	  gfc_error ("Expected another dimension in array declaration at %C");
	  goto cleanup;
	}

      if (as->rank + as->corank >= GFC_MAX_DIMENSIONS)
	{
	  gfc_error ("Array specification at %C has more than %d "
		     "dimensions", GFC_MAX_DIMENSIONS);
	  goto cleanup;
	}
    }

  if (current_type == AS_EXPLICIT)
    {
      gfc_error ("Upper bound of last coarray dimension must be %<*%> at %C");
      goto cleanup;
    }

  if (as->cotype == AS_ASSUMED_SIZE)
    as->cotype = AS_EXPLICIT;

  if (as->rank == 0)
    as->type = as->cotype;

done:
  if (as->rank == 0 && as->corank == 0)
    {
      *asp = NULL;
      gfc_free_array_spec (as);
      return MATCH_NO;
    }

  /* If a lower bounds of an assumed shape array is blank, put in one.  */
  if (as->type == AS_ASSUMED_SHAPE)
    {
      for (i = 0; i < as->rank + as->corank; i++)
	{
	  if (as->lower[i] == NULL)
	    as->lower[i] = gfc_get_int_expr (gfc_default_integer_kind, NULL, 1);
	}
    }

  *asp = as;

  return MATCH_YES;

cleanup:
  /* Something went wrong.  */
  gfc_free_array_spec (as);
  return MATCH_ERROR;
}

/* Given a symbol and an array specification, modify the symbol to
   have that array specification.  The error locus is needed in case
   something goes wrong.  On failure, the caller must free the spec.  */

bool
gfc_set_array_spec (gfc_symbol *sym, gfc_array_spec *as, locus *error_loc)
{
  int i;
  symbol_attribute *attr;
  
  if (as == NULL)
    return true;

  /* If the symbol corresponds to a submodule module procedure the array spec is
     already set, so do not attempt to set it again here. */
  attr = &sym->attr;
  if (gfc_submodule_procedure(attr))
    return true;
  
  if (as->rank
      && !gfc_add_dimension (&sym->attr, sym->name, error_loc))
    return false;

  if (as->corank
      && !gfc_add_codimension (&sym->attr, sym->name, error_loc))
    return false;

  if (sym->as == NULL)
    {
      sym->as = as;
      return true;
    }

  if ((sym->as->type == AS_ASSUMED_RANK && as->corank)
      || (as->type == AS_ASSUMED_RANK && sym->as->corank))
    {
      gfc_error ("The assumed-rank array %qs at %L shall not have a "
		 "codimension", sym->name, error_loc);
      return false;
    }

  /* Check F2018:C822.  */
  if (sym->as->rank + sym->as->corank > GFC_MAX_DIMENSIONS)
    goto too_many;

  if (as->corank)
    {
      sym->as->cotype = as->cotype;
      sym->as->corank = as->corank;
      /* Check F2018:C822.  */
      if (sym->as->rank + sym->as->corank > GFC_MAX_DIMENSIONS)
	goto too_many;

      for (i = 0; i < as->corank; i++)
	{
	  sym->as->lower[sym->as->rank + i] = as->lower[i];
	  sym->as->upper[sym->as->rank + i] = as->upper[i];
	}
    }
  else
    {
      /* The "sym" has no rank (checked via gfc_add_dimension). Thus
	 the dimension is added - but first the codimensions (if existing
	 need to be shifted to make space for the dimension.  */
      gcc_assert (as->corank == 0 && sym->as->rank == 0);

      sym->as->rank = as->rank;
      sym->as->type = as->type;
      sym->as->cray_pointee = as->cray_pointee;
      sym->as->cp_was_assumed = as->cp_was_assumed;

      /* Check F2018:C822.  */
      if (sym->as->rank + sym->as->corank > GFC_MAX_DIMENSIONS)
	goto too_many;

      for (i = sym->as->corank - 1; i >= 0; i--)
	{
	  sym->as->lower[as->rank + i] = sym->as->lower[i];
	  sym->as->upper[as->rank + i] = sym->as->upper[i];
	}
      for (i = 0; i < as->rank; i++)
	{
	  sym->as->lower[i] = as->lower[i];
	  sym->as->upper[i] = as->upper[i];
	}
    }

  free (as);
  return true;

too_many:

  gfc_error ("rank + corank of %qs exceeds %d at %C", sym->name,
	     GFC_MAX_DIMENSIONS);
  return false;
}


/* Copy an array specification.  */

gfc_array_spec *
gfc_copy_array_spec (gfc_array_spec *src)
{
  gfc_array_spec *dest;
  int i;

  if (src == NULL)
    return NULL;

  dest = gfc_get_array_spec ();

  *dest = *src;

  for (i = 0; i < dest->rank + dest->corank; i++)
    {
      dest->lower[i] = gfc_copy_expr (dest->lower[i]);
      dest->upper[i] = gfc_copy_expr (dest->upper[i]);
    }

  return dest;
}


/* Returns nonzero if the two expressions are equal.
   We should not need to support more than constant values, as that’s what is
   allowed in derived type component array spec.  However, we may create types
   with non-constant array spec for dummy variable class container types, for
   which the _data component holds the array spec of the variable declaration.
   So we have to support non-constant bounds as well.  */

static bool
compare_bounds (gfc_expr *bound1, gfc_expr *bound2)
{
  if (bound1 == NULL || bound2 == NULL
      || bound1->ts.type != BT_INTEGER
      || bound2->ts.type != BT_INTEGER)
    gfc_internal_error ("gfc_compare_array_spec(): Array spec clobbered");

  /* What qualifies as identical bounds?  We could probably just check that the
     expressions are exact clones.  We avoid rewriting a specific comparison
     function and re-use instead the rather involved gfc_dep_compare_expr which
     is just a bit more permissive, as it can also detect identical values for
     some mismatching expressions (extra parenthesis, swapped operands, unary
     plus, etc).  It probably only makes a difference in corner cases.  */
  return gfc_dep_compare_expr (bound1, bound2) == 0;
}


/* Compares two array specifications.  They must be constant or deferred
   shape.  */

int
gfc_compare_array_spec (gfc_array_spec *as1, gfc_array_spec *as2)
{
  int i;

  if (as1 == NULL && as2 == NULL)
    return 1;

  if (as1 == NULL || as2 == NULL)
    return 0;

  if (as1->rank != as2->rank)
    return 0;

  if (as1->corank != as2->corank)
    return 0;

  if (as1->rank == 0)
    return 1;

  if (as1->type != as2->type)
    return 0;

  if (as1->type == AS_EXPLICIT)
    for (i = 0; i < as1->rank + as1->corank; i++)
      {
	if (!compare_bounds (as1->lower[i], as2->lower[i]))
	  return 0;

	if (!compare_bounds (as1->upper[i], as2->upper[i]))
	  return 0;
      }

  return 1;
}


/****************** Array constructor functions ******************/


/* Given an expression node that might be an array constructor and a
   symbol, make sure that no iterators in this or child constructors
   use the symbol as an implied-DO iterator.  Returns nonzero if a
   duplicate was found.  */

static int
check_duplicate_iterator (gfc_constructor_base base, gfc_symbol *master)
{
  gfc_constructor *c;
  gfc_expr *e;

  for (c = gfc_constructor_first (base); c; c = gfc_constructor_next (c))
    {
      e = c->expr;

      if (e->expr_type == EXPR_ARRAY
	  && check_duplicate_iterator (e->value.constructor, master))
	return 1;

      if (c->iterator == NULL)
	continue;

      if (c->iterator->var->symtree->n.sym == master)
	{
	  gfc_error ("DO-iterator %qs at %L is inside iterator of the "
		     "same name", master->name, &c->where);

	  return 1;
	}
    }

  return 0;
}


/* Forward declaration because these functions are mutually recursive.  */
static match match_array_cons_element (gfc_constructor_base *);

/* Match a list of array elements.  */

static match
match_array_list (gfc_constructor_base *result)
{
  gfc_constructor_base head;
  gfc_constructor *p;
  gfc_iterator iter;
  locus old_loc;
  gfc_expr *e;
  match m;
  int n;

  old_loc = gfc_current_locus;

  if (gfc_match_char ('(') == MATCH_NO)
    return MATCH_NO;

  memset (&iter, '\0', sizeof (gfc_iterator));
  head = NULL;

  m = match_array_cons_element (&head);
  if (m != MATCH_YES)
    goto cleanup;

  if (gfc_match_char (',') != MATCH_YES)
    {
      m = MATCH_NO;
      goto cleanup;
    }

  for (n = 1;; n++)
    {
      m = gfc_match_iterator (&iter, 0);
      if (m == MATCH_YES)
	break;
      if (m == MATCH_ERROR)
	goto cleanup;

      m = match_array_cons_element (&head);
      if (m == MATCH_ERROR)
	goto cleanup;
      if (m == MATCH_NO)
	{
	  if (n > 2)
	    goto syntax;
	  m = MATCH_NO;
	  goto cleanup;		/* Could be a complex constant */
	}

      if (gfc_match_char (',') != MATCH_YES)
	{
	  if (n > 2)
	    goto syntax;
	  m = MATCH_NO;
	  goto cleanup;
	}
    }

  if (gfc_match_char (')') != MATCH_YES)
    goto syntax;

  if (check_duplicate_iterator (head, iter.var->symtree->n.sym))
    {
      m = MATCH_ERROR;
      goto cleanup;
    }

  e = gfc_get_array_expr (BT_UNKNOWN, 0, &old_loc);
  e->value.constructor = head;

  p = gfc_constructor_append_expr (result, e, &gfc_current_locus);
  p->iterator = gfc_get_iterator ();
  *p->iterator = iter;

  return MATCH_YES;

syntax:
  gfc_error ("Syntax error in array constructor at %C");
  m = MATCH_ERROR;

cleanup:
  gfc_constructor_free (head);
  gfc_free_iterator (&iter, 0);
  gfc_current_locus = old_loc;
  return m;
}


/* Match a single element of an array constructor, which can be a
   single expression or a list of elements.  */

static match
match_array_cons_element (gfc_constructor_base *result)
{
  gfc_expr *expr;
  match m;

  m = match_array_list (result);
  if (m != MATCH_NO)
    return m;

  m = gfc_match_expr (&expr);
  if (m != MATCH_YES)
    return m;

  if (expr->ts.type == BT_BOZ)
    {
      gfc_error ("BOZ literal constant at %L cannot appear in an "
		 "array constructor", &expr->where);
      goto done;
    }

  if (expr->expr_type == EXPR_FUNCTION
      && expr->ts.type == BT_UNKNOWN
      && strcmp(expr->symtree->name, "null") == 0)
    {
      gfc_error ("NULL() at %C cannot appear in an array constructor");
      goto done;
    }

  gfc_constructor_append_expr (result, expr, &gfc_current_locus);
  return MATCH_YES;

done:
  gfc_free_expr (expr);
  return MATCH_ERROR;
}


/* Convert components of an array constructor to the type in ts.  */

static match
walk_array_constructor (gfc_typespec *ts, gfc_constructor_base head)
{
  gfc_constructor *c;
  gfc_expr *e;
  match m;

  for (c = gfc_constructor_first (head); c; c = gfc_constructor_next (c))
    {
      e = c->expr;
      if (e->expr_type == EXPR_ARRAY && e->ts.type == BT_UNKNOWN
	  && !e->ref && e->value.constructor)
	{
	  m = walk_array_constructor (ts, e->value.constructor);
	  if (m == MATCH_ERROR)
	    return m;
	}
      else if (!gfc_convert_type_warn (e, ts, 1, 1, true)
	       && e->ts.type != BT_UNKNOWN)
	return MATCH_ERROR;
    }
  return MATCH_YES;
}

/* Match an array constructor.  */

match
gfc_match_array_constructor (gfc_expr **result)
{
  gfc_constructor *c;
  gfc_constructor_base head;
  gfc_expr *expr;
  gfc_typespec ts;
  locus where;
  match m;
  const char *end_delim;
  bool seen_ts;

  head = NULL;
  seen_ts = false;

  if (gfc_match (" (/") == MATCH_NO)
    {
      if (gfc_match (" [") == MATCH_NO)
	return MATCH_NO;
      else
	{
	  if (!gfc_notify_std (GFC_STD_F2003, "[...] "
			       "style array constructors at %C"))
	    return MATCH_ERROR;
	  end_delim = " ]";
	}
    }
  else
    end_delim = " /)";

  where = gfc_current_locus;

  /* Try to match an optional "type-spec ::"  */
  gfc_clear_ts (&ts);
  m = gfc_match_type_spec (&ts);
  if (m == MATCH_YES)
    {
      seen_ts = (gfc_match (" ::") == MATCH_YES);

      if (seen_ts)
	{
	  if (!gfc_notify_std (GFC_STD_F2003, "Array constructor "
			       "including type specification at %C"))
	    goto cleanup;

	  if (ts.deferred)
	    {
	      gfc_error ("Type-spec at %L cannot contain a deferred "
			 "type parameter", &where);
	      goto cleanup;
	    }

	  if (ts.type == BT_CHARACTER
	      && ts.u.cl && !ts.u.cl->length && !ts.u.cl->length_from_typespec)
	    {
	      gfc_error ("Type-spec at %L cannot contain an asterisk for a "
			 "type parameter", &where);
	      goto cleanup;
	    }
	}
    }
  else if (m == MATCH_ERROR)
    goto cleanup;

  if (!seen_ts)
    gfc_current_locus = where;

  if (gfc_match (end_delim) == MATCH_YES)
    {
      if (seen_ts)
	goto done;
      else
	{
	  gfc_error ("Empty array constructor at %C is not allowed");
	  goto cleanup;
	}
    }

  for (;;)
    {
      m = match_array_cons_element (&head);
      if (m == MATCH_ERROR)
	goto cleanup;
      if (m == MATCH_NO)
	goto syntax;

      if (gfc_match_char (',') == MATCH_NO)
	break;
    }

  if (gfc_match (end_delim) == MATCH_NO)
    goto syntax;

done:
  /* Size must be calculated at resolution time.  */
  if (seen_ts)
    {
      expr = gfc_get_array_expr (ts.type, ts.kind, &where);
      expr->ts = ts;

      /* If the typespec is CHARACTER, check that array elements can
	 be converted.  See PR fortran/67803.  */
      if (ts.type == BT_CHARACTER)
	{
	  c = gfc_constructor_first (head);
	  for (; c; c = gfc_constructor_next (c))
	    {
	      if (gfc_numeric_ts (&c->expr->ts)
		  || c->expr->ts.type == BT_LOGICAL)
		{
		  gfc_error ("Incompatible typespec for array element at %L",
			     &c->expr->where);
		  return MATCH_ERROR;
		}

	      /* Special case null().  */
	      if (c->expr->expr_type == EXPR_FUNCTION
		  && c->expr->ts.type == BT_UNKNOWN
		  && strcmp (c->expr->symtree->name, "null") == 0)
		{
		  gfc_error ("Incompatible typespec for array element at %L",
			     &c->expr->where);
		  return MATCH_ERROR;
		}
	    }
	}

      /* Walk the constructor, and if possible, do type conversion for
	 numeric types.  */
      if (gfc_numeric_ts (&ts))
	{
	  m = walk_array_constructor (&ts, head);
	  if (m == MATCH_ERROR)
	    return m;
	}
    }
  else
    expr = gfc_get_array_expr (BT_UNKNOWN, 0, &where);

  expr->value.constructor = head;
  if (expr->ts.u.cl)
    expr->ts.u.cl->length_from_typespec = seen_ts;

  *result = expr;

  return MATCH_YES;

syntax:
  gfc_error ("Syntax error in array constructor at %C");

cleanup:
  gfc_constructor_free (head);
  return MATCH_ERROR;
}



/************** Check array constructors for correctness **************/

/* Given an expression, compare it's type with the type of the current
   constructor.  Returns nonzero if an error was issued.  The
   cons_state variable keeps track of whether the type of the
   constructor being read or resolved is known to be good, bad or just
   starting out.  */

static gfc_typespec constructor_ts;
static enum
{ CONS_START, CONS_GOOD, CONS_BAD }
cons_state;

static int
check_element_type (gfc_expr *expr, bool convert)
{
  if (cons_state == CONS_BAD)
    return 0;			/* Suppress further errors */

  if (cons_state == CONS_START)
    {
      if (expr->ts.type == BT_UNKNOWN)
	cons_state = CONS_BAD;
      else
	{
	  cons_state = CONS_GOOD;
	  constructor_ts = expr->ts;
	}

      return 0;
    }

  if (gfc_compare_types (&constructor_ts, &expr->ts))
    return 0;

  if (convert)
    return gfc_convert_type_warn (expr, &constructor_ts, 1, 1, true) ? 0 : 1;

  gfc_error ("Element in %s array constructor at %L is %s",
	     gfc_typename (&constructor_ts), &expr->where,
	     gfc_typename (expr));

  cons_state = CONS_BAD;
  return 1;
}


/* Recursive work function for gfc_check_constructor_type().  */

static bool
check_constructor_type (gfc_constructor_base base, bool convert)
{
  gfc_constructor *c;
  gfc_expr *e;

  for (c = gfc_constructor_first (base); c; c = gfc_constructor_next (c))
    {
      e = c->expr;

      if (e->expr_type == EXPR_ARRAY)
	{
	  if (!check_constructor_type (e->value.constructor, convert))
	    return false;

	  continue;
	}

      if (check_element_type (e, convert))
	return false;
    }

  return true;
}


/* Check that all elements of an array constructor are the same type.
   On false, an error has been generated.  */

bool
gfc_check_constructor_type (gfc_expr *e)
{
  bool t;

  if (e->ts.type != BT_UNKNOWN)
    {
      cons_state = CONS_GOOD;
      constructor_ts = e->ts;
    }
  else
    {
      cons_state = CONS_START;
      gfc_clear_ts (&constructor_ts);
    }

  /* If e->ts.type != BT_UNKNOWN, the array constructor included a
     typespec, and we will now convert the values on the fly.  */
  t = check_constructor_type (e->value.constructor, e->ts.type != BT_UNKNOWN);
  if (t && e->ts.type == BT_UNKNOWN)
    e->ts = constructor_ts;

  return t;
}



typedef struct cons_stack
{
  gfc_iterator *iterator;
  struct cons_stack *previous;
}
cons_stack;

static cons_stack *base;

static bool check_constructor (gfc_constructor_base, bool (*) (gfc_expr *));

/* Check an EXPR_VARIABLE expression in a constructor to make sure
   that that variable is an iteration variable.  */

bool
gfc_check_iter_variable (gfc_expr *expr)
{
  gfc_symbol *sym;
  cons_stack *c;

  sym = expr->symtree->n.sym;

  for (c = base; c && c->iterator; c = c->previous)
    if (sym == c->iterator->var->symtree->n.sym)
      return true;

  return false;
}


/* Recursive work function for gfc_check_constructor().  This amounts
   to calling the check function for each expression in the
   constructor, giving variables with the names of iterators a pass.  */

static bool
check_constructor (gfc_constructor_base ctor, bool (*check_function) (gfc_expr *))
{
  cons_stack element;
  gfc_expr *e;
  bool t;
  gfc_constructor *c;

  for (c = gfc_constructor_first (ctor); c; c = gfc_constructor_next (c))
    {
      e = c->expr;

      if (!e)
	continue;

      if (e->expr_type != EXPR_ARRAY)
	{
	  if (!(*check_function)(e))
	    return false;
	  continue;
	}

      element.previous = base;
      element.iterator = c->iterator;

      base = &element;
      t = check_constructor (e->value.constructor, check_function);
      base = element.previous;

      if (!t)
	return false;
    }

  /* Nothing went wrong, so all OK.  */
  return true;
}


/* Checks a constructor to see if it is a particular kind of
   expression -- specification, restricted, or initialization as
   determined by the check_function.  */

bool
gfc_check_constructor (gfc_expr *expr, bool (*check_function) (gfc_expr *))
{
  cons_stack *base_save;
  bool t;

  base_save = base;
  base = NULL;

  t = check_constructor (expr->value.constructor, check_function);
  base = base_save;

  return t;
}



/**************** Simplification of array constructors ****************/

iterator_stack *iter_stack;

typedef struct
{
  gfc_constructor_base base;
  int extract_count, extract_n;
  gfc_expr *extracted;
  mpz_t *count;

  mpz_t *offset;
  gfc_component *component;
  mpz_t *repeat;

  bool (*expand_work_function) (gfc_expr *);
}
expand_info;

static expand_info current_expand;

static bool expand_constructor (gfc_constructor_base);


/* Work function that counts the number of elements present in a
   constructor.  */

static bool
count_elements (gfc_expr *e)
{
  mpz_t result;

  if (e->rank == 0)
    mpz_add_ui (*current_expand.count, *current_expand.count, 1);
  else
    {
      if (!gfc_array_size (e, &result))
	{
	  gfc_free_expr (e);
	  return false;
	}

      mpz_add (*current_expand.count, *current_expand.count, result);
      mpz_clear (result);
    }

  gfc_free_expr (e);
  return true;
}


/* Work function that extracts a particular element from an array
   constructor, freeing the rest.  */

static bool
extract_element (gfc_expr *e)
{
  if (e->rank != 0)
    {				/* Something unextractable */
      gfc_free_expr (e);
      return false;
    }

  if (current_expand.extract_count == current_expand.extract_n)
    current_expand.extracted = e;
  else
    gfc_free_expr (e);

  current_expand.extract_count++;

  return true;
}


/* Work function that constructs a new constructor out of the old one,
   stringing new elements together.  */

static bool
expand (gfc_expr *e)
{
  gfc_constructor *c = gfc_constructor_append_expr (&current_expand.base,
						    e, &e->where);

  c->n.component = current_expand.component;
  return true;
}


/* Given an initialization expression that is a variable reference,
   substitute the current value of the iteration variable.  */

void
gfc_simplify_iterator_var (gfc_expr *e)
{
  iterator_stack *p;

  for (p = iter_stack; p; p = p->prev)
    if (e->symtree == p->variable)
      break;

  if (p == NULL)
    return;		/* Variable not found */

  gfc_replace_expr (e, gfc_get_int_expr (gfc_default_integer_kind, NULL, 0));

  mpz_set (e->value.integer, p->value);

  return;
}


/* Expand an expression with that is inside of a constructor,
   recursing into other constructors if present.  */

static bool
expand_expr (gfc_expr *e)
{
  if (e->expr_type == EXPR_ARRAY)
    return expand_constructor (e->value.constructor);

  e = gfc_copy_expr (e);

  if (!gfc_simplify_expr (e, 1))
    {
      gfc_free_expr (e);
      return false;
    }

  return current_expand.expand_work_function (e);
}


static bool
expand_iterator (gfc_constructor *c)
{
  gfc_expr *start, *end, *step;
  iterator_stack frame;
  mpz_t trip;
  bool t;

  end = step = NULL;

  t = false;

  mpz_init (trip);
  mpz_init (frame.value);
  frame.prev = NULL;

  start = gfc_copy_expr (c->iterator->start);
  if (!gfc_simplify_expr (start, 1))
    goto cleanup;

  if (start->expr_type != EXPR_CONSTANT || start->ts.type != BT_INTEGER)
    goto cleanup;

  end = gfc_copy_expr (c->iterator->end);
  if (!gfc_simplify_expr (end, 1))
    goto cleanup;

  if (end->expr_type != EXPR_CONSTANT || end->ts.type != BT_INTEGER)
    goto cleanup;

  step = gfc_copy_expr (c->iterator->step);
  if (!gfc_simplify_expr (step, 1))
    goto cleanup;

  if (step->expr_type != EXPR_CONSTANT || step->ts.type != BT_INTEGER)
    goto cleanup;

  if (mpz_sgn (step->value.integer) == 0)
    {
      gfc_error ("Iterator step at %L cannot be zero", &step->where);
      goto cleanup;
    }

  /* Calculate the trip count of the loop.  */
  mpz_sub (trip, end->value.integer, start->value.integer);
  mpz_add (trip, trip, step->value.integer);
  mpz_tdiv_q (trip, trip, step->value.integer);

  mpz_set (frame.value, start->value.integer);

  frame.prev = iter_stack;
  frame.variable = c->iterator->var->symtree;
  iter_stack = &frame;

  while (mpz_sgn (trip) > 0)
    {
      if (!expand_expr (c->expr))
	goto cleanup;

      mpz_add (frame.value, frame.value, step->value.integer);
      mpz_sub_ui (trip, trip, 1);
    }

  t = true;

cleanup:
  gfc_free_expr (start);
  gfc_free_expr (end);
  gfc_free_expr (step);

  mpz_clear (trip);
  mpz_clear (frame.value);

  iter_stack = frame.prev;

  return t;
}

/* Variables for noticing if all constructors are empty, and
   if any of them had a type.  */

static bool empty_constructor;
static gfc_typespec empty_ts;

/* Expand a constructor into constant constructors without any
   iterators, calling the work function for each of the expanded
   expressions.  The work function needs to either save or free the
   passed expression.  */

static bool
expand_constructor (gfc_constructor_base base)
{
  gfc_constructor *c;
  gfc_expr *e;

  for (c = gfc_constructor_first (base); c; c = gfc_constructor_next(c))
    {
      if (c->iterator != NULL)
	{
	  if (!expand_iterator (c))
	    return false;
	  continue;
	}

      e = c->expr;

      if (e == NULL)
	return false;

      if (empty_constructor)
	empty_ts = e->ts;

      /* Simplify constant array expression/section within constructor.  */
      if (e->expr_type == EXPR_VARIABLE && e->rank > 0 && e->ref
	  && e->symtree && e->symtree->n.sym
	  && e->symtree->n.sym->attr.flavor == FL_PARAMETER)
	gfc_simplify_expr (e, 0);

      if (e->expr_type == EXPR_ARRAY)
	{
	  if (!expand_constructor (e->value.constructor))
	    return false;

	  continue;
	}

      empty_constructor = false;
      e = gfc_copy_expr (e);
      if (!gfc_simplify_expr (e, 1))
	{
	  gfc_free_expr (e);
	  return false;
	}
      e->from_constructor = 1;
      current_expand.offset = &c->offset;
      current_expand.repeat = &c->repeat;
      current_expand.component = c->n.component;
      if (!current_expand.expand_work_function(e))
	return false;
    }
  return true;
}


/* Given an array expression and an element number (starting at zero),
   return a pointer to the array element.  NULL is returned if the
   size of the array has been exceeded.  The expression node returned
   remains a part of the array and should not be freed.  Access is not
   efficient at all, but this is another place where things do not
   have to be particularly fast.  */

static gfc_expr *
gfc_get_array_element (gfc_expr *array, int element)
{
  expand_info expand_save;
  gfc_expr *e;
  bool rc;

  expand_save = current_expand;
  current_expand.extract_n = element;
  current_expand.expand_work_function = extract_element;
  current_expand.extracted = NULL;
  current_expand.extract_count = 0;

  iter_stack = NULL;

  rc = expand_constructor (array->value.constructor);
  e = current_expand.extracted;
  current_expand = expand_save;

  if (!rc)
    return NULL;

  return e;
}


/* Top level subroutine for expanding constructors.  We only expand
   constructor if they are small enough.  */

bool
gfc_expand_constructor (gfc_expr *e, bool fatal)
{
  expand_info expand_save;
  gfc_expr *f;
  bool rc;

  if (gfc_is_size_zero_array (e))
    return true;

  /* If we can successfully get an array element at the max array size then
     the array is too big to expand, so we just return.  */
  f = gfc_get_array_element (e, flag_max_array_constructor);
  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, flag_max_array_constructor);
	  return false;
	}
      return true;
    }

  /* We now know the array is not too big so go ahead and try to expand it.  */
  expand_save = current_expand;
  current_expand.base = NULL;

  iter_stack = NULL;

  empty_constructor = true;
  gfc_clear_ts (&empty_ts);
  current_expand.expand_work_function = expand;

  if (!expand_constructor (e->value.constructor))
    {
      gfc_constructor_free (current_expand.base);
      rc = false;
      goto done;
    }

  /* If we don't have an explicit constructor type, and there
     were only empty constructors, then take the type from
     them.  */

  if (constructor_ts.type == BT_UNKNOWN && empty_constructor)
    e->ts = empty_ts;

  gfc_constructor_free (e->value.constructor);
  e->value.constructor = current_expand.base;

  rc = true;

done:
  current_expand = expand_save;

  return rc;
}


/* Work function for checking that an element of a constructor is a
   constant, after removal of any iteration variables.  We return
   false if not so.  */

static bool
is_constant_element (gfc_expr *e)
{
  int rv;

  rv = gfc_is_constant_expr (e);
  gfc_free_expr (e);

  return rv ? true : false;
}


/* Given an array constructor, determine if the constructor is
   constant or not by expanding it and making sure that all elements
   are constants.  This is a bit of a hack since something like (/ (i,
   i=1,100000000) /) will take a while as* opposed to a more clever
   function that traverses the expression tree. FIXME.  */

int
gfc_constant_ac (gfc_expr *e)
{
  expand_info expand_save;
  bool rc;

  iter_stack = NULL;
  expand_save = current_expand;
  current_expand.expand_work_function = is_constant_element;

  rc = expand_constructor (e->value.constructor);

  current_expand = expand_save;
  if (!rc)
    return 0;

  return 1;
}


/* Returns nonzero if an array constructor has been completely
   expanded (no iterators) and zero if iterators are present.  */

int
gfc_expanded_ac (gfc_expr *e)
{
  gfc_constructor *c;

  if (e->expr_type == EXPR_ARRAY)
    for (c = gfc_constructor_first (e->value.constructor);
	 c; c = gfc_constructor_next (c))
      if (c->iterator != NULL || !gfc_expanded_ac (c->expr))
	return 0;

  return 1;
}


/*************** Type resolution of array constructors ***************/


/* The symbol expr_is_sought_symbol_ref will try to find.  */
static const gfc_symbol *sought_symbol = NULL;


/* Tells whether the expression E is a variable reference to the symbol
   in the static variable SOUGHT_SYMBOL, and sets the locus pointer WHERE
   accordingly.
   To be used with gfc_expr_walker: if a reference is found we don't need
   to look further so we return 1 to skip any further walk.  */

static int
expr_is_sought_symbol_ref (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
			   void *where)
{
  gfc_expr *expr = *e;
  locus *sym_loc = (locus *)where;

  if (expr->expr_type == EXPR_VARIABLE
      && expr->symtree->n.sym == sought_symbol)
    {
      *sym_loc = expr->where;
      return 1;
    }

  return 0;
}


/* Tells whether the expression EXPR contains a reference to the symbol
   SYM and in that case sets the position SYM_LOC where the reference is.  */

static bool
find_symbol_in_expr (gfc_symbol *sym, gfc_expr *expr, locus *sym_loc)
{
  int ret;

  sought_symbol = sym;
  ret = gfc_expr_walker (&expr, &expr_is_sought_symbol_ref, sym_loc);
  sought_symbol = NULL;
  return ret;
}


/* Recursive array list resolution function.  All of the elements must
   be of the same type.  */

static bool
resolve_array_list (gfc_constructor_base base)
{
  bool t;
  gfc_constructor *c;
  gfc_iterator *iter;

  t = true;

  for (c = gfc_constructor_first (base); c; c = gfc_constructor_next (c))
    {
      iter = c->iterator;
      if (iter != NULL)
        {
	  gfc_symbol *iter_var;
	  locus iter_var_loc;

	  if (!gfc_resolve_iterator (iter, false, true))
	    t = false;

	  /* Check for bounds referencing the iterator variable.  */
	  gcc_assert (iter->var->expr_type == EXPR_VARIABLE);
	  iter_var = iter->var->symtree->n.sym;
	  if (find_symbol_in_expr (iter_var, iter->start, &iter_var_loc))
	    {
	      if (!gfc_notify_std (GFC_STD_LEGACY, "AC-IMPLIED-DO initial "
				   "expression references control variable "
				   "at %L", &iter_var_loc))
	       t = false;
	    }
	  if (find_symbol_in_expr (iter_var, iter->end, &iter_var_loc))
	    {
	      if (!gfc_notify_std (GFC_STD_LEGACY, "AC-IMPLIED-DO final "
				   "expression references control variable "
				   "at %L", &iter_var_loc))
	       t = false;
	    }
	  if (find_symbol_in_expr (iter_var, iter->step, &iter_var_loc))
	    {
	      if (!gfc_notify_std (GFC_STD_LEGACY, "AC-IMPLIED-DO step "
				   "expression references control variable "
				   "at %L", &iter_var_loc))
	       t = false;
	    }
	}

      if (!gfc_resolve_expr (c->expr))
	t = false;

      if (UNLIMITED_POLY (c->expr))
	{
	  gfc_error ("Array constructor value at %L shall not be unlimited "
		     "polymorphic [F2008: C4106]", &c->expr->where);
	  t = false;
	}
    }

  return t;
}

/* Resolve character array constructor. If it has a specified constant character
   length, pad/truncate the elements here; if the length is not specified and
   all elements are of compile-time known length, emit an error as this is
   invalid.  */

bool
gfc_resolve_character_array_constructor (gfc_expr *expr)
{
  gfc_constructor *p;
  HOST_WIDE_INT found_length;

  gcc_assert (expr->expr_type == EXPR_ARRAY);
  gcc_assert (expr->ts.type == BT_CHARACTER);

  if (expr->ts.u.cl == NULL)
    {
      for (p = gfc_constructor_first (expr->value.constructor);
	   p; p = gfc_constructor_next (p))
	if (p->expr->ts.u.cl != NULL)
	  {
	    /* Ensure that if there is a char_len around that it is
	       used; otherwise the middle-end confuses them!  */
	    expr->ts.u.cl = p->expr->ts.u.cl;
	    goto got_charlen;
	  }

      expr->ts.u.cl = gfc_new_charlen (gfc_current_ns, NULL);
    }

got_charlen:

  /* Early exit for zero size arrays. */
  if (expr->shape)
    {
      mpz_t size;
      HOST_WIDE_INT arraysize;

      gfc_array_size (expr, &size);
      arraysize = mpz_get_ui (size);
      mpz_clear (size);

      if (arraysize == 0)
	return true;
    }

  found_length = -1;

  if (expr->ts.u.cl->length == NULL)
    {
      /* Check that all constant string elements have the same length until
	 we reach the end or find a variable-length one.  */

      for (p = gfc_constructor_first (expr->value.constructor);
	   p; p = gfc_constructor_next (p))
	{
	  HOST_WIDE_INT current_length = -1;
	  gfc_ref *ref;
	  for (ref = p->expr->ref; ref; ref = ref->next)
	    if (ref->type == REF_SUBSTRING
		&& ref->u.ss.start
		&& ref->u.ss.start->expr_type == EXPR_CONSTANT
		&& ref->u.ss.end
		&& ref->u.ss.end->expr_type == EXPR_CONSTANT)
	      break;

	  if (p->expr->expr_type == EXPR_CONSTANT)
	    current_length = p->expr->value.character.length;
	  else if (ref)
	    current_length = gfc_mpz_get_hwi (ref->u.ss.end->value.integer)
	      - gfc_mpz_get_hwi (ref->u.ss.start->value.integer) + 1;
	  else if (p->expr->ts.u.cl && p->expr->ts.u.cl->length
		   && p->expr->ts.u.cl->length->expr_type == EXPR_CONSTANT)
	    current_length = gfc_mpz_get_hwi (p->expr->ts.u.cl->length->value.integer);
	  else
	    return true;

	  if (current_length < 0)
	    current_length = 0;

	  if (found_length == -1)
	    found_length = current_length;
	  else if (found_length != current_length)
	    {
	      gfc_error ("Different CHARACTER lengths (%ld/%ld) in array"
			 " constructor at %L", (long) found_length,
			 (long) current_length, &p->expr->where);
	      return false;
	    }

	  gcc_assert (found_length == current_length);
	}

      gcc_assert (found_length != -1);

      /* Update the character length of the array constructor.  */
      expr->ts.u.cl->length = gfc_get_int_expr (gfc_charlen_int_kind,
						NULL, found_length);
    }
  else
    {
      /* We've got a character length specified.  It should be an integer,
	 otherwise an error is signalled elsewhere.  */
      gcc_assert (expr->ts.u.cl->length);

      /* If we've got a constant character length, pad according to this.
	 gfc_extract_int does check for BT_INTEGER and EXPR_CONSTANT and sets
	 max_length only if they pass.  */
      gfc_extract_hwi (expr->ts.u.cl->length, &found_length);

      /* Now pad/truncate the elements accordingly to the specified character
	 length.  This is ok inside this conditional, as in the case above
	 (without typespec) all elements are verified to have the same length
	 anyway.  */
      if (found_length != -1)
	for (p = gfc_constructor_first (expr->value.constructor);
	     p; p = gfc_constructor_next (p))
	  if (p->expr->expr_type == EXPR_CONSTANT)
	    {
	      gfc_expr *cl = NULL;
	      HOST_WIDE_INT current_length = -1;
	      bool has_ts;

	      if (p->expr->ts.u.cl && p->expr->ts.u.cl->length)
	      {
		cl = p->expr->ts.u.cl->length;
		gfc_extract_hwi (cl, &current_length);
	      }

	      /* If gfc_extract_int above set current_length, we implicitly
		 know the type is BT_INTEGER and it's EXPR_CONSTANT.  */

	      has_ts = expr->ts.u.cl->length_from_typespec;

	      if (! cl
		  || (current_length != -1 && current_length != found_length))
		gfc_set_constant_character_len (found_length, p->expr,
						has_ts ? -1 : found_length);
	    }
    }

  return true;
}


/* Resolve all of the expressions in an array list.  */

bool
gfc_resolve_array_constructor (gfc_expr *expr)
{
  bool t;

  t = resolve_array_list (expr->value.constructor);
  if (t)
    t = gfc_check_constructor_type (expr);

  /* gfc_resolve_character_array_constructor is called in gfc_resolve_expr after
     the call to this function, so we don't need to call it here; if it was
     called twice, an error message there would be duplicated.  */

  return t;
}


/* Copy an iterator structure.  */

gfc_iterator *
gfc_copy_iterator (gfc_iterator *src)
{
  gfc_iterator *dest;

  if (src == NULL)
    return NULL;

  dest = gfc_get_iterator ();

  dest->var = gfc_copy_expr (src->var);
  dest->start = gfc_copy_expr (src->start);
  dest->end = gfc_copy_expr (src->end);
  dest->step = gfc_copy_expr (src->step);
  dest->unroll = src->unroll;
  dest->ivdep = src->ivdep;
  dest->vector = src->vector;
  dest->novector = src->novector;

  return dest;
}


/********* Subroutines for determining the size of an array *********/

/* These are needed just to accommodate RESHAPE().  There are no
   diagnostics here, we just return false if something goes wrong.  */


/* Get the size of single dimension of an array specification.  The
   array is guaranteed to be one dimensional.  */

bool
spec_dimen_size (gfc_array_spec *as, int dimen, mpz_t *result)
{
  if (as == NULL)
    return false;

  if (dimen < 0 || dimen > as->rank - 1)
    gfc_internal_error ("spec_dimen_size(): Bad dimension");

  if (as->type != AS_EXPLICIT
      || !as->lower[dimen]
      || !as->upper[dimen])
    return false;

  if (as->lower[dimen]->expr_type != EXPR_CONSTANT
      || as->upper[dimen]->expr_type != EXPR_CONSTANT
      || as->lower[dimen]->ts.type != BT_INTEGER
      || as->upper[dimen]->ts.type != BT_INTEGER)
    return false;

  mpz_init (*result);

  mpz_sub (*result, as->upper[dimen]->value.integer,
	   as->lower[dimen]->value.integer);

  mpz_add_ui (*result, *result, 1);

  if (mpz_cmp_si (*result, 0) < 0)
    mpz_set_si (*result, 0);

  return true;
}


bool
spec_size (gfc_array_spec *as, mpz_t *result)
{
  mpz_t size;
  int d;

  if (!as || as->type == AS_ASSUMED_RANK)
    return false;

  mpz_init_set_ui (*result, 1);

  for (d = 0; d < as->rank; d++)
    {
      if (!spec_dimen_size (as, d, &size))
	{
	  mpz_clear (*result);
	  return false;
	}

      mpz_mul (*result, *result, size);
      mpz_clear (size);
    }

  return true;
}


/* Get the number of elements in an array section. Optionally, also supply
   the end value.  */

bool
gfc_ref_dimen_size (gfc_array_ref *ar, int dimen, mpz_t *result, mpz_t *end)
{
  mpz_t upper, lower, stride;
  mpz_t diff;
  bool t;
  gfc_expr *stride_expr = NULL;

  if (dimen < 0 || ar == NULL)
    gfc_internal_error ("gfc_ref_dimen_size(): Bad dimension");

  if (dimen > ar->dimen - 1)
    {
      gfc_error ("Bad array dimension at %L", &ar->c_where[dimen]);
      return false;
    }

  switch (ar->dimen_type[dimen])
    {
    case DIMEN_ELEMENT:
      mpz_init (*result);
      mpz_set_ui (*result, 1);
      t = true;
      break;

    case DIMEN_VECTOR:
      t = gfc_array_size (ar->start[dimen], result);	/* Recurse! */
      break;

    case DIMEN_RANGE:

      mpz_init (stride);

      if (ar->stride[dimen] == NULL)
	mpz_set_ui (stride, 1);
      else
	{
	  stride_expr = gfc_copy_expr(ar->stride[dimen]); 

	  if (!gfc_simplify_expr (stride_expr, 1)
	     || stride_expr->expr_type != EXPR_CONSTANT
	     || mpz_cmp_ui (stride_expr->value.integer, 0) == 0)
	    {
	      gfc_free_expr (stride_expr);
	      mpz_clear (stride);
	      return false;
	    }
	  mpz_set (stride, stride_expr->value.integer);
	  gfc_free_expr(stride_expr);
	}

      /* Calculate the number of elements via gfc_dep_difference, but only if
	 start and end are both supplied in the reference or the array spec.
	 This is to guard against strange but valid code like

	 subroutine foo(a,n)
	 real a(1:n)
	 n = 3
	 print *,size(a(n-1:))

	 where the user changes the value of a variable.  If we have to
	 determine end as well, we cannot do this using gfc_dep_difference.
	 Fall back to the constants-only code then.  */

      if (end == NULL)
	{
	  bool use_dep;

	  use_dep = gfc_dep_difference (ar->end[dimen], ar->start[dimen],
					&diff);
	  if (!use_dep && ar->end[dimen] == NULL && ar->start[dimen] == NULL)
	    use_dep = gfc_dep_difference (ar->as->upper[dimen],
					    ar->as->lower[dimen], &diff);

	  if (use_dep)
	    {
	      mpz_init (*result);
	      mpz_add (*result, diff, stride);
	      mpz_div (*result, *result, stride);
	      if (mpz_cmp_ui (*result, 0) < 0)
		mpz_set_ui (*result, 0);

	      mpz_clear (stride);
	      mpz_clear (diff);
	      return true;
	    }

	}

      /*  Constant-only code here, which covers more cases
	  like a(:4) etc.  */
      mpz_init (upper);
      mpz_init (lower);
      t = false;

      if (ar->start[dimen] == NULL)
	{
	  if (ar->as->lower[dimen] == NULL
	      || ar->as->lower[dimen]->expr_type != EXPR_CONSTANT
	      || ar->as->lower[dimen]->ts.type != BT_INTEGER)
	    goto cleanup;
	  mpz_set (lower, ar->as->lower[dimen]->value.integer);
	}
      else
	{
	  if (ar->start[dimen]->expr_type != EXPR_CONSTANT)
	    goto cleanup;
	  mpz_set (lower, ar->start[dimen]->value.integer);
	}

      if (ar->end[dimen] == NULL)
	{
	  if (ar->as->upper[dimen] == NULL
	      || ar->as->upper[dimen]->expr_type != EXPR_CONSTANT
	      || ar->as->upper[dimen]->ts.type != BT_INTEGER)
	    goto cleanup;
	  mpz_set (upper, ar->as->upper[dimen]->value.integer);
	}
      else
	{
	  if (ar->end[dimen]->expr_type != EXPR_CONSTANT)
	    goto cleanup;
	  mpz_set (upper, ar->end[dimen]->value.integer);
	}

      mpz_init (*result);
      mpz_sub (*result, upper, lower);
      mpz_add (*result, *result, stride);
      mpz_div (*result, *result, stride);

      /* Zero stride caught earlier.  */
      if (mpz_cmp_ui (*result, 0) < 0)
	mpz_set_ui (*result, 0);
      t = true;

      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);
      mpz_clear (stride);
      return t;

    default:
      gfc_internal_error ("gfc_ref_dimen_size(): Bad dimen_type");
    }

  return t;
}


static bool
ref_size (gfc_array_ref *ar, mpz_t *result)
{
  mpz_t size;
  int d;

  mpz_init_set_ui (*result, 1);

  for (d = 0; d < ar->dimen; d++)
    {
      if (!gfc_ref_dimen_size (ar, d, &size, NULL))
	{
	  mpz_clear (*result);
	  return false;
	}

      mpz_mul (*result, *result, size);
      mpz_clear (size);
    }

  return true;
}


/* Given an array expression and a dimension, figure out how many
   elements it has along that dimension.  Returns true if we were
   able to return a result in the 'result' variable, false
   otherwise.  */

bool
gfc_array_dimen_size (gfc_expr *array, int dimen, mpz_t *result)
{
  gfc_ref *ref;
  int i;

  gcc_assert (array != NULL);

  if (array->ts.type == BT_CLASS)
    return false;

  if (array->rank == -1)
    return false;

  if (dimen < 0 || dimen > array->rank - 1)
    gfc_internal_error ("gfc_array_dimen_size(): Bad dimension");

  switch (array->expr_type)
    {
    case EXPR_VARIABLE:
    case EXPR_FUNCTION:
      for (ref = array->ref; ref; ref = ref->next)
	{
	  if (ref->type != REF_ARRAY)
	    continue;

	  if (ref->u.ar.type == AR_FULL)
	    return spec_dimen_size (ref->u.ar.as, dimen, result);

	  if (ref->u.ar.type == AR_SECTION)
	    {
	      for (i = 0; dimen >= 0; i++)
		if (ref->u.ar.dimen_type[i] != DIMEN_ELEMENT)
		  dimen--;

	      return gfc_ref_dimen_size (&ref->u.ar, i - 1, result, NULL);
	    }
	}

      if (array->shape)
	{
	  mpz_init_set (*result, array->shape[dimen]);
	  return true;
	}

      if (array->symtree->n.sym->attr.generic
	  && array->value.function.esym != NULL)
	{
	  if (!spec_dimen_size (array->value.function.esym->as, dimen, result))
	    return false;
	}
      else if (!spec_dimen_size (array->symtree->n.sym->as, dimen, result))
	return false;

      break;

    case EXPR_ARRAY:
      if (array->shape == NULL) {
	/* Expressions with rank > 1 should have "shape" properly set */
	if ( array->rank != 1 )
	  gfc_internal_error ("gfc_array_dimen_size(): Bad EXPR_ARRAY expr");
	return gfc_array_size(array, result);
      }

      /* Fall through */
    default:
      if (array->shape == NULL)
	return false;

      mpz_init_set (*result, array->shape[dimen]);

      break;
    }

  return true;
}


/* Given an array expression, figure out how many elements are in the
   array.  Returns true if this is possible, and sets the 'result'
   variable.  Otherwise returns false.  */

bool
gfc_array_size (gfc_expr *array, mpz_t *result)
{
  expand_info expand_save;
  gfc_ref *ref;
  int i;
  bool t;

  if (array->ts.type == BT_CLASS)
    return false;

  switch (array->expr_type)
    {
    case EXPR_ARRAY:
      gfc_push_suppress_errors ();

      expand_save = current_expand;

      current_expand.count = result;
      mpz_init_set_ui (*result, 0);

      current_expand.expand_work_function = count_elements;
      iter_stack = NULL;

      t = expand_constructor (array->value.constructor);

      gfc_pop_suppress_errors ();

      if (!t)
	mpz_clear (*result);
      current_expand = expand_save;
      return t;

    case EXPR_VARIABLE:
      for (ref = array->ref; ref; ref = ref->next)
	{
	  if (ref->type != REF_ARRAY)
	    continue;

	  if (ref->u.ar.type == AR_FULL)
	    return spec_size (ref->u.ar.as, result);

	  if (ref->u.ar.type == AR_SECTION)
	    return ref_size (&ref->u.ar, result);
	}

      return spec_size (array->symtree->n.sym->as, result);


    default:
      if (array->rank == 0 || array->shape == NULL)
	return false;

      mpz_init_set_ui (*result, 1);

      for (i = 0; i < array->rank; i++)
	mpz_mul (*result, *result, array->shape[i]);

      break;
    }

  return true;
}


/* Given an array reference, return the shape of the reference in an
   array of mpz_t integers.  */

bool
gfc_array_ref_shape (gfc_array_ref *ar, mpz_t *shape)
{
  int d;
  int i;

  d = 0;

  switch (ar->type)
    {
    case AR_FULL:
      for (; d < ar->as->rank; d++)
	if (!spec_dimen_size (ar->as, d, &shape[d]))
	  goto cleanup;

      return true;

    case AR_SECTION:
      for (i = 0; i < ar->dimen; i++)
	{
	  if (ar->dimen_type[i] != DIMEN_ELEMENT)
	    {
	      if (!gfc_ref_dimen_size (ar, i, &shape[d], NULL))
		goto cleanup;
	      d++;
	    }
	}

      return true;

    default:
      break;
    }

cleanup:
  gfc_clear_shape (shape, d);
  return false;
}


/* Given an array expression, find the array reference structure that
   characterizes the reference.  */

gfc_array_ref *
gfc_find_array_ref (gfc_expr *e, bool allow_null)
{
  gfc_ref *ref;

  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))
      break;

  if (ref == NULL)
    {
      if (allow_null)
	return NULL;
      else
	gfc_internal_error ("gfc_find_array_ref(): No ref found");
    }

  return &ref->u.ar;
}


/* Find out if an array shape is known at compile time.  */

bool
gfc_is_compile_time_shape (gfc_array_spec *as)
{
  if (as->type != AS_EXPLICIT)
    return false;

  for (int i = 0; i < as->rank; i++)
    if (!gfc_is_constant_expr (as->lower[i])
	|| !gfc_is_constant_expr (as->upper[i]))
      return false;

  return true;
}
