Index: gcc/libgfortran/intrinsics/unpack_generic.c |
diff --git a/gcc/libgfortran/intrinsics/unpack_generic.c b/gcc/libgfortran/intrinsics/unpack_generic.c |
index a27e37c7272e71a6630fed068d2565d0de9a33aa..2dcef78001e8daa974c4bdc73f01bc2640f72788 100644 |
--- a/gcc/libgfortran/intrinsics/unpack_generic.c |
+++ b/gcc/libgfortran/intrinsics/unpack_generic.c |
@@ -28,10 +28,36 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
#include <assert.h> |
#include <string.h> |
+/* All the bounds checking for unpack in one function. If field is NULL, |
+ we don't check it, for the unpack0 functions. */ |
+ |
+static void |
+unpack_bounds (gfc_array_char *ret, const gfc_array_char *vector, |
+ const gfc_array_l1 *mask, const gfc_array_char *field) |
+{ |
+ index_type vec_size, mask_count; |
+ vec_size = size0 ((array_t *) vector); |
+ mask_count = count_0 (mask); |
+ if (vec_size < mask_count) |
+ runtime_error ("Incorrect size of return value in UNPACK" |
+ " intrinsic: should be at least %ld, is" |
+ " %ld", (long int) mask_count, |
+ (long int) vec_size); |
+ |
+ if (field != NULL) |
+ bounds_equal_extents ((array_t *) field, (array_t *) mask, |
+ "FIELD", "UNPACK"); |
+ |
+ if (ret->data != NULL) |
+ bounds_equal_extents ((array_t *) ret, (array_t *) mask, |
+ "return value", "UNPACK"); |
+ |
+} |
+ |
static void |
unpack_internal (gfc_array_char *ret, const gfc_array_char *vector, |
const gfc_array_l1 *mask, const gfc_array_char *field, |
- index_type size, index_type fsize) |
+ index_type size) |
{ |
/* r.* indicates the return array. */ |
index_type rstride[GFC_MAX_DIMENSIONS]; |
@@ -89,14 +115,13 @@ unpack_internal (gfc_array_char *ret, const gfc_array_char *vector, |
for (n = 0; n < dim; n++) |
{ |
count[n] = 0; |
- ret->dim[n].stride = rs; |
- ret->dim[n].lbound = 0; |
- ret->dim[n].ubound = mask->dim[n].ubound - mask->dim[n].lbound; |
- extent[n] = ret->dim[n].ubound + 1; |
+ GFC_DIMENSION_SET(ret->dim[n], 0, |
+ GFC_DESCRIPTOR_EXTENT(mask,n) - 1, rs); |
+ extent[n] = GFC_DESCRIPTOR_EXTENT(ret,n); |
empty = empty || extent[n] <= 0; |
- rstride[n] = ret->dim[n].stride * size; |
- fstride[n] = field->dim[n].stride * fsize; |
- mstride[n] = mask->dim[n].stride * mask_kind; |
+ rstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(ret, n); |
+ fstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(field, n); |
+ mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask, n); |
rs *= extent[n]; |
} |
ret->offset = 0; |
@@ -108,27 +133,18 @@ unpack_internal (gfc_array_char *ret, const gfc_array_char *vector, |
for (n = 0; n < dim; n++) |
{ |
count[n] = 0; |
- extent[n] = ret->dim[n].ubound + 1 - ret->dim[n].lbound; |
+ extent[n] = GFC_DESCRIPTOR_EXTENT(ret,n); |
empty = empty || extent[n] <= 0; |
- rstride[n] = ret->dim[n].stride * size; |
- fstride[n] = field->dim[n].stride * fsize; |
- mstride[n] = mask->dim[n].stride * mask_kind; |
+ rstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(ret, n); |
+ fstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(field, n); |
+ mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask, n); |
} |
- if (rstride[0] == 0) |
- rstride[0] = size; |
} |
if (empty) |
return; |
- if (fstride[0] == 0) |
- fstride[0] = fsize; |
- if (mstride[0] == 0) |
- mstride[0] = 1; |
- |
- vstride0 = vector->dim[0].stride * size; |
- if (vstride0 == 0) |
- vstride0 = size; |
+ vstride0 = GFC_DESCRIPTOR_STRIDE_BYTES(vector,0); |
rstride0 = rstride[0]; |
fstride0 = fstride[0]; |
mstride0 = mstride[0]; |
@@ -194,6 +210,9 @@ unpack1 (gfc_array_char *ret, const gfc_array_char *vector, |
index_type type_size; |
index_type size; |
+ if (unlikely(compile_options.bounds_check)) |
+ unpack_bounds (ret, vector, mask, field); |
+ |
type_size = GFC_DTYPE_TYPE_SIZE (vector); |
size = GFC_DESCRIPTOR_SIZE (vector); |
@@ -326,8 +345,7 @@ unpack1 (gfc_array_char *ret, const gfc_array_char *vector, |
#endif |
} |
- unpack_internal (ret, vector, mask, field, size, |
- GFC_DESCRIPTOR_SIZE (field)); |
+ unpack_internal (ret, vector, mask, field, size); |
} |
@@ -342,9 +360,13 @@ unpack1_char (gfc_array_char *ret, |
GFC_INTEGER_4 ret_length __attribute__((unused)), |
const gfc_array_char *vector, const gfc_array_l1 *mask, |
const gfc_array_char *field, GFC_INTEGER_4 vector_length, |
- GFC_INTEGER_4 field_length) |
+ GFC_INTEGER_4 field_length __attribute__((unused))) |
{ |
- unpack_internal (ret, vector, mask, field, vector_length, field_length); |
+ |
+ if (unlikely(compile_options.bounds_check)) |
+ unpack_bounds (ret, vector, mask, field); |
+ |
+ unpack_internal (ret, vector, mask, field, vector_length); |
} |
@@ -359,11 +381,14 @@ unpack1_char4 (gfc_array_char *ret, |
GFC_INTEGER_4 ret_length __attribute__((unused)), |
const gfc_array_char *vector, const gfc_array_l1 *mask, |
const gfc_array_char *field, GFC_INTEGER_4 vector_length, |
- GFC_INTEGER_4 field_length) |
+ GFC_INTEGER_4 field_length __attribute__((unused))) |
{ |
+ |
+ if (unlikely(compile_options.bounds_check)) |
+ unpack_bounds (ret, vector, mask, field); |
+ |
unpack_internal (ret, vector, mask, field, |
- vector_length * sizeof (gfc_char4_t), |
- field_length * sizeof (gfc_char4_t)); |
+ vector_length * sizeof (gfc_char4_t)); |
} |
@@ -378,12 +403,13 @@ unpack0 (gfc_array_char *ret, const gfc_array_char *vector, |
gfc_array_char tmp; |
index_type type_size; |
- index_type size; |
+ |
+ if (unlikely(compile_options.bounds_check)) |
+ unpack_bounds (ret, vector, mask, NULL); |
type_size = GFC_DTYPE_TYPE_SIZE (vector); |
- size = GFC_DESCRIPTOR_SIZE (vector); |
- switch(type_size) |
+ switch (type_size) |
{ |
case GFC_DTYPE_LOGICAL_1: |
case GFC_DTYPE_INTEGER_1: |
@@ -513,7 +539,7 @@ unpack0 (gfc_array_char *ret, const gfc_array_char *vector, |
memset (&tmp, 0, sizeof (tmp)); |
tmp.dtype = 0; |
tmp.data = field; |
- unpack_internal (ret, vector, mask, &tmp, GFC_DESCRIPTOR_SIZE (vector), 0); |
+ unpack_internal (ret, vector, mask, &tmp, GFC_DESCRIPTOR_SIZE (vector)); |
} |
@@ -531,10 +557,13 @@ unpack0_char (gfc_array_char *ret, |
{ |
gfc_array_char tmp; |
+ if (unlikely(compile_options.bounds_check)) |
+ unpack_bounds (ret, vector, mask, NULL); |
+ |
memset (&tmp, 0, sizeof (tmp)); |
tmp.dtype = 0; |
tmp.data = field; |
- unpack_internal (ret, vector, mask, &tmp, vector_length, 0); |
+ unpack_internal (ret, vector, mask, &tmp, vector_length); |
} |
@@ -552,9 +581,12 @@ unpack0_char4 (gfc_array_char *ret, |
{ |
gfc_array_char tmp; |
+ if (unlikely(compile_options.bounds_check)) |
+ unpack_bounds (ret, vector, mask, NULL); |
+ |
memset (&tmp, 0, sizeof (tmp)); |
tmp.dtype = 0; |
tmp.data = field; |
unpack_internal (ret, vector, mask, &tmp, |
- vector_length * sizeof (gfc_char4_t), 0); |
+ vector_length * sizeof (gfc_char4_t)); |
} |