| Index: gcc/gcc/fortran/check.c | 
| diff --git a/gcc/gcc/fortran/check.c b/gcc/gcc/fortran/check.c | 
| index b967d78cf2af5901ad5fd358b19aa5109b5cc3c5..2d8cfefb79be215c417943a560c8a93d5cf13298 100644 | 
| --- a/gcc/gcc/fortran/check.c | 
| +++ b/gcc/gcc/fortran/check.c | 
| @@ -214,6 +214,80 @@ array_check (gfc_expr *e, int n) | 
| } | 
|  | 
|  | 
| +/* If expr is a constant, then check to ensure that it is greater than | 
| +   of equal to zero.  */ | 
| + | 
| +static gfc_try | 
| +nonnegative_check (const char *arg, gfc_expr *expr) | 
| +{ | 
| +  int i; | 
| + | 
| +  if (expr->expr_type == EXPR_CONSTANT) | 
| +    { | 
| +      gfc_extract_int (expr, &i); | 
| +      if (i < 0) | 
| +	{ | 
| +	  gfc_error ("'%s' at %L must be nonnegative", arg, &expr->where); | 
| +	  return FAILURE; | 
| +	} | 
| +    } | 
| + | 
| +  return SUCCESS; | 
| +} | 
| + | 
| + | 
| +/* If expr2 is constant, then check that the value is less than | 
| +   bit_size(expr1).  */ | 
| + | 
| +static gfc_try | 
| +less_than_bitsize1 (const char *arg1, gfc_expr *expr1, const char *arg2, | 
| +	       gfc_expr *expr2) | 
| +{ | 
| +  int i2, i3; | 
| + | 
| +  if (expr2->expr_type == EXPR_CONSTANT) | 
| +    { | 
| +      gfc_extract_int (expr2, &i2); | 
| +      i3 = gfc_validate_kind (BT_INTEGER, expr1->ts.kind, false); | 
| +      if (i2 >= gfc_integer_kinds[i3].bit_size) | 
| +	{ | 
| +	  gfc_error ("'%s' at %L must be less than BIT_SIZE('%s')", | 
| +		     arg2, &expr2->where, arg1); | 
| +	  return FAILURE; | 
| +	} | 
| +    } | 
| + | 
| +  return SUCCESS; | 
| +} | 
| + | 
| + | 
| +/* If expr2 and expr3 are constants, then check that the value is less than | 
| +   or equal to bit_size(expr1).  */ | 
| + | 
| +static gfc_try | 
| +less_than_bitsize2 (const char *arg1, gfc_expr *expr1, const char *arg2, | 
| +	       gfc_expr *expr2, const char *arg3, gfc_expr *expr3) | 
| +{ | 
| +  int i2, i3; | 
| + | 
| +  if (expr2->expr_type == EXPR_CONSTANT && expr3->expr_type == EXPR_CONSTANT) | 
| +    { | 
| +      gfc_extract_int (expr2, &i2); | 
| +      gfc_extract_int (expr3, &i3); | 
| +      i2 += i3; | 
| +      i3 = gfc_validate_kind (BT_INTEGER, expr1->ts.kind, false); | 
| +      if (i2 > gfc_integer_kinds[i3].bit_size) | 
| +	{ | 
| +	  gfc_error ("'%s + %s' at %L must be less than or equal " | 
| +		     "to BIT_SIZE('%s')", | 
| +		     arg2, arg3, &expr2->where, arg1); | 
| +	  return FAILURE; | 
| +	} | 
| +    } | 
| + | 
| +  return SUCCESS; | 
| +} | 
| + | 
| /* Make sure two expressions have the same type.  */ | 
|  | 
| static gfc_try | 
| @@ -339,6 +413,9 @@ dim_rank_check (gfc_expr *dim, gfc_expr *array, int allow_assumed) | 
| gfc_array_ref *ar; | 
| int rank; | 
|  | 
| +  if (dim == NULL) | 
| +    return SUCCESS; | 
| + | 
| if (dim->expr_type != EXPR_CONSTANT | 
| || (array->expr_type != EXPR_VARIABLE | 
| && array->expr_type != EXPR_ARRAY)) | 
| @@ -407,20 +484,20 @@ gfc_check_same_strlen (const gfc_expr *a, const gfc_expr *b, const char *name) | 
| long len_a, len_b; | 
| len_a = len_b = -1; | 
|  | 
| -   if (a->ts.cl && a->ts.cl->length | 
| -       && a->ts.cl->length->expr_type == EXPR_CONSTANT) | 
| -     len_a = mpz_get_si (a->ts.cl->length->value.integer); | 
| +   if (a->ts.u.cl && a->ts.u.cl->length | 
| +       && a->ts.u.cl->length->expr_type == EXPR_CONSTANT) | 
| +     len_a = mpz_get_si (a->ts.u.cl->length->value.integer); | 
| else if (a->expr_type == EXPR_CONSTANT | 
| -	    && (a->ts.cl == NULL || a->ts.cl->length == NULL)) | 
| +	    && (a->ts.u.cl == NULL || a->ts.u.cl->length == NULL)) | 
| len_a = a->value.character.length; | 
| else | 
| return SUCCESS; | 
|  | 
| -   if (b->ts.cl && b->ts.cl->length | 
| -       && b->ts.cl->length->expr_type == EXPR_CONSTANT) | 
| -     len_b = mpz_get_si (b->ts.cl->length->value.integer); | 
| +   if (b->ts.u.cl && b->ts.u.cl->length | 
| +       && b->ts.u.cl->length->expr_type == EXPR_CONSTANT) | 
| +     len_b = mpz_get_si (b->ts.u.cl->length->value.integer); | 
| else if (b->expr_type == EXPR_CONSTANT | 
| -	    && (b->ts.cl == NULL || b->ts.cl->length == NULL)) | 
| +	    && (b->ts.u.cl == NULL || b->ts.u.cl->length == NULL)) | 
| len_b = b->value.character.length; | 
| else | 
| return SUCCESS; | 
| @@ -519,6 +596,9 @@ gfc_check_all_any (gfc_expr *mask, gfc_expr *dim) | 
| if (dim_check (dim, 1, false) == FAILURE) | 
| return FAILURE; | 
|  | 
| +  if (dim_rank_check (dim, mask, 0) == FAILURE) | 
| +    return FAILURE; | 
| + | 
| return SUCCESS; | 
| } | 
|  | 
| @@ -540,9 +620,6 @@ gfc_check_allocated (gfc_expr *array) | 
| return FAILURE; | 
| } | 
|  | 
| -  if (array_check (array, 0) == FAILURE) | 
| -    return FAILURE; | 
| - | 
| return SUCCESS; | 
| } | 
|  | 
| @@ -666,6 +743,19 @@ null_arg: | 
|  | 
|  | 
| gfc_try | 
| +gfc_check_atan_2 (gfc_expr *y, gfc_expr *x) | 
| +{ | 
| +  /* gfc_notify_std would be a wast of time as the return value | 
| +     is seemingly used only for the generic resolution.  The error | 
| +     will be: Too many arguments.  */ | 
| +  if ((gfc_option.allow_std & GFC_STD_F2008) == 0) | 
| +    return FAILURE; | 
| + | 
| +  return gfc_check_atan2 (y, x); | 
| +} | 
| + | 
| + | 
| +gfc_try | 
| gfc_check_atan2 (gfc_expr *y, gfc_expr *x) | 
| { | 
| if (type_check (y, 0, BT_REAL) == FAILURE) | 
| @@ -693,13 +783,20 @@ gfc_check_besn (gfc_expr *n, gfc_expr *x) | 
|  | 
|  | 
| gfc_try | 
| -gfc_check_btest (gfc_expr *i, gfc_expr *pos) | 
| +gfc_check_bitfcn (gfc_expr *i, gfc_expr *pos) | 
| { | 
| if (type_check (i, 0, BT_INTEGER) == FAILURE) | 
| return FAILURE; | 
| + | 
| if (type_check (pos, 1, BT_INTEGER) == FAILURE) | 
| return FAILURE; | 
|  | 
| +  if (nonnegative_check ("pos", pos) == FAILURE) | 
| +    return FAILURE; | 
| + | 
| +  if (less_than_bitsize1 ("i", i, "pos", pos) == FAILURE) | 
| +    return FAILURE; | 
| + | 
| return SUCCESS; | 
| } | 
|  | 
| @@ -861,6 +958,8 @@ gfc_check_count (gfc_expr *mask, gfc_expr *dim, gfc_expr *kind) | 
| return FAILURE; | 
| if (dim_check (dim, 1, false) == FAILURE) | 
| return FAILURE; | 
| +  if (dim_rank_check (dim, mask, 0) == FAILURE) | 
| +    return FAILURE; | 
| if (kind_check (kind, 2, BT_INTEGER) == FAILURE) | 
| return FAILURE; | 
| if (kind && gfc_notify_std (GFC_STD_F2003, "Fortran 2003: '%s' intrinsic " | 
| @@ -881,24 +980,56 @@ gfc_check_cshift (gfc_expr *array, gfc_expr *shift, gfc_expr *dim) | 
| if (type_check (shift, 1, BT_INTEGER) == FAILURE) | 
| return FAILURE; | 
|  | 
| -  if (array->rank == 1) | 
| +  if (dim_check (dim, 2, true) == FAILURE) | 
| +    return FAILURE; | 
| + | 
| +  if (dim_rank_check (dim, array, false) == FAILURE) | 
| +    return FAILURE; | 
| + | 
| +  if (array->rank == 1 || shift->rank == 0) | 
| { | 
| if (scalar_check (shift, 1) == FAILURE) | 
| return FAILURE; | 
| } | 
| -  else if (shift->rank != array->rank - 1 && shift->rank != 0) | 
| +  else if (shift->rank == array->rank - 1) | 
| { | 
| -      gfc_error ("SHIFT argument at %L of CSHIFT must have rank %d or be a " | 
| -		 "scalar", &shift->where, array->rank - 1); | 
| +      int d; | 
| +      if (!dim) | 
| +	d = 1; | 
| +      else if (dim->expr_type == EXPR_CONSTANT) | 
| +	gfc_extract_int (dim, &d); | 
| +      else | 
| +	d = -1; | 
| + | 
| +      if (d > 0) | 
| +	{ | 
| +	  int i, j; | 
| +	  for (i = 0, j = 0; i < array->rank; i++) | 
| +	    if (i != d - 1) | 
| +	      { | 
| +		if (!identical_dimen_shape (array, i, shift, j)) | 
| +		  { | 
| +		    gfc_error ("'%s' argument of '%s' intrinsic at %L has " | 
| +			       "invalid shape in dimension %d (%ld/%ld)", | 
| +			       gfc_current_intrinsic_arg[1], | 
| +			       gfc_current_intrinsic, &shift->where, i + 1, | 
| +			       mpz_get_si (array->shape[i]), | 
| +			       mpz_get_si (shift->shape[j])); | 
| +		    return FAILURE; | 
| +		  } | 
| + | 
| +		j += 1; | 
| +	      } | 
| +	} | 
| +    } | 
| +  else | 
| +    { | 
| +      gfc_error ("'%s' argument of intrinsic '%s' at %L of must have rank " | 
| +		 "%d or be a scalar", gfc_current_intrinsic_arg[1], | 
| +		 gfc_current_intrinsic, &shift->where, array->rank - 1); | 
| return FAILURE; | 
| } | 
|  | 
| -  /* TODO: Add shape conformance check between array (w/o dimension dim) | 
| -     and shift. */ | 
| - | 
| -  if (dim_check (dim, 2, true) == FAILURE) | 
| -    return FAILURE; | 
| - | 
| return SUCCESS; | 
| } | 
|  | 
| @@ -1055,55 +1186,85 @@ gfc_check_eoshift (gfc_expr *array, gfc_expr *shift, gfc_expr *boundary, | 
| if (type_check (shift, 1, BT_INTEGER) == FAILURE) | 
| return FAILURE; | 
|  | 
| -  if (array->rank == 1) | 
| +  if (dim_check (dim, 3, true) == FAILURE) | 
| +    return FAILURE; | 
| + | 
| +  if (dim_rank_check (dim, array, false) == FAILURE) | 
| +    return FAILURE; | 
| + | 
| +  if (array->rank == 1 || shift->rank == 0) | 
| { | 
| -      if (scalar_check (shift, 2) == FAILURE) | 
| +      if (scalar_check (shift, 1) == FAILURE) | 
| return FAILURE; | 
| } | 
| -  else if (shift->rank != array->rank - 1 && shift->rank != 0) | 
| +  else if (shift->rank == array->rank - 1) | 
| +    { | 
| +      int d; | 
| +      if (!dim) | 
| +	d = 1; | 
| +      else if (dim->expr_type == EXPR_CONSTANT) | 
| +	gfc_extract_int (dim, &d); | 
| +      else | 
| +	d = -1; | 
| + | 
| +      if (d > 0) | 
| +	{ | 
| +	  int i, j; | 
| +	  for (i = 0, j = 0; i < array->rank; i++) | 
| +	    if (i != d - 1) | 
| +	      { | 
| +		if (!identical_dimen_shape (array, i, shift, j)) | 
| +		  { | 
| +		    gfc_error ("'%s' argument of '%s' intrinsic at %L has " | 
| +			       "invalid shape in dimension %d (%ld/%ld)", | 
| +			       gfc_current_intrinsic_arg[1], | 
| +			       gfc_current_intrinsic, &shift->where, i + 1, | 
| +			       mpz_get_si (array->shape[i]), | 
| +			       mpz_get_si (shift->shape[j])); | 
| +		    return FAILURE; | 
| +		  } | 
| + | 
| +		j += 1; | 
| +	      } | 
| +	} | 
| +    } | 
| +  else | 
| { | 
| -      gfc_error ("SHIFT argument at %L of EOSHIFT must have rank %d or be a " | 
| -		 "scalar", &shift->where, array->rank - 1); | 
| +      gfc_error ("'%s' argument of intrinsic '%s' at %L of must have rank " | 
| +		 "%d or be a scalar", gfc_current_intrinsic_arg[1], | 
| +		 gfc_current_intrinsic, &shift->where, array->rank - 1); | 
| return FAILURE; | 
| } | 
|  | 
| -  /* TODO: Add shape conformance check between array (w/o dimension dim) | 
| -     and shift. */ | 
| - | 
| if (boundary != NULL) | 
| { | 
| if (same_type_check (array, 0, boundary, 2) == FAILURE) | 
| return FAILURE; | 
|  | 
| -      if (array->rank == 1) | 
| +      if (array->rank == 1 || boundary->rank == 0) | 
| { | 
| if (scalar_check (boundary, 2) == FAILURE) | 
| return FAILURE; | 
| } | 
| -      else if (boundary->rank != array->rank - 1 && boundary->rank != 0) | 
| +      else if (boundary->rank == array->rank - 1) | 
| { | 
| -	  gfc_error ("BOUNDARY argument at %L of EOSHIFT must have rank %d or be " | 
| -		     "a scalar", &boundary->where, array->rank - 1); | 
| -	  return FAILURE; | 
| +	  if (gfc_check_conformance (shift, boundary, | 
| +				     "arguments '%s' and '%s' for " | 
| +				     "intrinsic %s", | 
| +				     gfc_current_intrinsic_arg[1], | 
| +				     gfc_current_intrinsic_arg[2], | 
| +				     gfc_current_intrinsic ) == FAILURE) | 
| +	    return FAILURE; | 
| } | 
| - | 
| -      if (shift->rank == boundary->rank) | 
| +      else | 
| { | 
| -	  int i; | 
| -	  for (i = 0; i < shift->rank; i++) | 
| -	    if (! identical_dimen_shape (shift, i, boundary, i)) | 
| -	      { | 
| -		gfc_error ("Different shape in dimension %d for SHIFT and " | 
| -			   "BOUNDARY arguments of EOSHIFT at %L", shift->rank, | 
| -			   &boundary->where); | 
| -		return FAILURE; | 
| -	      } | 
| +	  gfc_error ("'%s' argument of intrinsic '%s' at %L of must have " | 
| +		     "rank %d or be a scalar", gfc_current_intrinsic_arg[1], | 
| +		     gfc_current_intrinsic, &shift->where, array->rank - 1); | 
| +	  return FAILURE; | 
| } | 
| } | 
|  | 
| -  if (dim_check (dim, 4, true) == FAILURE) | 
| -    return FAILURE; | 
| - | 
| return SUCCESS; | 
| } | 
|  | 
| @@ -1155,6 +1316,23 @@ gfc_check_fn_rc (gfc_expr *a) | 
|  | 
|  | 
| gfc_try | 
| +gfc_check_fn_rc2008 (gfc_expr *a) | 
| +{ | 
| +  if (real_or_complex_check (a, 0) == FAILURE) | 
| +    return FAILURE; | 
| + | 
| +  if (a->ts.type == BT_COMPLEX | 
| +      && gfc_notify_std (GFC_STD_F2008, "Fortran 2008: COMPLEX argument '%s' " | 
| +			 "argument of '%s' intrinsic at %L", | 
| +			 gfc_current_intrinsic_arg[0], gfc_current_intrinsic, | 
| +			 &a->where) == FAILURE) | 
| +    return FAILURE; | 
| + | 
| +  return SUCCESS; | 
| +} | 
| + | 
| + | 
| +gfc_try | 
| gfc_check_fnum (gfc_expr *unit) | 
| { | 
| if (type_check (unit, 0, BT_INTEGER) == FAILURE) | 
| @@ -1222,19 +1400,6 @@ gfc_check_iand (gfc_expr *i, gfc_expr *j) | 
|  | 
|  | 
| gfc_try | 
| -gfc_check_ibclr (gfc_expr *i, gfc_expr *pos) | 
| -{ | 
| -  if (type_check (i, 0, BT_INTEGER) == FAILURE) | 
| -    return FAILURE; | 
| - | 
| -  if (type_check (pos, 1, BT_INTEGER) == FAILURE) | 
| -    return FAILURE; | 
| - | 
| -  return SUCCESS; | 
| -} | 
| - | 
| - | 
| -gfc_try | 
| gfc_check_ibits (gfc_expr *i, gfc_expr *pos, gfc_expr *len) | 
| { | 
| if (type_check (i, 0, BT_INTEGER) == FAILURE) | 
| @@ -1246,17 +1411,13 @@ gfc_check_ibits (gfc_expr *i, gfc_expr *pos, gfc_expr *len) | 
| if (type_check (len, 2, BT_INTEGER) == FAILURE) | 
| return FAILURE; | 
|  | 
| -  return SUCCESS; | 
| -} | 
| - | 
| +  if (nonnegative_check ("pos", pos) == FAILURE) | 
| +    return FAILURE; | 
|  | 
| -gfc_try | 
| -gfc_check_ibset (gfc_expr *i, gfc_expr *pos) | 
| -{ | 
| -  if (type_check (i, 0, BT_INTEGER) == FAILURE) | 
| +  if (nonnegative_check ("len", len) == FAILURE) | 
| return FAILURE; | 
|  | 
| -  if (type_check (pos, 1, BT_INTEGER) == FAILURE) | 
| +  if (less_than_bitsize2 ("i", i, "pos", pos, "len", len) == FAILURE) | 
| return FAILURE; | 
|  | 
| return SUCCESS; | 
| @@ -1296,12 +1457,12 @@ gfc_check_ichar_iachar (gfc_expr *c, gfc_expr *kind) | 
| { | 
| /* Check that the argument is length one.  Non-constant lengths | 
| can't be checked here, so assume they are ok.  */ | 
| -	  if (c->ts.cl && c->ts.cl->length) | 
| +	  if (c->ts.u.cl && c->ts.u.cl->length) | 
| { | 
| /* If we already have a length for this expression then use it.  */ | 
| -	      if (c->ts.cl->length->expr_type != EXPR_CONSTANT) | 
| +	      if (c->ts.u.cl->length->expr_type != EXPR_CONSTANT) | 
| return SUCCESS; | 
| -	      i = mpz_get_si (c->ts.cl->length->value.integer); | 
| +	      i = mpz_get_si (c->ts.u.cl->length->value.integer); | 
| } | 
| else | 
| return SUCCESS; | 
| @@ -1525,14 +1686,11 @@ gfc_check_lbound (gfc_expr *array, gfc_expr *dim, gfc_expr *kind) | 
| if (array_check (array, 0) == FAILURE) | 
| return FAILURE; | 
|  | 
| -  if (dim != NULL) | 
| -    { | 
| -      if (dim_check (dim, 1, false) == FAILURE) | 
| -	return FAILURE; | 
| +  if (dim_check (dim, 1, false) == FAILURE) | 
| +    return FAILURE; | 
|  | 
| -      if (dim_rank_check (dim, array, 1) == FAILURE) | 
| -	return FAILURE; | 
| -    } | 
| +  if (dim_rank_check (dim, array, 1) == FAILURE) | 
| +    return FAILURE; | 
|  | 
| if (kind_check (kind, 2, BT_INTEGER) == FAILURE) | 
| return FAILURE; | 
| @@ -1732,13 +1890,11 @@ check_rest (bt type, int kind, gfc_actual_arglist *arglist) | 
| } | 
|  | 
| for (tmp = arglist, m=1; tmp != arg; tmp = tmp->next, m++) | 
| -        { | 
| -	  char buffer[80]; | 
| -	  snprintf (buffer, 80, "arguments 'a%d' and 'a%d' for intrinsic '%s'", | 
| -		    m, n, gfc_current_intrinsic); | 
| -	  if (gfc_check_conformance (buffer, tmp->expr, x) == FAILURE) | 
| +	if (gfc_check_conformance (tmp->expr, x, | 
| +				   "arguments 'a%d' and 'a%d' for " | 
| +				   "intrinsic '%s'", m, n, | 
| +				   gfc_current_intrinsic) == FAILURE) | 
| return FAILURE; | 
| -	} | 
| } | 
|  | 
| return SUCCESS; | 
| @@ -1918,24 +2074,22 @@ gfc_check_minloc_maxloc (gfc_actual_arglist *ap) | 
| ap->next->next->expr = m; | 
| } | 
|  | 
| -  if (d && dim_check (d, 1, false) == FAILURE) | 
| +  if (dim_check (d, 1, false) == FAILURE) | 
| return FAILURE; | 
|  | 
| -  if (d && dim_rank_check (d, a, 0) == FAILURE) | 
| +  if (dim_rank_check (d, a, 0) == FAILURE) | 
| return FAILURE; | 
|  | 
| if (m != NULL && type_check (m, 2, BT_LOGICAL) == FAILURE) | 
| return FAILURE; | 
|  | 
| -  if (m != NULL) | 
| -    { | 
| -      char buffer[80]; | 
| -      snprintf (buffer, 80, "arguments '%s' and '%s' for intrinsic %s", | 
| -		gfc_current_intrinsic_arg[0], gfc_current_intrinsic_arg[2], | 
| -		gfc_current_intrinsic); | 
| -      if (gfc_check_conformance (buffer, a, m) == FAILURE) | 
| -	return FAILURE; | 
| -    } | 
| +  if (m != NULL | 
| +      && gfc_check_conformance (a, m, | 
| +				"arguments '%s' and '%s' for intrinsic %s", | 
| +				gfc_current_intrinsic_arg[0], | 
| +				gfc_current_intrinsic_arg[2], | 
| +				gfc_current_intrinsic ) == FAILURE) | 
| +    return FAILURE; | 
|  | 
| return SUCCESS; | 
| } | 
| @@ -1974,24 +2128,22 @@ check_reduction (gfc_actual_arglist *ap) | 
| ap->next->next->expr = m; | 
| } | 
|  | 
| -  if (d && dim_check (d, 1, false) == FAILURE) | 
| +  if (dim_check (d, 1, false) == FAILURE) | 
| return FAILURE; | 
|  | 
| -  if (d && dim_rank_check (d, a, 0) == FAILURE) | 
| +  if (dim_rank_check (d, a, 0) == FAILURE) | 
| return FAILURE; | 
|  | 
| if (m != NULL && type_check (m, 2, BT_LOGICAL) == FAILURE) | 
| return FAILURE; | 
|  | 
| -  if (m != NULL) | 
| -    { | 
| -      char buffer[80]; | 
| -      snprintf (buffer, 80, "arguments '%s' and '%s' for intrinsic %s", | 
| -		gfc_current_intrinsic_arg[0], gfc_current_intrinsic_arg[2], | 
| -		gfc_current_intrinsic); | 
| -      if (gfc_check_conformance (buffer, a, m) == FAILURE) | 
| -	return FAILURE; | 
| -    } | 
| +  if (m != NULL | 
| +      && gfc_check_conformance (a, m, | 
| +				"arguments '%s' and '%s' for intrinsic %s", | 
| +				gfc_current_intrinsic_arg[0], | 
| +				gfc_current_intrinsic_arg[2], | 
| +				gfc_current_intrinsic) == FAILURE) | 
| +    return FAILURE; | 
|  | 
| return SUCCESS; | 
| } | 
| @@ -2043,9 +2195,6 @@ gfc_check_move_alloc (gfc_expr *from, gfc_expr *to) | 
| if (variable_check (from, 0) == FAILURE) | 
| return FAILURE; | 
|  | 
| -  if (array_check (from, 0) == FAILURE) | 
| -    return FAILURE; | 
| - | 
| attr = gfc_variable_attr (from, NULL); | 
| if (!attr.allocatable) | 
| { | 
| @@ -2058,9 +2207,6 @@ gfc_check_move_alloc (gfc_expr *from, gfc_expr *to) | 
| if (variable_check (to, 0) == FAILURE) | 
| return FAILURE; | 
|  | 
| -  if (array_check (to, 0) == FAILURE) | 
| -    return FAILURE; | 
| - | 
| attr = gfc_variable_attr (to, NULL); | 
| if (!attr.allocatable) | 
| { | 
| @@ -2070,7 +2216,7 @@ gfc_check_move_alloc (gfc_expr *from, gfc_expr *to) | 
| return FAILURE; | 
| } | 
|  | 
| -  if (same_type_check (from, 0, to, 1) == FAILURE) | 
| +  if (same_type_check (to, 1, from, 0) == FAILURE) | 
| return FAILURE; | 
|  | 
| if (to->rank != from->rank) | 
| @@ -2146,29 +2292,78 @@ gfc_check_null (gfc_expr *mold) | 
| gfc_try | 
| gfc_check_pack (gfc_expr *array, gfc_expr *mask, gfc_expr *vector) | 
| { | 
| -  char buffer[80]; | 
| - | 
| if (array_check (array, 0) == FAILURE) | 
| return FAILURE; | 
|  | 
| if (type_check (mask, 1, BT_LOGICAL) == FAILURE) | 
| return FAILURE; | 
|  | 
| -  snprintf (buffer, 80, "arguments '%s' and '%s' for intrinsic '%s'", | 
| -	    gfc_current_intrinsic_arg[0], gfc_current_intrinsic_arg[1], | 
| -	    gfc_current_intrinsic); | 
| -  if (gfc_check_conformance (buffer, array, mask) == FAILURE) | 
| +  if (gfc_check_conformance (array, mask, | 
| +			     "arguments '%s' and '%s' for intrinsic '%s'", | 
| +			     gfc_current_intrinsic_arg[0], | 
| +			     gfc_current_intrinsic_arg[1], | 
| +			     gfc_current_intrinsic) == FAILURE) | 
| return FAILURE; | 
|  | 
| if (vector != NULL) | 
| { | 
| +      mpz_t array_size, vector_size; | 
| +      bool have_array_size, have_vector_size; | 
| + | 
| if (same_type_check (array, 0, vector, 2) == FAILURE) | 
| return FAILURE; | 
|  | 
| if (rank_check (vector, 2, 1) == FAILURE) | 
| return FAILURE; | 
|  | 
| -      /* TODO: More constraints here.  */ | 
| +      /* VECTOR requires at least as many elements as MASK | 
| +         has .TRUE. values.  */ | 
| +      have_array_size = gfc_array_size (array, &array_size) == SUCCESS; | 
| +      have_vector_size = gfc_array_size (vector, &vector_size) == SUCCESS; | 
| + | 
| +      if (have_vector_size | 
| +	  && (mask->expr_type == EXPR_ARRAY | 
| +	      || (mask->expr_type == EXPR_CONSTANT | 
| +		  && have_array_size))) | 
| +	{ | 
| +	  int mask_true_values = 0; | 
| + | 
| +	  if (mask->expr_type == EXPR_ARRAY) | 
| +	    { | 
| +	      gfc_constructor *mask_ctor = mask->value.constructor; | 
| +	      while (mask_ctor) | 
| +		{ | 
| +		  if (mask_ctor->expr->expr_type != EXPR_CONSTANT) | 
| +		    { | 
| +		      mask_true_values = 0; | 
| +		      break; | 
| +		    } | 
| + | 
| +		  if (mask_ctor->expr->value.logical) | 
| +		    mask_true_values++; | 
| + | 
| +		  mask_ctor = mask_ctor->next; | 
| +		} | 
| +	    } | 
| +	  else if (mask->expr_type == EXPR_CONSTANT && mask->value.logical) | 
| +	    mask_true_values = mpz_get_si (array_size); | 
| + | 
| +	  if (mpz_get_si (vector_size) < mask_true_values) | 
| +	    { | 
| +	      gfc_error ("'%s' argument of '%s' intrinsic at %L must " | 
| +			 "provide at least as many elements as there " | 
| +			 "are .TRUE. values in '%s' (%ld/%d)", | 
| +			 gfc_current_intrinsic_arg[2],gfc_current_intrinsic, | 
| +			 &vector->where, gfc_current_intrinsic_arg[1], | 
| +			 mpz_get_si (vector_size), mask_true_values); | 
| +	      return FAILURE; | 
| +	    } | 
| +	} | 
| + | 
| +      if (have_array_size) | 
| +	mpz_clear (array_size); | 
| +      if (have_vector_size) | 
| +	mpz_clear (vector_size); | 
| } | 
|  | 
| return SUCCESS; | 
| @@ -2337,7 +2532,7 @@ gfc_check_reshape (gfc_expr *source, gfc_expr *shape, | 
| { | 
| mpz_t size; | 
| mpz_t nelems; | 
| -  int m; | 
| +  int shape_size; | 
|  | 
| if (array_check (source, 0) == FAILURE) | 
| return FAILURE; | 
| @@ -2355,26 +2550,121 @@ gfc_check_reshape (gfc_expr *source, gfc_expr *shape, | 
| return FAILURE; | 
| } | 
|  | 
| -  m = mpz_cmp_ui (size, GFC_MAX_DIMENSIONS); | 
| +  shape_size = mpz_get_ui (size); | 
| mpz_clear (size); | 
|  | 
| -  if (m > 0) | 
| +  if (shape_size <= 0) | 
| +    { | 
| +      gfc_error ("'%s' argument of '%s' intrinsic at %L is empty", | 
| +		 gfc_current_intrinsic_arg[1], gfc_current_intrinsic, | 
| +		 &shape->where); | 
| +      return FAILURE; | 
| +    } | 
| +  else if (shape_size > GFC_MAX_DIMENSIONS) | 
| { | 
| gfc_error ("'shape' argument of 'reshape' intrinsic at %L has more " | 
| "than %d elements", &shape->where, GFC_MAX_DIMENSIONS); | 
| return FAILURE; | 
| } | 
| +  else if (shape->expr_type == EXPR_ARRAY) | 
| +    { | 
| +      gfc_expr *e; | 
| +      int i, extent; | 
| +      for (i = 0; i < shape_size; ++i) | 
| +	{ | 
| +	  e = gfc_get_array_element (shape, i); | 
| +	  if (e->expr_type != EXPR_CONSTANT) | 
| +	    { | 
| +	      gfc_free_expr (e); | 
| +	      continue; | 
| +	    } | 
| + | 
| +	  gfc_extract_int (e, &extent); | 
| +	  if (extent < 0) | 
| +	    { | 
| +	      gfc_error ("'%s' argument of '%s' intrinsic at %L has " | 
| +			 "negative element (%d)", gfc_current_intrinsic_arg[1], | 
| +			 gfc_current_intrinsic, &e->where, extent); | 
| +	      return FAILURE; | 
| +	    } | 
| + | 
| +	  gfc_free_expr (e); | 
| +	} | 
| +    } | 
|  | 
| if (pad != NULL) | 
| { | 
| if (same_type_check (source, 0, pad, 2) == FAILURE) | 
| return FAILURE; | 
| + | 
| if (array_check (pad, 2) == FAILURE) | 
| return FAILURE; | 
| } | 
|  | 
| -  if (order != NULL && array_check (order, 3) == FAILURE) | 
| -    return FAILURE; | 
| +  if (order != NULL) | 
| +    { | 
| +      if (array_check (order, 3) == FAILURE) | 
| +	return FAILURE; | 
| + | 
| +      if (type_check (order, 3, BT_INTEGER) == FAILURE) | 
| +	return FAILURE; | 
| + | 
| +      if (order->expr_type == EXPR_ARRAY) | 
| +	{ | 
| +	  int i, order_size, dim, perm[GFC_MAX_DIMENSIONS]; | 
| +	  gfc_expr *e; | 
| + | 
| +	  for (i = 0; i < GFC_MAX_DIMENSIONS; ++i) | 
| +	    perm[i] = 0; | 
| + | 
| +	  gfc_array_size (order, &size); | 
| +	  order_size = mpz_get_ui (size); | 
| +	  mpz_clear (size); | 
| + | 
| +	  if (order_size != shape_size) | 
| +	    { | 
| +	      gfc_error ("'%s' argument of '%s' intrinsic at %L " | 
| +			 "has wrong number of elements (%d/%d)", | 
| +			 gfc_current_intrinsic_arg[3], | 
| +			 gfc_current_intrinsic, &order->where, | 
| +			 order_size, shape_size); | 
| +	      return FAILURE; | 
| +	    } | 
| + | 
| +	  for (i = 1; i <= order_size; ++i) | 
| +	    { | 
| +	      e = gfc_get_array_element (order, i-1); | 
| +	      if (e->expr_type != EXPR_CONSTANT) | 
| +		{ | 
| +		  gfc_free_expr (e); | 
| +		  continue; | 
| +		} | 
| + | 
| +	      gfc_extract_int (e, &dim); | 
| + | 
| +	      if (dim < 1 || dim > order_size) | 
| +		{ | 
| +		  gfc_error ("'%s' argument of '%s' intrinsic at %L " | 
| +			     "has out-of-range dimension (%d)", | 
| +			     gfc_current_intrinsic_arg[3], | 
| +			     gfc_current_intrinsic, &e->where, dim); | 
| +		  return FAILURE; | 
| +		} | 
| + | 
| +	      if (perm[dim-1] != 0) | 
| +		{ | 
| +		  gfc_error ("'%s' argument of '%s' intrinsic at %L has " | 
| +			     "invalid permutation of dimensions (dimension " | 
| +			     "'%d' duplicated)", gfc_current_intrinsic_arg[3], | 
| +			     gfc_current_intrinsic, &e->where, dim); | 
| +		  return FAILURE; | 
| +		} | 
| + | 
| +	      perm[dim-1] = 1; | 
| +	      gfc_free_expr (e); | 
| +	    } | 
| +	} | 
| +    } | 
|  | 
| if (pad == NULL && shape->expr_type == EXPR_ARRAY | 
| && gfc_is_constant_expr (shape) | 
| @@ -2411,6 +2701,46 @@ gfc_check_reshape (gfc_expr *source, gfc_expr *shape, | 
|  | 
|  | 
| gfc_try | 
| +gfc_check_same_type_as (gfc_expr *a, gfc_expr *b) | 
| +{ | 
| + | 
| +  if (a->ts.type != BT_DERIVED && a->ts.type != BT_CLASS) | 
| +    { | 
| +      gfc_error ("'%s' argument of '%s' intrinsic at %L " | 
| +		 "must be of a derived type", gfc_current_intrinsic_arg[0], | 
| +		 gfc_current_intrinsic, &a->where); | 
| +      return FAILURE; | 
| +    } | 
| + | 
| +  if (!gfc_type_is_extensible (a->ts.u.derived)) | 
| +    { | 
| +      gfc_error ("'%s' argument of '%s' intrinsic at %L " | 
| +		 "must be of an extensible type", gfc_current_intrinsic_arg[0], | 
| +		 gfc_current_intrinsic, &a->where); | 
| +      return FAILURE; | 
| +    } | 
| + | 
| +  if (b->ts.type != BT_DERIVED && b->ts.type != BT_CLASS) | 
| +    { | 
| +      gfc_error ("'%s' argument of '%s' intrinsic at %L " | 
| +		 "must be of a derived type", gfc_current_intrinsic_arg[1], | 
| +		 gfc_current_intrinsic, &b->where); | 
| +      return FAILURE; | 
| +    } | 
| + | 
| +  if (!gfc_type_is_extensible (b->ts.u.derived)) | 
| +    { | 
| +      gfc_error ("'%s' argument of '%s' intrinsic at %L " | 
| +		 "must be of an extensible type", gfc_current_intrinsic_arg[1], | 
| +		 gfc_current_intrinsic, &b->where); | 
| +      return FAILURE; | 
| +    } | 
| + | 
| +  return SUCCESS; | 
| +} | 
| + | 
| + | 
| +gfc_try | 
| gfc_check_scale (gfc_expr *x, gfc_expr *i) | 
| { | 
| if (type_check (x, 0, BT_REAL) == FAILURE) | 
| @@ -2505,11 +2835,23 @@ gfc_check_selected_real_kind (gfc_expr *p, gfc_expr *r) | 
| return FAILURE; | 
| } | 
|  | 
| -  if (p != NULL && type_check (p, 0, BT_INTEGER) == FAILURE) | 
| -    return FAILURE; | 
| +  if (p) | 
| +    { | 
| +      if (type_check (p, 0, BT_INTEGER) == FAILURE) | 
| +	return FAILURE; | 
|  | 
| -  if (r != NULL && type_check (r, 1, BT_INTEGER) == FAILURE) | 
| -    return FAILURE; | 
| +      if (scalar_check (p, 0) == FAILURE) | 
| +	return FAILURE; | 
| +    } | 
| + | 
| +  if (r) | 
| +    { | 
| +      if (type_check (r, 1, BT_INTEGER) == FAILURE) | 
| +	return FAILURE; | 
| + | 
| +      if (scalar_check (r, 1) == FAILURE) | 
| +	return FAILURE; | 
| +    } | 
|  | 
| return SUCCESS; | 
| } | 
| @@ -2568,14 +2910,11 @@ gfc_check_size (gfc_expr *array, gfc_expr *dim, gfc_expr *kind) | 
| if (array_check (array, 0) == FAILURE) | 
| return FAILURE; | 
|  | 
| -  if (dim != NULL) | 
| -    { | 
| -      if (dim_check (dim, 1, true) == FAILURE) | 
| -	return FAILURE; | 
| +  if (dim_check (dim, 1, true) == FAILURE) | 
| +    return FAILURE; | 
|  | 
| -      if (dim_rank_check (dim, array, 0) == FAILURE) | 
| -	return FAILURE; | 
| -    } | 
| +  if (dim_rank_check (dim, array, 0) == FAILURE) | 
| +    return FAILURE; | 
|  | 
| if (kind_check (kind, 2, BT_INTEGER) == FAILURE) | 
| return FAILURE; | 
| @@ -2627,6 +2966,18 @@ gfc_check_spread (gfc_expr *source, gfc_expr *dim, gfc_expr *ncopies) | 
| if (dim_check (dim, 1, false) == FAILURE) | 
| return FAILURE; | 
|  | 
| +  /* dim_rank_check() does not apply here.  */ | 
| +  if (dim | 
| +      && dim->expr_type == EXPR_CONSTANT | 
| +      && (mpz_cmp_ui (dim->value.integer, 1) < 0 | 
| +	  || mpz_cmp_ui (dim->value.integer, source->rank + 1) > 0)) | 
| +    { | 
| +      gfc_error ("'%s' argument of '%s' intrinsic at %L is not a valid " | 
| +		 "dimension index", gfc_current_intrinsic_arg[1], | 
| +		 gfc_current_intrinsic, &dim->where); | 
| +      return FAILURE; | 
| +    } | 
| + | 
| if (type_check (ncopies, 2, BT_INTEGER) == FAILURE) | 
| return FAILURE; | 
|  | 
| @@ -2911,14 +3262,11 @@ gfc_check_ubound (gfc_expr *array, gfc_expr *dim, gfc_expr *kind) | 
| if (array_check (array, 0) == FAILURE) | 
| return FAILURE; | 
|  | 
| -  if (dim != NULL) | 
| -    { | 
| -      if (dim_check (dim, 1, false) == FAILURE) | 
| -	return FAILURE; | 
| +  if (dim_check (dim, 1, false) == FAILURE) | 
| +    return FAILURE; | 
|  | 
| -      if (dim_rank_check (dim, array, 0) == FAILURE) | 
| -	return FAILURE; | 
| -    } | 
| +  if (dim_rank_check (dim, array, 0) == FAILURE) | 
| +    return FAILURE; | 
|  | 
| if (kind_check (kind, 2, BT_INTEGER) == FAILURE) | 
| return FAILURE; | 
| @@ -2934,6 +3282,8 @@ gfc_check_ubound (gfc_expr *array, gfc_expr *dim, gfc_expr *kind) | 
| gfc_try | 
| gfc_check_unpack (gfc_expr *vector, gfc_expr *mask, gfc_expr *field) | 
| { | 
| +  mpz_t vector_size; | 
| + | 
| if (rank_check (vector, 0, 1) == FAILURE) | 
| return FAILURE; | 
|  | 
| @@ -2946,10 +3296,45 @@ gfc_check_unpack (gfc_expr *vector, gfc_expr *mask, gfc_expr *field) | 
| if (same_type_check (vector, 0, field, 2) == FAILURE) | 
| return FAILURE; | 
|  | 
| +  if (mask->expr_type == EXPR_ARRAY | 
| +      && gfc_array_size (vector, &vector_size) == SUCCESS) | 
| +    { | 
| +      int mask_true_count = 0; | 
| +      gfc_constructor *mask_ctor = mask->value.constructor; | 
| +      while (mask_ctor) | 
| +	{ | 
| +	  if (mask_ctor->expr->expr_type != EXPR_CONSTANT) | 
| +	    { | 
| +	      mask_true_count = 0; | 
| +	      break; | 
| +	    } | 
| + | 
| +	  if (mask_ctor->expr->value.logical) | 
| +	    mask_true_count++; | 
| + | 
| +	  mask_ctor = mask_ctor->next; | 
| +	} | 
| + | 
| +      if (mpz_get_si (vector_size) < mask_true_count) | 
| +	{ | 
| +	  gfc_error ("'%s' argument of '%s' intrinsic at %L must " | 
| +		     "provide at least as many elements as there " | 
| +		     "are .TRUE. values in '%s' (%ld/%d)", | 
| +		     gfc_current_intrinsic_arg[0], gfc_current_intrinsic, | 
| +		     &vector->where, gfc_current_intrinsic_arg[1], | 
| +		     mpz_get_si (vector_size), mask_true_count); | 
| +	  return FAILURE; | 
| +	} | 
| + | 
| +      mpz_clear (vector_size); | 
| +    } | 
| + | 
| if (mask->rank != field->rank && field->rank != 0) | 
| { | 
| -      gfc_error ("FIELD argument at %L of UNPACK must have the same rank as " | 
| -		 "MASK or be a scalar", &field->where); | 
| +      gfc_error ("'%s' argument of '%s' intrinsic at %L must have " | 
| +		 "the same rank as '%s' or be a scalar", | 
| +		 gfc_current_intrinsic_arg[2], gfc_current_intrinsic, | 
| +		 &field->where, gfc_current_intrinsic_arg[1]); | 
| return FAILURE; | 
| } | 
|  | 
| @@ -2959,9 +3344,11 @@ gfc_check_unpack (gfc_expr *vector, gfc_expr *mask, gfc_expr *field) | 
| for (i = 0; i < field->rank; i++) | 
| if (! identical_dimen_shape (mask, i, field, i)) | 
| { | 
| -	  gfc_error ("Different shape in dimension %d for MASK and FIELD " | 
| -		     "arguments of UNPACK at %L", mask->rank, &field->where); | 
| -	  return FAILURE; | 
| +	  gfc_error ("'%s' and '%s' arguments of '%s' intrinsic at %L " | 
| +		     "must have identical shape.", | 
| +		     gfc_current_intrinsic_arg[2], | 
| +		     gfc_current_intrinsic_arg[1], gfc_current_intrinsic, | 
| +		     &field->where); | 
| } | 
| } | 
|  | 
| @@ -3127,6 +3514,22 @@ gfc_check_mvbits (gfc_expr *from, gfc_expr *frompos, gfc_expr *len, | 
| if (type_check (topos, 4, BT_INTEGER) == FAILURE) | 
| return FAILURE; | 
|  | 
| +  if (nonnegative_check ("frompos", frompos) == FAILURE) | 
| +    return FAILURE; | 
| + | 
| +  if (nonnegative_check ("topos", topos) == FAILURE) | 
| +    return FAILURE; | 
| + | 
| +  if (nonnegative_check ("len", len) == FAILURE) | 
| +    return FAILURE; | 
| + | 
| +  if (less_than_bitsize2 ("from", from, "frompos", frompos, "len", len) | 
| +      == FAILURE) | 
| +    return FAILURE; | 
| + | 
| +  if (less_than_bitsize2 ("to", to, "topos", topos, "len", len) == FAILURE) | 
| +    return FAILURE; | 
| + | 
| return SUCCESS; | 
| } | 
|  | 
|  |