This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH,fortran] Fix PR 31244
- From: Steve Kargl <sgk at troutmask dot apl dot washington dot edu>
- To: fortran at gcc dot gnu dot org, gcc-patches at gcc dot gnu dot org
- Date: Mon, 24 Sep 2007 15:11:22 -0700
- Subject: [PATCH,fortran] Fix PR 31244
The attached patch fixes PR 31244 by replacing an
unsigned int variable in gfc_data_value with a mpz_t
variable. The consequence is that the code from the
PR:
program main
integer(kind=1), dimension(4294967296_8) :: i
data i /4294967296_8 * 1_1/
print *,i(1)
end program main
now compiles. I'll note however that the above required
over an hour to compile, 4+GB of memory, and the loader
died with some strange error about bssv size exceeded.
I suspect that had ld completed its task, the executable
would have exceed 4 GB.
I had an alternative patch that put a sane limit on
the repeat count and documented this limit in manual.
Personally, I preferred this patch.
2007-09-24 Steven G. Kargl <kargl@gcc.gnu.org>
PR fortran/31244
* decl.c (free_value): Clear mpz value.
(top_val_list): Convert variable from unsigned int to mpz_t.
* gfortran.h (gfc_data_value): Ditto.
* resolve.c (struct values): Ditto
(next_data_value): Use mpz_t variable.
(check_data_variable): Ditto.
(resolve_data): Ditto.
--
Steve
Index: decl.c
===================================================================
--- decl.c (revision 128724)
+++ decl.c (working copy)
@@ -123,6 +123,7 @@ free_value (gfc_data_value *p)
for (; p; p = q)
{
q = p->next;
+ mpz_clear (p->repeat);
gfc_free_expr (p->expr);
gfc_free (p);
}
@@ -372,7 +373,6 @@ top_val_list (gfc_data *data)
{
gfc_data_value *new, *tail;
gfc_expr *expr;
- const char *msg;
match m;
tail = NULL;
@@ -386,6 +386,7 @@ top_val_list (gfc_data *data)
return MATCH_ERROR;
new = gfc_get_data_value ();
+ mpz_init (new->repeat);
if (tail == NULL)
data->value = new;
@@ -397,19 +398,13 @@ top_val_list (gfc_data *data)
if (expr->ts.type != BT_INTEGER || gfc_match_char ('*') != MATCH_YES)
{
tail->expr = expr;
- tail->repeat = 1;
+ mpz_set_ui (tail->repeat, 1);
}
else
{
- signed int tmp;
- msg = gfc_extract_int (expr, &tmp);
+ if (expr->ts.type == BT_INTEGER)
+ mpz_set (tail->repeat, expr->value.integer);
gfc_free_expr (expr);
- if (msg != NULL)
- {
- gfc_error (msg);
- return MATCH_ERROR;
- }
- tail->repeat = tmp;
m = match_data_constant (&tail->expr);
if (m == MATCH_NO)
@@ -5954,6 +5949,51 @@ gfc_match_enum (void)
}
Index: gfortran.h
===================================================================
--- gfortran.h (revision 128724)
+++ gfortran.h (working copy)
@@ -1775,7 +1776,7 @@ gfc_data_variable;
typedef struct gfc_data_value
{
- unsigned int repeat;
+ mpz_t repeat;
gfc_expr *expr;
struct gfc_data_value *next;
}
Index: resolve.c
===================================================================
--- resolve.c (revision 128724)
+++ resolve.c (working copy)
@@ -7939,7 +7939,7 @@ resolve_symbol (gfc_symbol *sym)
static struct
{
gfc_data_value *vnode;
- unsigned int left;
+ mpz_t left;
}
values;
@@ -7949,13 +7949,14 @@ values;
static try
next_data_value (void)
{
- while (values.left == 0)
+
+ while (mpz_cmp_ui (values.left, 0) == 0)
{
if (values.vnode->next == NULL)
return FAILURE;
values.vnode = values.vnode->next;
- values.left = values.vnode->repeat;
+ mpz_set (values.left, values.vnode->repeat);
}
return SUCCESS;
@@ -8058,23 +8059,23 @@ check_data_variable (gfc_data_variable *
/* If we have more than one element left in the repeat count,
and we have more than one element left in the target variable,
then create a range assignment. */
- /* ??? Only done for full arrays for now, since array sections
+ /* FIXME: Only done for full arrays for now, since array sections
seem tricky. */
if (mark == AR_FULL && ref && ref->next == NULL
- && values.left > 1 && mpz_cmp_ui (size, 1) > 0)
+ && mpz_cmp_ui (values.left, 1) > 0 && mpz_cmp_ui (size, 1) > 0)
{
mpz_t range;
- if (mpz_cmp_ui (size, values.left) >= 0)
+ if (mpz_cmp (size, values.left) >= 0)
{
- mpz_init_set_ui (range, values.left);
- mpz_sub_ui (size, size, values.left);
- values.left = 0;
+ mpz_init_set (range, values.left);
+ mpz_sub (size, size, values.left);
+ mpz_set_ui (values.left, 0);
}
else
{
mpz_init_set (range, size);
- values.left -= mpz_get_ui (size);
+ mpz_sub (values.left, values.left, size);
mpz_set_ui (size, 0);
}
@@ -8088,7 +8089,7 @@ check_data_variable (gfc_data_variable *
/* Assign initial value to symbol. */
else
{
- values.left -= 1;
+ mpz_sub_ui (values.left, values.left, 1);
mpz_sub_ui (size, size, 1);
t = gfc_assign_data_value (var->expr, values.vnode->expr, offset);
@@ -8261,13 +8262,17 @@ resolve_data_variables (gfc_data_variabl
variables list, expanding iterators and such. */
static void
-resolve_data (gfc_data * d)
+resolve_data (gfc_data *d)
{
+
if (resolve_data_variables (d->var) == FAILURE)
return;
values.vnode = d->value;
- values.left = (d->value == NULL) ? 0 : d->value->repeat;
+ if (d->value == NULL)
+ mpz_set_ui (values.left, 0);
+ else
+ mpz_set (values.left, d->value->repeat);
if (traverse_data_var (d->var, &d->where) == FAILURE)
return;