https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84065

Jakub Jelinek <jakub at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Priority|P3                          |P4
                 CC|                            |jakub at gcc dot gnu.org
   Target Milestone|---                         |8.0

--- Comment #2 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
I guess the testcase kind of assumes both 32-bit target and 32-bit host,
because on 64-bit host, 32-bit target we do:
1760                  HOST_WIDE_INT len = gfc_mpz_get_hwi
(sym->ts.u.cl->length->value.integer);
1761    
1762                  if (init->expr_type == EXPR_CONSTANT)
1763                    gfc_set_constant_character_len (len, init, -1);

and len is 0x100000004, i.e. larger than can fit into target's address space.
Which in the end means allocation of 0x100000004 * 4 bytes of memory, setting
that all to ' ' etc., and doing it for a bunch of similar strings.
Conceptually, it would be nice if the FE could represent more efficiently these
cases where there is just small amount of real data followed by a huge
repetition of something (in this case ' ').

Or, for this testcase, we could perhaps repeat the comparison that
resolve_charlen will do, and either don't create the initializer in that case,
or error right away.  The former is in:

--- decl.c.jj8  2018-01-23 21:35:04.000000000 +0100
+++ decl.c      2018-01-26 18:24:22.064763299 +0100
@@ -1757,22 +1757,32 @@ add_init_expr_to_sym (const char *name,
              if (!gfc_specification_expr (sym->ts.u.cl->length))
                return false;

-             HOST_WIDE_INT len = gfc_mpz_get_hwi
(sym->ts.u.cl->length->value.integer);
-
-             if (init->expr_type == EXPR_CONSTANT)
-               gfc_set_constant_character_len (len, init, -1);
-             else if (init->expr_type == EXPR_ARRAY)
+             int k = gfc_validate_kind (BT_INTEGER, gfc_charlen_int_kind,
+                                        false);
+             /* resolve_charlen will complain later on if the length
+                is too large.  Just skeep the initialization in that case.  */
+             if (mpz_cmp (sym->ts.u.cl->length->value.integer,
+                          gfc_integer_kinds[k].huge) <= 0)
                {
-                 gfc_constructor *c;
+                 HOST_WIDE_INT len
+                   = gfc_mpz_get_hwi (sym->ts.u.cl->length->value.integer);
+
+                 if (init->expr_type == EXPR_CONSTANT)
+                   gfc_set_constant_character_len (len, init, -1);
+                 else if (init->expr_type == EXPR_ARRAY)
+                   {
+                     gfc_constructor *c;

-                 /* Build a new charlen to prevent simplification from
-                    deleting the length before it is resolved.  */
-                 init->ts.u.cl = gfc_new_charlen (gfc_current_ns, NULL);
-                 init->ts.u.cl->length = gfc_copy_expr (sym->ts.u.cl->length);
+                     /* Build a new charlen to prevent simplification from
+                        deleting the length before it is resolved.  */
+                     init->ts.u.cl = gfc_new_charlen (gfc_current_ns, NULL);
+                     init->ts.u.cl->length
+                       = gfc_copy_expr (sym->ts.u.cl->length);

-                 for (c = gfc_constructor_first (init->value.constructor);
-                      c; c = gfc_constructor_next (c))
-                   gfc_set_constant_character_len (len, c->expr, -1);
+                     for (c = gfc_constructor_first (init->value.constructor);
+                          c; c = gfc_constructor_next (c))
+                       gfc_set_constant_character_len (len, c->expr, -1);
+                   }
                }
            }
        }

Reply via email to