support array bounds checking
authorCraig Burley <craig@jcb-sc.com>
Thu, 22 Apr 1999 23:01:43 +0000 (23:01 +0000)
committerCraig Burley <burley@gcc.gnu.org>
Thu, 22 Apr 1999 23:01:43 +0000 (19:01 -0400)
From-SVN: r26592

gcc/f/ChangeLog
gcc/f/com-rt.def
gcc/f/com.c
gcc/f/g77.texi
gcc/f/lang-options.h
gcc/f/news.texi
gcc/f/ste.c
gcc/f/top.c
gcc/f/top.h
gcc/f/version.c

index fb17af47e78c94d86b703d16680a2b0c90a8f791..1d163aca847eb4b7f1b28ce49c71cca94416948f 100644 (file)
@@ -1,3 +1,24 @@
+Fri Apr 23 01:48:28 1999  Craig Burley  <craig@jcb-sc.com>
+
+       Support new -fsubscript-check and -ff2c-subscript-check options:
+       * com-rt.def (FFECOM_gfrtRANGE): Describe s_rnge, in libf2c/libF77.
+       * com.c (ffecom_subscript_check_, ffecom_arrayref_): New functions.
+       (ffecom_char_args_x_): Use new ffecom_arrayref_ function for
+       FFEBLD_opARRAYREF case.
+       Compute character name, array type, and use new
+       ffecom_subscript_check_ function for FFEBLD_opSUBSTRING case.
+       (ffecom_expr_): Use new ffecom_arrayref_ function.
+       (ffecom_ptr_to_expr): Use new ffecom_arrayref_ function.
+       * g77.texi, news.texi: Document new options.
+       * top.c, top.h: Support new options.
+
+       * news.texi: Fix up some items to not be in "User-Visible Changes".
+
+       * ste.c (ffeste_R819B): Fix type for loop variable, to avoid
+       warnings.
+
+       * version.c: Bump version.
+
 Tue Apr 20 01:38:57 1999  Craig Burley  <craig@jcb-sc.com>
 
        * bugs.texi, news.texi: Clarify -malign-double situation.
index 5c08fee6c3e830c182989a564321ad642ca2f05b..cb3a5f14e8e82e8269e8372778b666d51babcf7f 100644 (file)
@@ -66,6 +66,7 @@ DEFGFRT (FFECOM_gfrtCMP, "s_cmp", FFECOM_rttypeINTEGER_, 0, FALSE, FALSE)
 DEFGFRT (FFECOM_gfrtCOPY, "s_copy", FFECOM_rttypeVOID_, 0, FALSE, FALSE)
 DEFGFRT (FFECOM_gfrtPAUSE, "s_paus", FFECOM_rttypeVOID_, 0, FALSE, FALSE)
 DEFGFRT (FFECOM_gfrtSTOP, "s_stop", FFECOM_rttypeVOID_, 0, TRUE, FALSE)
+DEFGFRT (FFECOM_gfrtRANGE, "s_rnge", FFECOM_rttypeINTEGER_, 0, TRUE, FALSE)
 
 DEFGFRT (FFECOM_gfrtSRDUE, "s_rdue", FFECOM_rttypeINTEGER_, 0, FALSE, FALSE)
 DEFGFRT (FFECOM_gfrtERDUE, "e_rdue", FFECOM_rttypeINTEGER_, 0, FALSE, FALSE)
index ad85268ea3edf6dc7da650977294300d10052e46..9d05bab93df9e281e926e40b7275f11f9daf5099 100644 (file)
@@ -745,6 +745,233 @@ static tree shadowed_labels;
 
 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
 \f
+/* Return the subscript expression, modified to do range-checking.
+
+   `array' is the array to be checked against.
+   `element' is the subscript expression to check.
+   `dim' is the dimension number (starting at 0).
+   `total_dims' is the total number of dimensions (0 for CHARACTER substring).
+*/
+
+static tree
+ffecom_subscript_check_ (tree array, tree element, int dim, int total_dims,
+                        char *array_name)
+{
+  tree low = TYPE_MIN_VALUE (TYPE_DOMAIN (array));
+  tree high = TYPE_MAX_VALUE (TYPE_DOMAIN (array));
+  tree cond;
+  tree die;
+  tree args;
+
+  if (element == error_mark_node)
+    return element;
+
+  element = ffecom_save_tree (element);
+  cond = ffecom_2 (LE_EXPR, integer_type_node,
+                  low,
+                  element);
+  if (high)
+    {
+      cond = ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
+                      cond,
+                      ffecom_2 (LE_EXPR, integer_type_node,
+                                element,
+                                high));
+    }
+
+  {
+    int len;
+    char *proc;
+    char *var;
+    tree arg3;
+    tree arg2;
+    tree arg1;
+    tree arg4;
+
+    switch (total_dims)
+      {
+      case 0:
+       var = xmalloc (strlen (array_name) + 20);
+       sprintf (&var[0], "%s[%s-substring]",
+                array_name,
+                dim ? "end" : "start");
+       len = strlen (var) + 1;
+       break;
+
+      case 1:
+       len = strlen (array_name) + 1;
+       var = array_name;
+       break;
+
+      default:
+       var = xmalloc (strlen (array_name) + 40);
+       sprintf (&var[0], "%s[subscript-%d-of-%d]",
+                array_name,
+                dim + 1, total_dims);
+       len = strlen (var) + 1;
+       break;
+      }
+
+    arg1 = build_string (len, var);
+
+    if (total_dims != 1)
+      free (var);
+
+    TREE_TYPE (arg1)
+      = build_type_variant (build_array_type (char_type_node,
+                                             build_range_type
+                                             (integer_type_node,
+                                              integer_one_node,
+                                              build_int_2 (len, 0))),
+                           1, 0);
+    TREE_CONSTANT (arg1) = 1;
+    TREE_STATIC (arg1) = 1;
+    arg1 = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (arg1)),
+                    arg1);
+
+    /* s_rnge adds one to the element to print it, so bias against
+       that -- want to print a faithful *subscript* value.  */
+    arg2 = convert (ffecom_f2c_ftnint_type_node,
+                   ffecom_2 (MINUS_EXPR,
+                             TREE_TYPE (element),
+                             element,
+                             convert (TREE_TYPE (element),
+                                      integer_one_node)));
+
+    proc = xmalloc ((len = strlen (input_filename)
+                    + IDENTIFIER_LENGTH (DECL_NAME (current_function_decl))
+                    + 2));
+
+    sprintf (&proc[0], "%s/%s",
+            input_filename,
+            IDENTIFIER_POINTER (DECL_NAME (current_function_decl)));
+    arg3 = build_string (len, proc);
+
+    free (proc);
+
+    TREE_TYPE (arg3)
+      = build_type_variant (build_array_type (char_type_node,
+                                             build_range_type
+                                             (integer_type_node,
+                                              integer_one_node,
+                                              build_int_2 (len, 0))),
+                           1, 0);
+    TREE_CONSTANT (arg3) = 1;
+    TREE_STATIC (arg3) = 1;
+    arg3 = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (arg3)),
+                    arg3);
+
+    arg4 = convert (ffecom_f2c_ftnint_type_node,
+                   build_int_2 (lineno, 0));
+
+    arg1 = build_tree_list (NULL_TREE, arg1);
+    arg2 = build_tree_list (NULL_TREE, arg2);
+    arg3 = build_tree_list (NULL_TREE, arg3);
+    arg4 = build_tree_list (NULL_TREE, arg4);
+    TREE_CHAIN (arg3) = arg4;
+    TREE_CHAIN (arg2) = arg3;
+    TREE_CHAIN (arg1) = arg2;
+
+    args = arg1;
+  }
+  die = ffecom_call_gfrt (FFECOM_gfrtRANGE,
+                         args, NULL_TREE);
+  TREE_SIDE_EFFECTS (die) = 1;
+
+  element = ffecom_3 (COND_EXPR,
+                     TREE_TYPE (element),
+                     cond,
+                     element,
+                     die);
+
+  return element;
+}
+
+/* Return the computed element of an array reference.
+
+   `item' is the array or a pointer to the array.  It must be a pointer
+     to the array if ffe_is_flat_arrays ().
+   `expr' is the original opARRAYREF expression.
+   `want_ptr' is non-zero if `item' is a pointer to the element, instead of
+     the element itself, is to be returned.  */
+
+static tree
+ffecom_arrayref_ (tree item, ffebld expr, int want_ptr)
+{
+  ffebld dims[FFECOM_dimensionsMAX];
+  int i;
+  int total_dims;
+  int flatten = 0 /* ~~~ ffe_is_flat_arrays () */;
+  int need_ptr = want_ptr || flatten;
+  tree array;
+  tree element;
+  char *array_name;
+
+  if (ffebld_op (ffebld_left (expr)) == FFEBLD_opSYMTER)
+    array_name = ffesymbol_text (ffebld_symter (ffebld_left (expr)));
+  else
+    array_name = "[expr?]";
+
+  /* Build up ARRAY_REFs in reverse order (since we're column major
+     here in Fortran land). */
+
+  for (i = 0, expr = ffebld_right (expr);
+       expr != NULL;
+       expr = ffebld_trail (expr))
+    dims[i++] = ffebld_head (expr);
+
+  total_dims = i;
+
+  if (need_ptr)
+    {
+      for (--i, array = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item)));
+          i >= 0;
+          --i, array = TYPE_MAIN_VARIANT (TREE_TYPE (array)))
+       {
+         element = ffecom_expr (dims[i]);
+         if (ffe_is_subscript_check ())
+           element = ffecom_subscript_check_ (array, element, i, total_dims,
+                                              array_name);
+         item = ffecom_2 (PLUS_EXPR,
+                          build_pointer_type (TREE_TYPE (array)),
+                          item,
+                          size_binop (MULT_EXPR,
+                                      size_in_bytes (TREE_TYPE (array)),
+                                      convert (sizetype,
+                                               fold (build (MINUS_EXPR,
+                                                            TREE_TYPE (TYPE_MIN_VALUE (TYPE_DOMAIN (array))),
+                                                            element,
+                                                            TYPE_MIN_VALUE (TYPE_DOMAIN (array)))))));
+       }
+      if (! want_ptr)
+       {
+         item = ffecom_1 (INDIRECT_REF,
+                          TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item))),
+                          item);
+       }
+    }
+  else
+    {
+      for (--i;
+          i >= 0;
+          --i)
+       {
+         array = TYPE_MAIN_VARIANT (TREE_TYPE (item));
+
+         element = ffecom_expr_ (dims[i], NULL, NULL, NULL, FALSE, TRUE);
+         if (ffe_is_subscript_check ())
+           element = ffecom_subscript_check_ (array, element, i, total_dims,
+                                              array_name);
+         item = ffecom_2 (ARRAY_REF,
+                          TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item))),
+                          item,
+                          element);
+       }
+    }
+
+  return item;
+}
+
 /* This is like gcc's stabilize_reference -- in fact, most of the code
    comes from that -- but it handles the situation where the reference
    is going to have its subparts picked at, and it shouldn't change
@@ -1746,10 +1973,6 @@ ffecom_char_args_x_ (tree *xitem, tree *length, ffebld expr, bool with_null)
 
     case FFEBLD_opARRAYREF:
       {
-       ffebld dims[FFECOM_dimensionsMAX];
-       tree array;
-       int i;
-
        ffecom_char_args_ (&item, length, ffebld_left (expr));
 
        if (item == error_mark_node || *length == error_mark_node)
@@ -1758,26 +1981,7 @@ ffecom_char_args_x_ (tree *xitem, tree *length, ffebld expr, bool with_null)
            break;
          }
 
-       /* Build up ARRAY_REFs in reverse order (since we're column major
-          here in Fortran land). */
-
-       for (i = 0, expr = ffebld_right (expr);
-            expr != NULL;
-            expr = ffebld_trail (expr))
-         dims[i++] = ffebld_head (expr);
-
-       for (--i, array = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item)));
-            i >= 0;
-            --i, array = TYPE_MAIN_VARIANT (TREE_TYPE (array)))
-         {
-           item = ffecom_2 (PLUS_EXPR, build_pointer_type (TREE_TYPE (array)),
-                            item,
-                            size_binop (MULT_EXPR,
-                                        size_in_bytes (TREE_TYPE (array)),
-                                        size_binop (MINUS_EXPR,
-                                                    ffecom_expr (dims[i]),
-                                   TYPE_MIN_VALUE (TYPE_DOMAIN (array)))));
-         }
+       item = ffecom_arrayref_ (item, expr, 1);
       }
       break;
 
@@ -1788,6 +1992,9 @@ ffecom_char_args_x_ (tree *xitem, tree *length, ffebld expr, bool with_null)
        ffebld thing = ffebld_right (expr);
        tree start_tree;
        tree end_tree;
+       char *char_name;
+       ffebld left_symter;
+       tree array;
 
        assert (ffebld_op (thing) == FFEBLD_opITEM);
        start = ffebld_head (thing);
@@ -1795,6 +2002,16 @@ ffecom_char_args_x_ (tree *xitem, tree *length, ffebld expr, bool with_null)
        assert (ffebld_trail (thing) == NULL);
        end = ffebld_head (thing);
 
+       /* Determine name for pretty-printing range-check errors.  */
+       for (left_symter = ffebld_left (expr);
+            left_symter && ffebld_op (left_symter) == FFEBLD_opARRAYREF;
+            left_symter = ffebld_left (left_symter))
+         ;
+       if (ffebld_op (left_symter) == FFEBLD_opSYMTER)
+         char_name = ffesymbol_text (ffebld_symter (left_symter));
+       else
+         char_name = "[expr?]";
+
        ffecom_char_args_ (&item, length, ffebld_left (expr));
 
        if (item == error_mark_node || *length == error_mark_node)
@@ -1803,14 +2020,20 @@ ffecom_char_args_x_ (tree *xitem, tree *length, ffebld expr, bool with_null)
            break;
          }
 
+       array = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item)));
+
        if (start == NULL)
          {
            if (end == NULL)
              ;
            else
              {
+               end_tree = ffecom_expr (end);
+               if (ffe_is_subscript_check ())
+                 end_tree = ffecom_subscript_check_ (array, end_tree, 1, 0,
+                                                     char_name);
                end_tree = convert (ffecom_f2c_ftnlen_type_node,
-                                   ffecom_expr (end));
+                                   end_tree);
 
                if (end_tree == error_mark_node)
                  {
@@ -1823,8 +2046,12 @@ ffecom_char_args_x_ (tree *xitem, tree *length, ffebld expr, bool with_null)
          }
        else
          {
+           start_tree = ffecom_expr (start);
+           if (ffe_is_subscript_check ())
+             start_tree = ffecom_subscript_check_ (array, start_tree, 0, 0,
+                                                   char_name);
            start_tree = convert (ffecom_f2c_ftnlen_type_node,
-                                 ffecom_expr (start));
+                                 start_tree);
 
            if (start_tree == error_mark_node)
              {
@@ -1852,8 +2079,12 @@ ffecom_char_args_x_ (tree *xitem, tree *length, ffebld expr, bool with_null)
              }
            else
              {
+               end_tree = ffecom_expr (end);
+               if (ffe_is_subscript_check ())
+                 end_tree = ffecom_subscript_check_ (array, end_tree, 1, 0,
+                                                     char_name);
                end_tree = convert (ffecom_f2c_ftnlen_type_node,
-                                   ffecom_expr (end));
+                                   end_tree);
 
                if (end_tree == error_mark_node)
                  {
@@ -2973,17 +3204,11 @@ ffecom_expr_ (ffebld expr, tree dest_tree, ffebld dest,
 
     case FFEBLD_opARRAYREF:
       {
-       ffebld dims[FFECOM_dimensionsMAX];
-#if FFECOM_FASTER_ARRAY_REFS
-       tree array;
-#endif
-       int i;
+       if (0 /* ~~~~~ ffe_is_flat_arrays () */)
+         t = ffecom_ptr_to_expr (ffebld_left (expr));
+       else
+         t = ffecom_expr (ffebld_left (expr));
 
-#if FFECOM_FASTER_ARRAY_REFS
-       t = ffecom_ptr_to_expr (ffebld_left (expr));
-#else
-       t = ffecom_expr (ffebld_left (expr));
-#endif
        if (t == error_mark_node)
          return t;
 
@@ -2992,36 +3217,7 @@ ffecom_expr_ (ffebld expr, tree dest_tree, ffebld dest,
          return error_mark_node;       /* Make sure non-const ref is to
                                           non-reg. */
 
-       /* Build up ARRAY_REFs in reverse order (since we're column major
-          here in Fortran land). */
-
-       for (i = 0, expr = ffebld_right (expr);
-            expr != NULL;
-            expr = ffebld_trail (expr))
-         dims[i++] = ffebld_head (expr);
-
-#if FFECOM_FASTER_ARRAY_REFS
-       for (--i, array = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (t)));
-            i >= 0;
-            --i, array = TYPE_MAIN_VARIANT (TREE_TYPE (array)))
-         t = ffecom_2 (PLUS_EXPR,
-                       build_pointer_type (TREE_TYPE (array)),
-                       t,
-                       size_binop (MULT_EXPR,
-                                   size_in_bytes (TREE_TYPE (array)),
-                                   size_binop (MINUS_EXPR,
-                                               ffecom_expr (dims[i]),
-                                               TYPE_MIN_VALUE (TYPE_DOMAIN (array)))));
-       t = ffecom_1 (INDIRECT_REF,
-                     TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (t))),
-                     t);
-#else
-       while (i > 0)
-         t = ffecom_2 (ARRAY_REF,
-                       TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (t))),
-                       t,
-                       ffecom_expr_ (dims[--i], NULL, NULL, NULL, FALSE, TRUE));
-#endif
+       t = ffecom_arrayref_ (t, expr, 0);
 
        return t;
       }
@@ -12522,10 +12718,6 @@ ffecom_ptr_to_expr (ffebld expr)
 
     case FFEBLD_opARRAYREF:
       {
-       ffebld dims[FFECOM_dimensionsMAX];
-       tree array;
-       int i;
-
        item = ffecom_ptr_to_expr (ffebld_left (expr));
 
        if (item == error_mark_node)
@@ -12536,32 +12728,7 @@ ffecom_ptr_to_expr (ffebld expr)
          return error_mark_node;       /* Make sure non-const ref is to
                                           non-reg. */
 
-       /* Build up ARRAY_REFs in reverse order (since we're column major
-          here in Fortran land). */
-
-       for (i = 0, expr = ffebld_right (expr);
-            expr != NULL;
-            expr = ffebld_trail (expr))
-         dims[i++] = ffebld_head (expr);
-
-       for (--i, array = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item)));
-            i >= 0;
-            --i, array = TYPE_MAIN_VARIANT (TREE_TYPE (array)))
-         {
-           /* The initial subtraction should happen in the original type so
-              that (possible) negative values are handled appropriately.  */
-           item
-             = ffecom_2 (PLUS_EXPR,
-                         build_pointer_type (TREE_TYPE (array)),
-                         item,
-                         size_binop (MULT_EXPR,
-                                     size_in_bytes (TREE_TYPE (array)),
-                                     convert (sizetype,
-                                              fold (build (MINUS_EXPR,
-                                                    TREE_TYPE (TYPE_MIN_VALUE (TYPE_DOMAIN (array))),
-                                                    ffecom_expr (dims[i]),
-                                                    TYPE_MIN_VALUE (TYPE_DOMAIN (array)))))));
-         }
+       item = ffecom_arrayref_ (item, expr, 1);
       }
       return item;
 
index 8d0a08f2d679e34602df32a336d01dc5d55c5988..9bd39283f1e68891448026572f865f9e4afdce37 100644 (file)
@@ -2,7 +2,7 @@
 @c %**start of header
 @setfilename g77.info
 
-@set last-update 1999-04-17
+@set last-update 1999-04-23
 @set copyrights-g77 1995-1999
 
 @include root.texi
@@ -1471,6 +1471,7 @@ by type.  Explanations are in the following sections.
 -falias-check  -fargument-alias
 -fargument-noalias  -fno-argument-noalias-global
 -fno-globals
+-fsubscript-check  -ff2c-subscript-check
 @end smallexample
 @end table
 
@@ -3370,6 +3371,73 @@ and warns about similar disagreements
 that are currently believed to not
 likely to result in the compiler later crashing
 or producing incorrect code.
+
+@cindex -fsubscript-check option
+@cindex -ff2c-subscript-check option
+@item -fsubscript-check
+@itemx -ff2c-subscript-check
+@cindex bounds checking
+@cindex range checking
+@cindex array bounds checking
+@cindex subscript checking
+@cindex substring checking
+@cindex checking subscripts
+@cindex checking substrings
+Enable generation of run-time checks for array subscripts
+and substring start and end points
+against the (locally) declared minimum and maximum values.
+
+The current implementation uses the @code{libf2c}
+library routine @code{s_rnge} to print the diagnostic.
+
+However, whereas @code{f2c} generates a single check per
+reference for a multi-dimensional array, of the computed
+offset against the valid offset range (0 through the size of the array),
+@code{g77} generates a single check per @emph{subscript} expression.
+This catches some cases of potential bugs that @code{f2c} does not,
+such as references to below the beginning of an assumed-size array.
+
+@code{g77} also generates checks for @code{CHARACTER} substring references,
+something @code{f2c} currently does not do.
+
+Since a future version of @code{g77} might use a different implementation,
+use the new @samp{-ff2c-subscript-check} option
+if your application requires use of @code{s_rnge} or a compile-time diagnostic.
+
+@emph{Note:} To provide more detailed information on the offending subscript,
+@code{g77} provides @code{s_rnge}
+with somewhat differently-formatted information.
+Here's a sample diagnostic:
+
+@smallexample
+Subscript out of range on file line 4, procedure rnge.f/bf.
+Attempt to access the -6-th element of variable b[subscript-2-of-2].
+Aborted
+@end smallexample
+
+The above message indicates that the offending source line is
+line 4 of the file @file{rnge.f},
+within the program unit (or statement function) named @samp{bf}.
+The offended array is named @samp{b}.
+The offended array dimension is the second for a two-dimensional array,
+and the offending, computed subscript expression was @samp{-6}.
+
+For a @code{CHARACTER} substring reference, the second line has
+this appearance:
+
+@smallexample
+Attempt to access the 11-th element of variable a[start-substring].
+@end smallexample
+
+This indicates that the offended @code{CHARACTER} variable or array
+is named @samp{a},
+the offended substring position is the starting (leftmost) position,
+and the offending substring expression is @samp{11}.
+
+(Though the verbage of @code{s_rnge} is not ideal
+for the purpose of the @code{g77} compiler,
+the above information should provide adequate diagnostic abilities
+to it users.)
 @end table
 
 @xref{Code Gen Options,,Options for Code Generation Conventions,
@@ -11015,6 +11083,8 @@ themselves as @emph{visible} problems some time later.
 Overflowing the bounds of an array---usually by writing beyond
 the end of it---is one of two kinds of bug that often occurs
 in Fortran code.
+(Compile your code with the @samp{-fsubscript-check} option
+to catch many of these kinds of errors at program run time.)
 
 The other kind of bug is a mismatch between the actual arguments
 passed to a procedure and the dummy arguments as declared by that
@@ -11028,11 +11098,13 @@ That is, these bugs can be quite sensitive to data, including
 data representing the placement of other data in memory (that is,
 pointers, such as the placement of stack frames in memory).
 
-Plans call for improving @code{g77} so that it can offer the
+@code{g77} now offers the
 ability to catch and report some of these problems at compile, link, or
 run time, such as by generating code to detect references to
-beyond the bounds of an array, or checking for agreement between
-calling and called procedures.
+beyond the bounds of most arrays (except assumed-size arrays),
+and checking for agreement between calling and called procedures.
+Future improvements are likely to be made in the procedure-mismatch area,
+at least.
 
 In the meantime, finding and fixing the programming
 bugs that lead to these behaviors is, ultimately, the user's
@@ -11275,7 +11347,6 @@ Better diagnostics:
 
 Run-time facilities:
 * Uninitialized Variables at Run Time::
-* Bounds Checking at Run Time::
 * Portable Unformatted Files::
 
 Debugging:
@@ -12159,15 +12230,6 @@ some kinds of uninitialized variables at run time.
 Note that use of the options @samp{-O -Wuninitialized} can catch
 many such bugs at compile time.
 
-@node Bounds Checking at Run Time
-@subsection Bounds Checking at Run Time
-
-@code{g77} should offer run-time bounds-checking of array/subscript references
-in a fashion similar to @code{f2c}.
-
-Note that @code{g77} already warns about references to out-of-bounds
-elements of arrays when it detects these at compile time.
-
 @node Portable Unformatted Files
 @subsection Portable Unformatted Files
 
index 64e9f63615c3d29859f6da4523aa67f4ee7bbfa0..4e98a309b0c45a2f78245462b19feb0d93f3a3aa 100644 (file)
@@ -147,6 +147,10 @@ FTNOPT( "-fglobals", "" )
 FTNOPT( "-fno-globals", "Disable fatal diagnostics about inter-procedural problems" )
 FTNOPT( "-ftypeless-boz", "Make prefix-radix non-decimal constants be typeless" )
 FTNOPT( "-fno-typeless-boz", "" )
+FTNOPT( "-fsubscript-check", "Generate code to check array-subscript ranges" )
+FTNOPT( "-fno-subscript-check", "" )
+FTNOPT( "-ff2c-subscript-check", "Generate f2c-like code to check array-subscript ranges")
+FTNOPT( "-fno-f2c-subscript-check", "" )
 FTNOPT( "-Wglobals", "" )
 FTNOPT( "-Wno-globals", "Disable warnings about inter-procedural problems" )
 /*"-Wimplicit",*/
index 37acb1ca1ba33ea089fd47df462197f917819fb3..3c43cad5468db712960cab8fcaa9d6778a799af3 100644 (file)
@@ -9,7 +9,7 @@
 @c in the standalone derivations of this file (e.g. NEWS).
 @set copyrights-news 1995-1999
 
-@set last-update-news 1999-04-20
+@set last-update-news 1999-04-23
 
 @include root.texi
 
@@ -187,6 +187,17 @@ The @samp{-ax} option is now obeyed when compiling Fortran programs.
 (It is passed to the @file{f771} driver.)
 @end ifclear
 
+@item
+The new @samp{-fsubscript-check} option
+causes @code{g77} to compile run-time bounds checks
+of array subscripts, as well as of substring start and end points.
+
+The current implementation uses the @code{libf2c}
+library routine @code{s_rnge} to print the diagnostic.
+Since a future version of @code{g77} might use a different implementation,
+use the new @samp{-ff2c-subscript-check} option
+if your application requires use of @code{s_rnge} or a compile-time diagnostic.
+
 @item
 Source file names with the suffixes @samp{.FOR} and @samp{.FPP}
 now are recognized by @code{g77}
@@ -224,12 +235,15 @@ The @samp{-malign-double} option
 now reliably aligns @emph{all} double-precision variables and arrays
 on Intel x86 targets.
 
+@ifclear USERVISONLY
 @item
 Even without the @samp{-malign-double} option,
 @code{g77} reliably aligns local double-precision variables
 that are not in @code{EQUIVALENCE} areas
 and not @code{SAVE}'d.
+@end ifclear
 
+@ifclear USERVISONLY
 @item
 A substantial portion of the @code{g77} front end's code-generation component
 was rewritten.
@@ -238,6 +252,7 @@ by the @code{gcc} back end.
 One effect of this rewrite is that some codes no longer produce
 a spurious ``label @var{lab} used before containing binding contour''
 message.
+@end ifclear
 
 @item
 Support for the @samp{-fugly} option has been removed.
index 92c31429ae7d4c801ceef4f6959ed5ecccf38e50..2b018555b1e77880ffc14480c03134990faac6cf 100644 (file)
@@ -3096,7 +3096,7 @@ ffeste_R819B (ffestw block, ffelab label UNUSED, ffebld expr)
 
     if (expr)
       {
-       tree loop;
+       struct nesting *loop;
 
        result = ffecom_make_tempvar ("dowhile", integer_type_node,
                                      FFETARGET_charactersizeNONE, -1);
index e8f0ce5e6d4594253fff900c60972fabb42f6d67..8603f011ea095e291e461122b8860df6c8751418 100644 (file)
@@ -82,6 +82,7 @@ bool ffe_is_mainprog_;                /* TRUE if current prog unit known to be
 bool ffe_is_null_version_ = FALSE;
 bool ffe_is_onetrip_ = FALSE;
 bool ffe_is_silent_ = TRUE;
+bool ffe_is_subscript_check_ = FALSE;
 bool ffe_is_typeless_boz_ = FALSE;
 bool ffe_is_pedantic_ = FFETARGET_defaultIS_PEDANTIC;
 bool ffe_is_saveall_;          /* TRUE if mainprog or SAVE (no args) seen. */
@@ -317,6 +318,14 @@ ffe_decode_option (argc, argv)
        ffe_set_is_globals (TRUE);
       else if (strcmp (&opt[2], "no-globals") == 0)
        ffe_set_is_globals (FALSE);
+      else if (strcmp (&opt[2], "subscript-check") == 0)
+       ffe_set_is_subscript_check (TRUE);
+      else if (strcmp (&opt[2], "no-subscript-check") == 0)
+       ffe_set_is_subscript_check (FALSE);
+      else if (strcmp (&opt[2], "f2c-subscript-check") == 0)
+       ffe_set_is_subscript_check (TRUE);
+      else if (strcmp (&opt[2], "no-f2c-subscript-check") == 0)
+       ffe_set_is_subscript_check (FALSE);
       else if (strcmp (&opt[2], "typeless-boz") == 0)
        ffe_set_is_typeless_boz (TRUE);
       else if (strcmp (&opt[2], "no-typeless-boz") == 0)
index d8de0e32f93e41f67be52f762a31bf151ee259d5..c03e1d6540039ea4f357a08180179f32461e5fd2 100644 (file)
@@ -97,6 +97,7 @@ extern bool ffe_is_mainprog_;
 extern bool ffe_is_null_version_;
 extern bool ffe_is_onetrip_;
 extern bool ffe_is_silent_;
+extern bool ffe_is_subscript_check_;
 extern bool ffe_is_typeless_boz_;
 extern bool ffe_is_pedantic_;
 extern bool ffe_is_saveall_;
@@ -188,6 +189,7 @@ void ffe_terminate_4 (void);
 #define ffe_is_saveall() ffe_is_saveall_
 #define ffe_is_second_underscore() ffe_is_second_underscore_
 #define ffe_is_silent() ffe_is_silent_
+#define ffe_is_subscript_check() ffe_is_subscript_check_
 #define ffe_is_typeless_boz() ffe_is_typeless_boz_
 #define ffe_is_ugly_args() ffe_is_ugly_args_
 #define ffe_is_ugly_assign() ffe_is_ugly_assign_
@@ -238,6 +240,7 @@ void ffe_terminate_4 (void);
 #define ffe_set_is_saveall(f) (ffe_is_saveall_ = (f))
 #define ffe_set_is_second_underscore(f) (ffe_is_second_underscore_ = (f))
 #define ffe_set_is_silent(f) (ffe_is_silent_ = (f))
+#define ffe_set_is_subscript_check(f) (ffe_is_subscript_check_ = (f))
 #define ffe_set_is_typeless_boz(f) (ffe_is_typeless_boz_ = (f))
 #define ffe_set_is_ugly_args(f) (ffe_is_ugly_args_ = (f))
 #define ffe_set_is_ugly_assign(f) (ffe_is_ugly_assign_ = (f))
index b2b996fa15f3ab013c7b9ca62d9f244df0de403d..82ab0146a9289318e33f948ea05b92249302fd13 100644 (file)
@@ -1 +1 @@
-const char *ffe_version_string = "0.5.24-19990420";
+const char *ffe_version_string = "0.5.24-19990423";