* [gfortran,patch] More detailled runtime bounds-checking messages...
@ 2007-08-09 23:32 FX Coudert
2007-08-10 9:48 ` Tobias Burnus
0 siblings, 1 reply; 2+ messages in thread
From: FX Coudert @ 2007-08-09 23:32 UTC (permalink / raw)
To: GNU Fortran, gcc-patches list
[-- Attachment #1: Type: text/plain, Size: 1361 bytes --]
... including out-of-bounds index and array bounds!
This patch allows us to perform runtime checks with more than a
static failure message: we can now call runtime_error_at with a
printf-like format string and variable arguments. The front-end also
offers variable-args functions to build these function calls, passing
them trees. For example, if we detect that i (which is not a compile-
time constant, but a tree) is lower than 1 and is used as substring
index, we can do:
gfc_trans_runtime_check (condition, &se->pre, locus, "Substring
index (%%ld) is smaller than one", fold_convert
(long_integer_type_node, index));
The only thing is that we need to make sure the trees passed as
arguments have types matching the format string.
So, I used this new functionality in bounds-checking error messages
generated through-out the front-end, as much as possible (which is
almost everywhere). New messages now look like:
> At line 6 of file a.f90
> Fortran runtime error: Array reference out of bounds for array
> 'ivec', upper
> bound of dimension 1 exceeded, 3 is greater than 2
So now, I'm looking for a review to get this in, and eventually
suggestions to change the wording if deemed inappropriate.
Bootstrapped and regtested (both with and without -fbounds-check) on
x86_64-linux, OK to commit?
FX
:ADDPATCH fortran:
[-- Attachment #2: pr31270.ChangeLog --]
[-- Type: application/octet-stream, Size: 1357 bytes --]
2007-08-09 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
PR fortran/31270
* trans.c (gfc_trans_runtime_check): Reorder arguments and
add extra variable arguments. Hand them to the library function.
* trans.h (gfc_trans_runtime_check): Update prototype.
* trans-array.c (gfc_trans_array_bound_check): Issue more
detailled error messages.
(gfc_conv_array_ref): Likewise.
(gfc_conv_ss_startstride): Likewise.
(gfc_trans_dummy_array_bias): Reorder arguments to
gfc_trans_runtime_check.
* trans-expr.c (gfc_conv_substring): Issue more detailled
error messages.
(gfc_conv_function_call): Reorder arguments to gfc_trans_runtime_check.
* trans-stmt.c (gfc_trans_goto): Likewise.
* trans-io.c (set_string): Reorder arguments to
gfc_trans_runtime_check and issue a more detailled error message.
* trans-decl.c (gfc_build_builtin_function_decls): Make
runtime_error and runtime_error_at handle a variable number of
arguments.
* trans-intrinsic.c (gfc_conv_intrinsic_bound): Reorder arguments
to gfc_trans_runtime_check.
(gfc_conv_intrinsic_minmax): Likewise.
(gfc_conv_intrinsic_repeat): Issue more detailled error messages.
2007-08-09 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
PR fortran/31270
* runtime/error.c (runtime_error_at): Add a variable number of
arguments.
* libgfortran.h (runtime_error_at): Update prototype.
[-- Attachment #3: pr31270.diff --]
[-- Type: application/octet-stream, Size: 19350 bytes --]
Index: gcc/fortran/trans-array.c
===================================================================
--- gcc/fortran/trans-array.c (revision 127319)
+++ gcc/fortran/trans-array.c (working copy)
@@ -2097,9 +2097,11 @@ gfc_trans_array_bound_check (gfc_se * se
asprintf (&msg, "%s for array '%s', lower bound of dimension %d exceeded",
gfc_msg_fault, name, n+1);
else
- asprintf (&msg, "%s, lower bound of dimension %d exceeded",
- gfc_msg_fault, n+1);
- gfc_trans_runtime_check (fault, msg, &se->pre, where);
+ asprintf (&msg, "%s, lower bound of dimension %d exceeded, %%ld is "
+ "smaller than %%ld", gfc_msg_fault, n+1);
+ gfc_trans_runtime_check (fault, &se->pre, where, msg,
+ fold_convert (long_integer_type_node, index),
+ fold_convert (long_integer_type_node, tmp));
gfc_free (msg);
/* Check upper bound. */
@@ -2111,9 +2113,11 @@ gfc_trans_array_bound_check (gfc_se * se
asprintf (&msg, "%s for array '%s', upper bound of dimension %d "
" exceeded", gfc_msg_fault, name, n+1);
else
- asprintf (&msg, "%s, upper bound of dimension %d exceeded",
- gfc_msg_fault, n+1);
- gfc_trans_runtime_check (fault, msg, &se->pre, where);
+ asprintf (&msg, "%s, upper bound of dimension %d exceeded, %%ld is "
+ "larger than %%ld", gfc_msg_fault, n+1);
+ gfc_trans_runtime_check (fault, &se->pre, where, msg,
+ fold_convert (long_integer_type_node, index),
+ fold_convert (long_integer_type_node, tmp));
gfc_free (msg);
}
@@ -2300,9 +2304,12 @@ gfc_conv_array_ref (gfc_se * se, gfc_arr
cond = fold_build2 (LT_EXPR, boolean_type_node,
indexse.expr, tmp);
asprintf (&msg, "%s for array '%s', "
- "lower bound of dimension %d exceeded", gfc_msg_fault,
- sym->name, n+1);
- gfc_trans_runtime_check (cond, msg, &se->pre, where);
+ "lower bound of dimension %d exceeded, %%ld is smaller "
+ "than %%ld", gfc_msg_fault, sym->name, n+1);
+ gfc_trans_runtime_check (cond, &se->pre, where, msg,
+ fold_convert (long_integer_type_node,
+ indexse.expr),
+ fold_convert (long_integer_type_node, tmp));
gfc_free (msg);
/* Upper bound, but not for the last dimension of assumed-size
@@ -2314,9 +2321,12 @@ gfc_conv_array_ref (gfc_se * se, gfc_arr
cond = fold_build2 (GT_EXPR, boolean_type_node,
indexse.expr, tmp);
asprintf (&msg, "%s for array '%s', "
- "upper bound of dimension %d exceeded", gfc_msg_fault,
- sym->name, n+1);
- gfc_trans_runtime_check (cond, msg, &se->pre, where);
+ "upper bound of dimension %d exceeded, %%ld is "
+ "greater than %%ld", gfc_msg_fault, sym->name, n+1);
+ gfc_trans_runtime_check (cond, &se->pre, where, msg,
+ fold_convert (long_integer_type_node,
+ indexse.expr),
+ fold_convert (long_integer_type_node, tmp));
gfc_free (msg);
}
}
@@ -2872,7 +2882,7 @@ gfc_conv_ss_startstride (gfc_loopinfo *
asprintf (&msg, "Zero stride is not allowed, for dimension %d "
"of array '%s'", info->dim[n]+1,
ss->expr->symtree->name);
- gfc_trans_runtime_check (tmp, msg, &block, &ss->expr->where);
+ gfc_trans_runtime_check (tmp, &block, &ss->expr->where, msg);
gfc_free (msg);
desc = ss->data.info.descriptor;
@@ -2912,9 +2922,13 @@ gfc_conv_ss_startstride (gfc_loopinfo *
tmp = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
non_zerosized, tmp);
asprintf (&msg, "%s, lower bound of dimension %d of array '%s'"
- " exceeded", gfc_msg_fault, info->dim[n]+1,
- ss->expr->symtree->name);
- gfc_trans_runtime_check (tmp, msg, &block, &ss->expr->where);
+ " exceeded, %%ld is smaller than %%ld", gfc_msg_fault,
+ info->dim[n]+1, ss->expr->symtree->name);
+ gfc_trans_runtime_check (tmp, &block, &ss->expr->where, msg,
+ fold_convert (long_integer_type_node,
+ info->start[n]),
+ fold_convert (long_integer_type_node,
+ lbound));
gfc_free (msg);
if (check_upper)
@@ -2924,9 +2938,12 @@ gfc_conv_ss_startstride (gfc_loopinfo *
tmp = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
non_zerosized, tmp);
asprintf (&msg, "%s, upper bound of dimension %d of array "
- "'%s' exceeded", gfc_msg_fault, info->dim[n]+1,
+ "'%s' exceeded, %%ld is greater than %%ld",
+ gfc_msg_fault, info->dim[n]+1,
ss->expr->symtree->name);
- gfc_trans_runtime_check (tmp, msg, &block, &ss->expr->where);
+ gfc_trans_runtime_check (tmp, &block, &ss->expr->where, msg,
+ fold_convert (long_integer_type_node, info->start[n]),
+ fold_convert (long_integer_type_node, ubound));
gfc_free (msg);
}
@@ -2944,9 +2961,13 @@ gfc_conv_ss_startstride (gfc_loopinfo *
tmp = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
non_zerosized, tmp);
asprintf (&msg, "%s, lower bound of dimension %d of array '%s'"
- " exceeded", gfc_msg_fault, info->dim[n]+1,
- ss->expr->symtree->name);
- gfc_trans_runtime_check (tmp, msg, &block, &ss->expr->where);
+ " exceeded, %%ld is smaller than %%ld", gfc_msg_fault,
+ info->dim[n]+1, ss->expr->symtree->name);
+ gfc_trans_runtime_check (tmp, &block, &ss->expr->where, msg,
+ fold_convert (long_integer_type_node,
+ tmp2),
+ fold_convert (long_integer_type_node,
+ lbound));
gfc_free (msg);
if (check_upper)
@@ -2955,9 +2976,12 @@ gfc_conv_ss_startstride (gfc_loopinfo *
tmp = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
non_zerosized, tmp);
asprintf (&msg, "%s, upper bound of dimension %d of array "
- "'%s' exceeded", gfc_msg_fault, info->dim[n]+1,
+ "'%s' exceeded, %%ld is greater than %%ld",
+ gfc_msg_fault, info->dim[n]+1,
ss->expr->symtree->name);
- gfc_trans_runtime_check (tmp, msg, &block, &ss->expr->where);
+ gfc_trans_runtime_check (tmp, &block, &ss->expr->where, msg,
+ fold_convert (long_integer_type_node, tmp2),
+ fold_convert (long_integer_type_node, ubound));
gfc_free (msg);
}
@@ -2970,12 +2994,14 @@ gfc_conv_ss_startstride (gfc_loopinfo *
others against this. */
if (size[n])
{
- tmp =
- fold_build2 (NE_EXPR, boolean_type_node, tmp, size[n]);
+ tree tmp3
+ = fold_build2 (NE_EXPR, boolean_type_node, tmp, size[n]);
asprintf (&msg, "%s, size mismatch for dimension %d "
- "of array '%s'", gfc_msg_bounds, info->dim[n]+1,
- ss->expr->symtree->name);
- gfc_trans_runtime_check (tmp, msg, &block, &ss->expr->where);
+ "of array '%s' (%%ld/%%ld)", gfc_msg_bounds,
+ info->dim[n]+1, ss->expr->symtree->name);
+ gfc_trans_runtime_check (tmp3, &block, &ss->expr->where, msg,
+ fold_convert (long_integer_type_node, tmp),
+ fold_convert (long_integer_type_node, size[n]));
gfc_free (msg);
}
else
@@ -4194,7 +4220,7 @@ gfc_trans_dummy_array_bias (gfc_symbol *
tmp = fold_build2 (NE_EXPR, gfc_array_index_type, tmp, stride2);
asprintf (&msg, "%s for dimension %d of array '%s'",
gfc_msg_bounds, n+1, sym->name);
- gfc_trans_runtime_check (tmp, msg, &block, &loc);
+ gfc_trans_runtime_check (tmp, &block, &loc, msg);
gfc_free (msg);
}
}
Index: gcc/fortran/trans-expr.c
===================================================================
--- gcc/fortran/trans-expr.c (revision 127319)
+++ gcc/fortran/trans-expr.c (working copy)
@@ -296,12 +296,14 @@ gfc_conv_substring (gfc_se * se, gfc_ref
fault = fold_build2 (TRUTH_ANDIF_EXPR, boolean_type_node,
nonempty, fault);
if (name)
- asprintf (&msg, "Substring out of bounds: lower bound of '%s' "
+ asprintf (&msg, "Substring out of bounds: lower bound (%%ld) of '%s' "
"is less than one", name);
else
- asprintf (&msg, "Substring out of bounds: lower bound "
+ asprintf (&msg, "Substring out of bounds: lower bound (%%ld)"
"is less than one");
- gfc_trans_runtime_check (fault, msg, &se->pre, where);
+ gfc_trans_runtime_check (fault, &se->pre, where, msg,
+ fold_convert (long_integer_type_node,
+ start.expr));
gfc_free (msg);
/* Check upper bound. */
@@ -310,12 +312,15 @@ gfc_conv_substring (gfc_se * se, gfc_ref
fault = fold_build2 (TRUTH_ANDIF_EXPR, boolean_type_node,
nonempty, fault);
if (name)
- asprintf (&msg, "Substring out of bounds: upper bound of '%s' "
- "exceeds string length", name);
+ asprintf (&msg, "Substring out of bounds: upper bound (%%ld) of '%s' "
+ "exceeds string length (%%ld)", name);
else
- asprintf (&msg, "Substring out of bounds: upper bound "
- "exceeds string length");
- gfc_trans_runtime_check (fault, msg, &se->pre, where);
+ asprintf (&msg, "Substring out of bounds: upper bound (%%ld) "
+ "exceeds string length (%%ld)");
+ gfc_trans_runtime_check (fault, &se->pre, where, msg,
+ fold_convert (long_integer_type_node, end.expr),
+ fold_convert (long_integer_type_node,
+ se->string_length));
gfc_free (msg);
}
@@ -2589,7 +2594,7 @@ gfc_conv_function_call (gfc_se * se, gfc
tmp = gfc_conv_descriptor_data_get (info->descriptor);
tmp = fold_build2 (NE_EXPR, boolean_type_node,
tmp, info->data);
- gfc_trans_runtime_check (tmp, gfc_msg_fault, &se->pre, NULL);
+ gfc_trans_runtime_check (tmp, &se->pre, NULL, gfc_msg_fault);
}
se->expr = info->descriptor;
/* Bundle in the string length. */
Index: gcc/fortran/trans-stmt.c
===================================================================
--- gcc/fortran/trans-stmt.c (revision 127319)
+++ gcc/fortran/trans-stmt.c (working copy)
@@ -153,8 +153,8 @@ gfc_trans_goto (gfc_code * code)
tmp = GFC_DECL_STRING_LEN (se.expr);
tmp = fold_build2 (NE_EXPR, boolean_type_node, tmp,
build_int_cst (TREE_TYPE (tmp), -1));
- gfc_trans_runtime_check (tmp, "Assigned label is not a target label",
- &se.pre, &loc);
+ gfc_trans_runtime_check (tmp, &se.pre, &loc,
+ "Assigned label is not a target label");
assigned_goto = GFC_DECL_ASSIGN_ADDR (se.expr);
@@ -179,8 +179,8 @@ gfc_trans_goto (gfc_code * code)
code = code->block;
}
while (code != NULL);
- gfc_trans_runtime_check (boolean_true_node,
- "Assigned label is not in the list", &se.pre, &loc);
+ gfc_trans_runtime_check (boolean_true_node, &se.pre, &loc,
+ "Assigned label is not in the list");
return gfc_finish_block (&se.pre);
}
Index: gcc/fortran/trans.c
===================================================================
--- gcc/fortran/trans.c (revision 127319)
+++ gcc/fortran/trans.c (working copy)
@@ -320,19 +320,32 @@ gfc_build_array_ref (tree base, tree off
/* Generate a runtime error if COND is true. */
void
-gfc_trans_runtime_check (tree cond, const char * msgid, stmtblock_t * pblock,
- locus * where)
+gfc_trans_runtime_check (tree cond, stmtblock_t * pblock, locus * where,
+ const char * msgid, ...)
{
+ va_list ap;
stmtblock_t block;
tree body;
tree tmp;
tree arg, arg2;
+ tree *argarray;
+ tree fntype;
char *message;
- int line;
+ const char *p;
+ int line, nargs, i;
if (integer_zerop (cond))
return;
+ /* Compute the number of extra arguments from the format string. */
+ for (p = msgid, nargs = 0; *p; p++)
+ if (*p == '%')
+ {
+ p++;
+ if (*p != '%')
+ nargs++;
+ }
+
/* The code to generate the error. */
gfc_start_block (&block);
@@ -357,7 +370,23 @@ gfc_trans_runtime_check (tree cond, cons
arg2 = gfc_build_addr_expr (pchar_type_node, gfc_build_cstring_const(message));
gfc_free(message);
- tmp = build_call_expr (gfor_fndecl_runtime_error_at, 2, arg, arg2);
+ /* Build the argument array. */
+ argarray = (tree *) alloca (sizeof (tree) * (nargs + 2));
+ argarray[0] = arg;
+ argarray[1] = arg2;
+ va_start (ap, msgid);
+ for (i = 0; i < nargs; i++)
+ argarray[2+i] = va_arg (ap, tree);
+ va_end (ap);
+
+ /* Build the function call to runtime_error_at; because of the variable
+ number of arguments, we can't use build_call_expr directly. */
+ fntype = TREE_TYPE (gfor_fndecl_runtime_error_at);
+ tmp = fold_builtin_call_array (TREE_TYPE (fntype),
+ build1 (ADDR_EXPR,
+ build_pointer_type (fntype),
+ gfor_fndecl_runtime_error_at),
+ nargs + 2, argarray);
gfc_add_expr_to_block (&block, tmp);
body = gfc_finish_block (&block);
Index: gcc/fortran/trans.h
===================================================================
--- gcc/fortran/trans.h (revision 127319)
+++ gcc/fortran/trans.h (working copy)
@@ -442,7 +442,7 @@ void gfc_generate_constructors (void);
bool get_array_ctor_strlen (stmtblock_t *, gfc_constructor *, tree *);
/* Generate a runtime error check. */
-void gfc_trans_runtime_check (tree, const char *, stmtblock_t *, locus *);
+void gfc_trans_runtime_check (tree, stmtblock_t *, locus *, const char *, ...);
/* Generate a call to free() after checking that its arg is non-NULL. */
tree gfc_call_free (tree);
Index: gcc/fortran/trans-io.c
===================================================================
--- gcc/fortran/trans-io.c (revision 127319)
+++ gcc/fortran/trans-io.c (working copy)
@@ -653,15 +653,17 @@ set_string (stmtblock_t * block, stmtblo
if (e->ts.type == BT_INTEGER && e->symtree->n.sym->attr.assign == 1)
{
char * msg;
+ tree cond;
gfc_conv_label_variable (&se, e);
tmp = GFC_DECL_STRING_LEN (se.expr);
- tmp = fold_build2 (LT_EXPR, boolean_type_node,
- tmp, build_int_cst (TREE_TYPE (tmp), 0));
+ cond = fold_build2 (LT_EXPR, boolean_type_node,
+ tmp, build_int_cst (TREE_TYPE (tmp), 0));
- asprintf(&msg, "Label assigned to variable '%s' is not a format label",
- e->symtree->name);
- gfc_trans_runtime_check (tmp, msg, &se.pre, &e->where);
+ asprintf(&msg, "Label assigned to variable '%s' (%%ld) is not a format "
+ "label", e->symtree->name);
+ gfc_trans_runtime_check (cond, &se.pre, &e->where, msg,
+ fold_convert (long_integer_type_node, tmp));
gfc_free (msg);
gfc_add_modify_expr (&se.pre, io,
Index: gcc/fortran/trans-decl.c
===================================================================
--- gcc/fortran/trans-decl.c (revision 127319)
+++ gcc/fortran/trans-decl.c (working copy)
@@ -2341,13 +2341,13 @@ gfc_build_builtin_function_decls (void)
gfor_fndecl_runtime_error =
gfc_build_library_function_decl (get_identifier (PREFIX("runtime_error")),
- void_type_node, 1, pchar_type_node);
+ void_type_node, -1, pchar_type_node);
/* The runtime_error function does not return. */
TREE_THIS_VOLATILE (gfor_fndecl_runtime_error) = 1;
gfor_fndecl_runtime_error_at =
gfc_build_library_function_decl (get_identifier (PREFIX("runtime_error_at")),
- void_type_node, 2, pchar_type_node,
+ void_type_node, -2, pchar_type_node,
pchar_type_node);
/* The runtime_error_at function does not return. */
TREE_THIS_VOLATILE (gfor_fndecl_runtime_error_at) = 1;
Index: gcc/fortran/trans-intrinsic.c
===================================================================
--- gcc/fortran/trans-intrinsic.c (revision 127319)
+++ gcc/fortran/trans-intrinsic.c (working copy)
@@ -855,7 +855,7 @@ gfc_conv_intrinsic_bound (gfc_se * se, g
tmp = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (TREE_TYPE (desc))];
tmp = fold_build2 (GE_EXPR, boolean_type_node, bound, tmp);
cond = fold_build2 (TRUTH_ORIF_EXPR, boolean_type_node, cond, tmp);
- gfc_trans_runtime_check (cond, gfc_msg_fault, &se->pre, &expr->where);
+ gfc_trans_runtime_check (cond, &se->pre, &expr->where, gfc_msg_fault);
}
}
@@ -1485,7 +1485,7 @@ gfc_conv_intrinsic_minmax (gfc_se * se,
expr->symtree->n.sym->name);
cond = build2 (EQ_EXPR, boolean_type_node, TREE_OPERAND (args[0], 0),
build_int_cst (TREE_TYPE (TREE_OPERAND (args[0], 0)), 0));
- gfc_trans_runtime_check (cond, msg, &se->pre, &expr->where);
+ gfc_trans_runtime_check (cond, &se->pre, &expr->where, msg);
gfc_free (msg);
}
@@ -1501,7 +1501,7 @@ gfc_conv_intrinsic_minmax (gfc_se * se,
expr->symtree->n.sym->name);
cond = build2 (EQ_EXPR, boolean_type_node, TREE_OPERAND (args[1], 0),
build_int_cst (TREE_TYPE (TREE_OPERAND (args[1], 0)), 0));
- gfc_trans_runtime_check (cond, msg, &se->pre, &expr->where);
+ gfc_trans_runtime_check (cond, &se->pre, &expr->where, msg);
gfc_free (msg);
}
@@ -3668,9 +3668,10 @@ gfc_conv_intrinsic_repeat (gfc_se * se,
/* Check that NCOPIES is not negative. */
cond = fold_build2 (LT_EXPR, boolean_type_node, ncopies,
build_int_cst (ncopies_type, 0));
- gfc_trans_runtime_check (cond,
- "Argument NCOPIES of REPEAT intrinsic is negative",
- &se->pre, &expr->where);
+ gfc_trans_runtime_check (cond, &se->pre, &expr->where,
+ "Argument NCOPIES of REPEAT intrinsic is negative "
+ "(its value is %lld)",
+ fold_convert (long_integer_type_node, ncopies));
/* If the source length is zero, any non negative value of NCOPIES
is valid, and nothing happens. */
@@ -3699,9 +3700,9 @@ gfc_conv_intrinsic_repeat (gfc_se * se,
build_int_cst (size_type_node, 0));
cond = fold_build3 (COND_EXPR, boolean_type_node, tmp, boolean_false_node,
cond);
- gfc_trans_runtime_check (cond,
- "Argument NCOPIES of REPEAT intrinsic is too large",
- &se->pre, &expr->where);
+ gfc_trans_runtime_check (cond, &se->pre, &expr->where,
+ "Argument NCOPIES of REPEAT intrinsic is too large");
+
/* Compute the destination length. */
dlen = fold_build2 (MULT_EXPR, gfc_charlen_type_node,
Index: libgfortran/runtime/error.c
===================================================================
--- libgfortran/runtime/error.c (revision 127319)
+++ libgfortran/runtime/error.c (working copy)
@@ -267,11 +267,17 @@ iexport(runtime_error);
* run time error generated by the front end compiler. */
void
-runtime_error_at (const char *where, const char *message)
+runtime_error_at (const char *where, const char *message, ...)
{
+ va_list ap;
+
recursion_check ();
st_printf ("%s\n", where);
- st_printf ("Fortran runtime error: %s\n", message);
+ st_printf ("Fortran runtime error: ");
+ va_start (ap, message);
+ st_vprintf (message, ap);
+ va_end (ap);
+ st_printf ("\n");
sys_exit (2);
}
iexport(runtime_error_at);
Index: libgfortran/libgfortran.h
===================================================================
--- libgfortran/libgfortran.h (revision 127319)
+++ libgfortran/libgfortran.h (working copy)
@@ -599,8 +599,8 @@ extern void runtime_error (const char *,
__attribute__ ((noreturn, format (printf, 1, 2)));
iexport_proto(runtime_error);
-extern void runtime_error_at (const char *, const char *)
-__attribute__ ((noreturn));
+extern void runtime_error_at (const char *, const char *, ...)
+ __attribute__ ((noreturn, format (printf, 2, 3)));
iexport_proto(runtime_error_at);
extern void internal_error (st_parameter_common *, const char *)
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [gfortran,patch] More detailled runtime bounds-checking messages...
2007-08-09 23:32 [gfortran,patch] More detailled runtime bounds-checking messages FX Coudert
@ 2007-08-10 9:48 ` Tobias Burnus
0 siblings, 0 replies; 2+ messages in thread
From: Tobias Burnus @ 2007-08-10 9:48 UTC (permalink / raw)
To: FX Coudert; +Cc: GNU Fortran, gcc-patches list
:REVIEWMAIL:
FX Coudert wrote:
> So now, I'm looking for a review to get this in, and eventually
> suggestions to change the wording if deemed inappropriate.
> Bootstrapped and regtested (both with and without -fbounds-check) on
> x86_64-linux, OK to commit?
The patch is OK.
In terms of wording (two files, one array (-4:5) accessed as a(1:-5:-1)
and the other a string len=5 a(2:6)):
NAG f95:
Subscript 1 of A (value -5) is out of range (-4:5)
Out of range: substring ending position 6 is greater than length 5
g95:
At line 4 of file b.f90 (Unit 6)
Fortran runtime error: Array section out of bounds
Fortran runtime error: Substring reference out of bounds: (2:6) in
string of length 5
ifort:
forrtl: severe (408): fort: (3): Subscript #1 of the array A has value
-5 which is less than the lower bound of -4
forrtl: severe (408): fort: (4): Variable A has substring ending point 6
which is greater than the variable length of 5
sunf95:
Subscript out of range. Location: line 5 column 15 of 'a.f90'
Subscript number 1 has value -5 in array 'A'
Substring out of range. Location: line 5 column 15 of 'b.f90'
The ending point has value 6 for substring of 'A'
gfortran (new):
At line 5 of file a.f90
Fortran runtime error: Array reference out of bounds, lower bound of
dimension 1 of array 'a' exceeded, -5 is smaller than -4
Fortran runtime error: Substring out of bounds: upper bound (6) of 'a'
exceeds string length (5)
gfortran contains all information (unless one wants to show both lower
and upper bound in the error message); I found none of the other ones
really superior.
One may argue whether "subscript" or "dimension" is the better word. I
have to admit that I like the one by NAG f95 as they are concise.
Tobias
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2007-08-10 9:48 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-08-09 23:32 [gfortran,patch] More detailled runtime bounds-checking messages FX Coudert
2007-08-10 9:48 ` Tobias Burnus
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).