aboutsummaryrefslogtreecommitdiff
path: root/gcc/fortran/check.c
diff options
context:
space:
mode:
authorDaniel Franke <franke.daniel@gmail.com>2009-06-06 14:51:29 -0400
committerTobias Burnus <burnus@gcc.gnu.org>2009-06-06 20:51:29 +0200
commit7ba8c18c1eb8ab48d44a9735c9974ae09b8dd9d4 (patch)
treefd5f22b85c7834a1bd7f940233ff37789a1b2dc3 /gcc/fortran/check.c
parentdbb0ce047b0299395e1f7140ec6474cf402498ca (diff)
downloadgcc-7ba8c18c1eb8ab48d44a9735c9974ae09b8dd9d4.zip
gcc-7ba8c18c1eb8ab48d44a9735c9974ae09b8dd9d4.tar.gz
gcc-7ba8c18c1eb8ab48d44a9735c9974ae09b8dd9d4.tar.bz2
re PR fortran/32890 (Compile-time detect of LHS/RHS missmatch for PACK)
fortran/ 2009-06-06 Daniel Franke <franke.daniel@gmail.com> PR fortran/32890 * intrinsic.h (gfc_simplify_pack): New prototype. * intrinsic.c (add_functions): Added simplifier-callback to PACK. * simplify.c (is_constant_array_expr): Moved to beginning of file. (gfc_simplify_pack): New. * check.c (gfc_check_pack): Check that VECTOR has enough elements. Added safeguards for empty arrays. testsuite/ 2009-06-06 Daniel Franke <franke.daniel@gmail.com> PR fortran/32890 * gfortran.dg/pack_assign_1.f90: New. * gfortran.dg/pack_vector_1.f90: New. From-SVN: r148237
Diffstat (limited to 'gcc/fortran/check.c')
-rw-r--r--gcc/fortran/check.c52
1 files changed, 51 insertions, 1 deletions
diff --git a/gcc/fortran/check.c b/gcc/fortran/check.c
index c4e33bb..b61909b 100644
--- a/gcc/fortran/check.c
+++ b/gcc/fortran/check.c
@@ -2149,13 +2149,63 @@ gfc_check_pack (gfc_expr *array, gfc_expr *mask, gfc_expr *vector)
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;