Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(132)

Unified Diff: gcc/gcc/fortran/check.c

Issue 3050029: [gcc] GCC 4.5.0=>4.5.1 (Closed) Base URL: ssh://git@gitrw.chromium.org:9222/nacl-toolchain.git
Patch Set: Created 10 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « gcc/gcc/fortran/ChangeLog-2007 ('k') | gcc/gcc/fortran/decl.c » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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;
}
« no previous file with comments | « gcc/gcc/fortran/ChangeLog-2007 ('k') | gcc/gcc/fortran/decl.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698