support array bounds checking
From-SVN: r26592
This commit is contained in:
parent
01680a2591
commit
6b55276ed9
@ -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>
|
Tue Apr 20 01:38:57 1999 Craig Burley <craig@jcb-sc.com>
|
||||||
|
|
||||||
* bugs.texi, news.texi: Clarify -malign-double situation.
|
* bugs.texi, news.texi: Clarify -malign-double situation.
|
||||||
|
@ -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_gfrtCOPY, "s_copy", FFECOM_rttypeVOID_, 0, FALSE, FALSE)
|
||||||
DEFGFRT (FFECOM_gfrtPAUSE, "s_paus", 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_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_gfrtSRDUE, "s_rdue", FFECOM_rttypeINTEGER_, 0, FALSE, FALSE)
|
||||||
DEFGFRT (FFECOM_gfrtERDUE, "e_rdue", FFECOM_rttypeINTEGER_, 0, FALSE, FALSE)
|
DEFGFRT (FFECOM_gfrtERDUE, "e_rdue", FFECOM_rttypeINTEGER_, 0, FALSE, FALSE)
|
||||||
|
359
gcc/f/com.c
359
gcc/f/com.c
@ -745,6 +745,233 @@ static tree shadowed_labels;
|
|||||||
|
|
||||||
#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
|
#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
|
||||||
|
|
||||||
|
/* 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
|
/* This is like gcc's stabilize_reference -- in fact, most of the code
|
||||||
comes from that -- but it handles the situation where the reference
|
comes from that -- but it handles the situation where the reference
|
||||||
is going to have its subparts picked at, and it shouldn't change
|
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:
|
case FFEBLD_opARRAYREF:
|
||||||
{
|
{
|
||||||
ffebld dims[FFECOM_dimensionsMAX];
|
|
||||||
tree array;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
ffecom_char_args_ (&item, length, ffebld_left (expr));
|
ffecom_char_args_ (&item, length, ffebld_left (expr));
|
||||||
|
|
||||||
if (item == error_mark_node || *length == error_mark_node)
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Build up ARRAY_REFs in reverse order (since we're column major
|
item = ffecom_arrayref_ (item, expr, 1);
|
||||||
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)))));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1788,6 +1992,9 @@ ffecom_char_args_x_ (tree *xitem, tree *length, ffebld expr, bool with_null)
|
|||||||
ffebld thing = ffebld_right (expr);
|
ffebld thing = ffebld_right (expr);
|
||||||
tree start_tree;
|
tree start_tree;
|
||||||
tree end_tree;
|
tree end_tree;
|
||||||
|
char *char_name;
|
||||||
|
ffebld left_symter;
|
||||||
|
tree array;
|
||||||
|
|
||||||
assert (ffebld_op (thing) == FFEBLD_opITEM);
|
assert (ffebld_op (thing) == FFEBLD_opITEM);
|
||||||
start = ffebld_head (thing);
|
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);
|
assert (ffebld_trail (thing) == NULL);
|
||||||
end = ffebld_head (thing);
|
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));
|
ffecom_char_args_ (&item, length, ffebld_left (expr));
|
||||||
|
|
||||||
if (item == error_mark_node || *length == error_mark_node)
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
array = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item)));
|
||||||
|
|
||||||
if (start == NULL)
|
if (start == NULL)
|
||||||
{
|
{
|
||||||
if (end == NULL)
|
if (end == NULL)
|
||||||
;
|
;
|
||||||
else
|
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,
|
end_tree = convert (ffecom_f2c_ftnlen_type_node,
|
||||||
ffecom_expr (end));
|
end_tree);
|
||||||
|
|
||||||
if (end_tree == error_mark_node)
|
if (end_tree == error_mark_node)
|
||||||
{
|
{
|
||||||
@ -1823,8 +2046,12 @@ ffecom_char_args_x_ (tree *xitem, tree *length, ffebld expr, bool with_null)
|
|||||||
}
|
}
|
||||||
else
|
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,
|
start_tree = convert (ffecom_f2c_ftnlen_type_node,
|
||||||
ffecom_expr (start));
|
start_tree);
|
||||||
|
|
||||||
if (start_tree == error_mark_node)
|
if (start_tree == error_mark_node)
|
||||||
{
|
{
|
||||||
@ -1852,8 +2079,12 @@ ffecom_char_args_x_ (tree *xitem, tree *length, ffebld expr, bool with_null)
|
|||||||
}
|
}
|
||||||
else
|
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,
|
end_tree = convert (ffecom_f2c_ftnlen_type_node,
|
||||||
ffecom_expr (end));
|
end_tree);
|
||||||
|
|
||||||
if (end_tree == error_mark_node)
|
if (end_tree == error_mark_node)
|
||||||
{
|
{
|
||||||
@ -2973,17 +3204,11 @@ ffecom_expr_ (ffebld expr, tree dest_tree, ffebld dest,
|
|||||||
|
|
||||||
case FFEBLD_opARRAYREF:
|
case FFEBLD_opARRAYREF:
|
||||||
{
|
{
|
||||||
ffebld dims[FFECOM_dimensionsMAX];
|
if (0 /* ~~~~~ ffe_is_flat_arrays () */)
|
||||||
#if FFECOM_FASTER_ARRAY_REFS
|
|
||||||
tree array;
|
|
||||||
#endif
|
|
||||||
int i;
|
|
||||||
|
|
||||||
#if FFECOM_FASTER_ARRAY_REFS
|
|
||||||
t = ffecom_ptr_to_expr (ffebld_left (expr));
|
t = ffecom_ptr_to_expr (ffebld_left (expr));
|
||||||
#else
|
else
|
||||||
t = ffecom_expr (ffebld_left (expr));
|
t = ffecom_expr (ffebld_left (expr));
|
||||||
#endif
|
|
||||||
if (t == error_mark_node)
|
if (t == error_mark_node)
|
||||||
return t;
|
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
|
return error_mark_node; /* Make sure non-const ref is to
|
||||||
non-reg. */
|
non-reg. */
|
||||||
|
|
||||||
/* Build up ARRAY_REFs in reverse order (since we're column major
|
t = ffecom_arrayref_ (t, expr, 0);
|
||||||
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
|
|
||||||
|
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
@ -12522,10 +12718,6 @@ ffecom_ptr_to_expr (ffebld expr)
|
|||||||
|
|
||||||
case FFEBLD_opARRAYREF:
|
case FFEBLD_opARRAYREF:
|
||||||
{
|
{
|
||||||
ffebld dims[FFECOM_dimensionsMAX];
|
|
||||||
tree array;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
item = ffecom_ptr_to_expr (ffebld_left (expr));
|
item = ffecom_ptr_to_expr (ffebld_left (expr));
|
||||||
|
|
||||||
if (item == error_mark_node)
|
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
|
return error_mark_node; /* Make sure non-const ref is to
|
||||||
non-reg. */
|
non-reg. */
|
||||||
|
|
||||||
/* Build up ARRAY_REFs in reverse order (since we're column major
|
item = ffecom_arrayref_ (item, expr, 1);
|
||||||
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)))))));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return item;
|
return item;
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
@c %**start of header
|
@c %**start of header
|
||||||
@setfilename g77.info
|
@setfilename g77.info
|
||||||
|
|
||||||
@set last-update 1999-04-17
|
@set last-update 1999-04-23
|
||||||
@set copyrights-g77 1995-1999
|
@set copyrights-g77 1995-1999
|
||||||
|
|
||||||
@include root.texi
|
@include root.texi
|
||||||
@ -1471,6 +1471,7 @@ by type. Explanations are in the following sections.
|
|||||||
-falias-check -fargument-alias
|
-falias-check -fargument-alias
|
||||||
-fargument-noalias -fno-argument-noalias-global
|
-fargument-noalias -fno-argument-noalias-global
|
||||||
-fno-globals
|
-fno-globals
|
||||||
|
-fsubscript-check -ff2c-subscript-check
|
||||||
@end smallexample
|
@end smallexample
|
||||||
@end table
|
@end table
|
||||||
|
|
||||||
@ -3370,6 +3371,73 @@ and warns about similar disagreements
|
|||||||
that are currently believed to not
|
that are currently believed to not
|
||||||
likely to result in the compiler later crashing
|
likely to result in the compiler later crashing
|
||||||
or producing incorrect code.
|
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
|
@end table
|
||||||
|
|
||||||
@xref{Code Gen Options,,Options for Code Generation Conventions,
|
@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
|
Overflowing the bounds of an array---usually by writing beyond
|
||||||
the end of it---is one of two kinds of bug that often occurs
|
the end of it---is one of two kinds of bug that often occurs
|
||||||
in Fortran code.
|
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
|
The other kind of bug is a mismatch between the actual arguments
|
||||||
passed to a procedure and the dummy arguments as declared by that
|
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,
|
data representing the placement of other data in memory (that is,
|
||||||
pointers, such as the placement of stack frames in memory).
|
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
|
ability to catch and report some of these problems at compile, link, or
|
||||||
run time, such as by generating code to detect references to
|
run time, such as by generating code to detect references to
|
||||||
beyond the bounds of an array, or checking for agreement between
|
beyond the bounds of most arrays (except assumed-size arrays),
|
||||||
calling and called procedures.
|
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
|
In the meantime, finding and fixing the programming
|
||||||
bugs that lead to these behaviors is, ultimately, the user's
|
bugs that lead to these behaviors is, ultimately, the user's
|
||||||
@ -11275,7 +11347,6 @@ Better diagnostics:
|
|||||||
|
|
||||||
Run-time facilities:
|
Run-time facilities:
|
||||||
* Uninitialized Variables at Run Time::
|
* Uninitialized Variables at Run Time::
|
||||||
* Bounds Checking at Run Time::
|
|
||||||
* Portable Unformatted Files::
|
* Portable Unformatted Files::
|
||||||
|
|
||||||
Debugging:
|
Debugging:
|
||||||
@ -12159,15 +12230,6 @@ some kinds of uninitialized variables at run time.
|
|||||||
Note that use of the options @samp{-O -Wuninitialized} can catch
|
Note that use of the options @samp{-O -Wuninitialized} can catch
|
||||||
many such bugs at compile time.
|
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
|
@node Portable Unformatted Files
|
||||||
@subsection Portable Unformatted Files
|
@subsection Portable Unformatted Files
|
||||||
|
|
||||||
|
@ -147,6 +147,10 @@ FTNOPT( "-fglobals", "" )
|
|||||||
FTNOPT( "-fno-globals", "Disable fatal diagnostics about inter-procedural problems" )
|
FTNOPT( "-fno-globals", "Disable fatal diagnostics about inter-procedural problems" )
|
||||||
FTNOPT( "-ftypeless-boz", "Make prefix-radix non-decimal constants be typeless" )
|
FTNOPT( "-ftypeless-boz", "Make prefix-radix non-decimal constants be typeless" )
|
||||||
FTNOPT( "-fno-typeless-boz", "" )
|
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( "-Wglobals", "" )
|
||||||
FTNOPT( "-Wno-globals", "Disable warnings about inter-procedural problems" )
|
FTNOPT( "-Wno-globals", "Disable warnings about inter-procedural problems" )
|
||||||
/*"-Wimplicit",*/
|
/*"-Wimplicit",*/
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
@c in the standalone derivations of this file (e.g. NEWS).
|
@c in the standalone derivations of this file (e.g. NEWS).
|
||||||
@set copyrights-news 1995-1999
|
@set copyrights-news 1995-1999
|
||||||
|
|
||||||
@set last-update-news 1999-04-20
|
@set last-update-news 1999-04-23
|
||||||
|
|
||||||
@include root.texi
|
@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.)
|
(It is passed to the @file{f771} driver.)
|
||||||
@end ifclear
|
@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
|
@item
|
||||||
Source file names with the suffixes @samp{.FOR} and @samp{.FPP}
|
Source file names with the suffixes @samp{.FOR} and @samp{.FPP}
|
||||||
now are recognized by @code{g77}
|
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
|
now reliably aligns @emph{all} double-precision variables and arrays
|
||||||
on Intel x86 targets.
|
on Intel x86 targets.
|
||||||
|
|
||||||
|
@ifclear USERVISONLY
|
||||||
@item
|
@item
|
||||||
Even without the @samp{-malign-double} option,
|
Even without the @samp{-malign-double} option,
|
||||||
@code{g77} reliably aligns local double-precision variables
|
@code{g77} reliably aligns local double-precision variables
|
||||||
that are not in @code{EQUIVALENCE} areas
|
that are not in @code{EQUIVALENCE} areas
|
||||||
and not @code{SAVE}'d.
|
and not @code{SAVE}'d.
|
||||||
|
@end ifclear
|
||||||
|
|
||||||
|
@ifclear USERVISONLY
|
||||||
@item
|
@item
|
||||||
A substantial portion of the @code{g77} front end's code-generation component
|
A substantial portion of the @code{g77} front end's code-generation component
|
||||||
was rewritten.
|
was rewritten.
|
||||||
@ -238,6 +252,7 @@ by the @code{gcc} back end.
|
|||||||
One effect of this rewrite is that some codes no longer produce
|
One effect of this rewrite is that some codes no longer produce
|
||||||
a spurious ``label @var{lab} used before containing binding contour''
|
a spurious ``label @var{lab} used before containing binding contour''
|
||||||
message.
|
message.
|
||||||
|
@end ifclear
|
||||||
|
|
||||||
@item
|
@item
|
||||||
Support for the @samp{-fugly} option has been removed.
|
Support for the @samp{-fugly} option has been removed.
|
||||||
|
@ -3096,7 +3096,7 @@ ffeste_R819B (ffestw block, ffelab label UNUSED, ffebld expr)
|
|||||||
|
|
||||||
if (expr)
|
if (expr)
|
||||||
{
|
{
|
||||||
tree loop;
|
struct nesting *loop;
|
||||||
|
|
||||||
result = ffecom_make_tempvar ("dowhile", integer_type_node,
|
result = ffecom_make_tempvar ("dowhile", integer_type_node,
|
||||||
FFETARGET_charactersizeNONE, -1);
|
FFETARGET_charactersizeNONE, -1);
|
||||||
|
@ -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_null_version_ = FALSE;
|
||||||
bool ffe_is_onetrip_ = FALSE;
|
bool ffe_is_onetrip_ = FALSE;
|
||||||
bool ffe_is_silent_ = TRUE;
|
bool ffe_is_silent_ = TRUE;
|
||||||
|
bool ffe_is_subscript_check_ = FALSE;
|
||||||
bool ffe_is_typeless_boz_ = FALSE;
|
bool ffe_is_typeless_boz_ = FALSE;
|
||||||
bool ffe_is_pedantic_ = FFETARGET_defaultIS_PEDANTIC;
|
bool ffe_is_pedantic_ = FFETARGET_defaultIS_PEDANTIC;
|
||||||
bool ffe_is_saveall_; /* TRUE if mainprog or SAVE (no args) seen. */
|
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);
|
ffe_set_is_globals (TRUE);
|
||||||
else if (strcmp (&opt[2], "no-globals") == 0)
|
else if (strcmp (&opt[2], "no-globals") == 0)
|
||||||
ffe_set_is_globals (FALSE);
|
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)
|
else if (strcmp (&opt[2], "typeless-boz") == 0)
|
||||||
ffe_set_is_typeless_boz (TRUE);
|
ffe_set_is_typeless_boz (TRUE);
|
||||||
else if (strcmp (&opt[2], "no-typeless-boz") == 0)
|
else if (strcmp (&opt[2], "no-typeless-boz") == 0)
|
||||||
|
@ -97,6 +97,7 @@ extern bool ffe_is_mainprog_;
|
|||||||
extern bool ffe_is_null_version_;
|
extern bool ffe_is_null_version_;
|
||||||
extern bool ffe_is_onetrip_;
|
extern bool ffe_is_onetrip_;
|
||||||
extern bool ffe_is_silent_;
|
extern bool ffe_is_silent_;
|
||||||
|
extern bool ffe_is_subscript_check_;
|
||||||
extern bool ffe_is_typeless_boz_;
|
extern bool ffe_is_typeless_boz_;
|
||||||
extern bool ffe_is_pedantic_;
|
extern bool ffe_is_pedantic_;
|
||||||
extern bool ffe_is_saveall_;
|
extern bool ffe_is_saveall_;
|
||||||
@ -188,6 +189,7 @@ void ffe_terminate_4 (void);
|
|||||||
#define ffe_is_saveall() ffe_is_saveall_
|
#define ffe_is_saveall() ffe_is_saveall_
|
||||||
#define ffe_is_second_underscore() ffe_is_second_underscore_
|
#define ffe_is_second_underscore() ffe_is_second_underscore_
|
||||||
#define ffe_is_silent() ffe_is_silent_
|
#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_typeless_boz() ffe_is_typeless_boz_
|
||||||
#define ffe_is_ugly_args() ffe_is_ugly_args_
|
#define ffe_is_ugly_args() ffe_is_ugly_args_
|
||||||
#define ffe_is_ugly_assign() ffe_is_ugly_assign_
|
#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_saveall(f) (ffe_is_saveall_ = (f))
|
||||||
#define ffe_set_is_second_underscore(f) (ffe_is_second_underscore_ = (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_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_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_args(f) (ffe_is_ugly_args_ = (f))
|
||||||
#define ffe_set_is_ugly_assign(f) (ffe_is_ugly_assign_ = (f))
|
#define ffe_set_is_ugly_assign(f) (ffe_is_ugly_assign_ = (f))
|
||||||
|
@ -1 +1 @@
|
|||||||
const char *ffe_version_string = "0.5.24-19990420";
|
const char *ffe_version_string = "0.5.24-19990423";
|
||||||
|
Loading…
Reference in New Issue
Block a user