------- Comment #1 from fxcoudert at gcc dot gnu dot org  2007-02-01 13:51 
-------
With a little variation, you get a better error message, although "augument"
part could be improved :)

$ cat u.f90
  integer :: i
  i = -1
  print *, repeat ("", i)
  end
$ gfortran u.f90 && ./a.out
Fortran runtime error: Augument NCOPIES is negative.

The following patch removes the check from the library, and makes the front-end
generate it instead: removes the weird error message, adds error location, more
easily optimized away.

More important: examination of the generated code revealed that REPEAT
evaluates it ncopies arguments multiple times (up to 3 times), which is
wrong-code:

  integer :: i
  i = -1
  print *, repeat ("a", f())
contains
  integer function f()
    integer :: x = 5
    save x

    x = x - 1
    f = x
  end function f
end

The above code prints out "aa" instead of "aaaa"; it segfaults if "x = 5" is
changed into "x = 3", for example. The patch below does also fix this
wrong-code issue. (We're not alone on this one, I found the same bug in Sun and
Portland compilers)



Index: gcc/fortran/trans-intrinsic.c
===================================================================
--- gcc/fortran/trans-intrinsic.c       (revision 121280)
+++ gcc/fortran/trans-intrinsic.c       (working copy)
@@ -3357,18 +3357,32 @@
   tree ncopies;
   tree var;
   tree type;
+  tree cond;

   args = gfc_conv_intrinsic_function_args (se, expr);
   len = TREE_VALUE (args);
   tmp = gfc_advance_chain (args, 2);
   ncopies = TREE_VALUE (tmp);
+
+  /* Check that ncopies is not negative.  */
+  ncopies = gfc_evaluate_now (ncopies, &se->pre);
+  cond = fold_build2 (LT_EXPR, boolean_type_node, ncopies,
+                     build_int_cst (TREE_TYPE (ncopies), 0));
+  gfc_trans_runtime_check (cond,
+                          "Argument NCOPIES of REPEAT intrinsic is negative",
+                          &se->pre, &expr->where);
+
+  /* Compute the destination length.  */
   len = fold_build2 (MULT_EXPR, gfc_int4_type_node, len, ncopies);
   type = gfc_get_character_type (expr->ts.kind, expr->ts.cl);
   var = gfc_conv_string_tmp (se, build_pointer_type (type), len);

+  /* Create the argument list and generate the function call.  */
   arglist = NULL_TREE;
   arglist = gfc_chainon_list (arglist, var);
-  arglist = chainon (arglist, args);
+  arglist = gfc_chainon_list (arglist, TREE_VALUE(args));
+  arglist = gfc_chainon_list (arglist, TREE_VALUE(TREE_CHAIN(args)));
+  arglist = gfc_chainon_list (arglist, ncopies);
   tmp = build_function_call_expr (gfor_fndecl_string_repeat, arglist);
   gfc_add_expr_to_block (&se->pre, tmp);

Index: libgfortran/intrinsics/string_intrinsics.c
===================================================================
--- libgfortran/intrinsics/string_intrinsics.c  (revision 121280)
+++ libgfortran/intrinsics/string_intrinsics.c  (working copy)
@@ -362,14 +362,8 @@
 {
   int i;

-  /* See if ncopies is valid.  */
-  if (ncopies < 0)
-    {
-      /* The error is already reported.  */
-      runtime_error ("Augument NCOPIES is negative.");
-    }
-
-  /* Copy characters.  */
+  /* We don't need to check that ncopies is non-negative here, because
+     the front-end already generates code for that check.  */
   for (i = 0; i < ncopies; i++) 
     {
       memmove (dest + (i * slen), src, slen);


-- 

fxcoudert at gcc dot gnu dot org changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |fxcoudert at gcc dot gnu dot
                   |                            |org
             Status|UNCONFIRMED                 |NEW
     Ever Confirmed|0                           |1
           Keywords|                            |wrong-code
      Known to fail|                            |4.3.0 4.2.0 4.1.2
   Last reconfirmed|0000-00-00 00:00:00         |2007-02-01 13:51:13
               date|                            |
   Target Milestone|---                         |4.2.0


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=30611

Reply via email to