gcj.texi (Configure-time Options): Add -fcheck-references.
2001-02-07 Andrew Haley <aph@redhat.com> * gcj.texi (Configure-time Options): Add -fcheck-references. * expr.c (build_java_indirect_ref): New function. (build_java_array_length_access): Use build_java_indirect_ref to check for null references. (build_java_arrayaccess): Likewise. (build_get_class): Likewise. (build_field_ref): Likewise. (invoke_build_dtable): Likewise. (build_invokeinterface): Likewise. * lang.c (lang_f_options): Add flag_check_references. * jvspec.c (jvgenmain_spec): Add flag_check_references. * java-tree.h (flag_check_references): New variable. * lang.c (flag_check_references): Likewise. From-SVN: r40780
This commit is contained in:
parent
8e4ce833ab
commit
4ff17c6a1a
@ -1,3 +1,19 @@
|
||||
2001-02-07 Andrew Haley <aph@redhat.com>
|
||||
|
||||
* gcj.texi (Configure-time Options): Add -fcheck-references.
|
||||
* expr.c (build_java_indirect_ref): New function.
|
||||
(build_java_array_length_access): Use build_java_indirect_ref to
|
||||
check for null references.
|
||||
(build_java_arrayaccess): Likewise.
|
||||
(build_get_class): Likewise.
|
||||
(build_field_ref): Likewise.
|
||||
(invoke_build_dtable): Likewise.
|
||||
(build_invokeinterface): Likewise.
|
||||
* lang.c (lang_f_options): Add flag_check_references.
|
||||
* jvspec.c (jvgenmain_spec): Add flag_check_references.
|
||||
* java-tree.h (flag_check_references): New variable.
|
||||
* lang.c (flag_check_references): Likewise.
|
||||
|
||||
2001-03-23 Bryce McKinlay <bryce@albatross.co.nz>
|
||||
|
||||
* gjavah.c (cxx_keywords): Update from the definitive list in cp/lex.c.
|
||||
|
102
gcc/java/expr.c
102
gcc/java/expr.c
@ -710,36 +710,46 @@ build_java_array_length_access (node)
|
||||
length = java_array_type_length (type);
|
||||
if (length >= 0)
|
||||
return build_int_2 (length, 0);
|
||||
|
||||
return fold (build1 (INDIRECT_REF,
|
||||
int_type_node,
|
||||
return fold (build1 (INDIRECT_REF, int_type_node,
|
||||
fold (build (PLUS_EXPR, ptr_type_node,
|
||||
node,
|
||||
java_check_reference (node, 1),
|
||||
JAVA_ARRAY_LENGTH_OFFSET(node)))));
|
||||
}
|
||||
|
||||
/* Optionally checks an array against the NULL pointer, eventually throwing a
|
||||
NullPointerException. It could replace signal handling, but tied to NULL.
|
||||
ARG1: the pointer to check, ARG2: the expression to use if
|
||||
the pointer is non-null and ARG3 the type that should be returned. */
|
||||
/* Optionally checks a reference against the NULL pointer. ARG1: the
|
||||
expr, ARG2: we should check the reference. Don't generate extra
|
||||
checks if we're not generating code. */
|
||||
|
||||
tree
|
||||
java_check_reference (expr, check)
|
||||
tree expr;
|
||||
int check;
|
||||
{
|
||||
if (!flag_syntax_only && check)
|
||||
{
|
||||
tree cond;
|
||||
expr = save_expr (expr);
|
||||
cond = build (COND_EXPR, void_type_node,
|
||||
build (EQ_EXPR, boolean_type_node, expr, null_pointer_node),
|
||||
build (CALL_EXPR, void_type_node,
|
||||
build_address_of (soft_nullpointer_node),
|
||||
NULL_TREE, NULL_TREE),
|
||||
empty_stmt_node);
|
||||
expr = build (COMPOUND_EXPR, TREE_TYPE (expr), cond, expr);
|
||||
}
|
||||
|
||||
return expr;
|
||||
}
|
||||
|
||||
/* Reference an object: just like an INDIRECT_REF, but with checking. */
|
||||
|
||||
tree
|
||||
build_java_arraynull_check (node, expr, type)
|
||||
tree node ATTRIBUTE_UNUSED;
|
||||
tree expr;
|
||||
tree type ATTRIBUTE_UNUSED;
|
||||
build_java_indirect_ref (type, expr, check)
|
||||
tree type;
|
||||
tree expr;
|
||||
int check;
|
||||
{
|
||||
#if 0
|
||||
static int java_array_access_throws_null_exception = 0;
|
||||
node = ???;
|
||||
if (java_array_access_throws_null_exception)
|
||||
return (build (COND_EXPR,
|
||||
type,
|
||||
build (EQ_EXPR, int_type_node, node, null_pointer_node),
|
||||
build_java_athrow (node), expr ));
|
||||
else
|
||||
#endif
|
||||
return (expr);
|
||||
return build1 (INDIRECT_REF, type, java_check_reference (expr, check));
|
||||
}
|
||||
|
||||
static tree
|
||||
@ -792,15 +802,15 @@ build_java_arrayaccess (array, type, index)
|
||||
TREE_SIDE_EFFECTS( throw ) = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
node = build1 (INDIRECT_REF, type,
|
||||
fold (build (PLUS_EXPR, ptr_type_node,
|
||||
array,
|
||||
java_check_reference (array, flag_check_references),
|
||||
(throw ? build (COMPOUND_EXPR, int_type_node,
|
||||
throw, arith )
|
||||
: arith))));
|
||||
|
||||
return (fold (build_java_arraynull_check (array, node, type)));
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
/* Makes sure that INDEXED_TYPE is appropriate. If not, make it from
|
||||
@ -1008,7 +1018,7 @@ expand_java_array_length ()
|
||||
tree array = pop_value (ptr_type_node);
|
||||
tree length = build_java_array_length_access (array);
|
||||
|
||||
push_value (build_java_arraynull_check (array, length, int_type_node));
|
||||
push_value (length);
|
||||
}
|
||||
|
||||
/* Emit code for the call to _Jv_Monitor{Enter,Exit}. CALL can be
|
||||
@ -1118,7 +1128,8 @@ build_get_class (value)
|
||||
return build (COMPONENT_REF, class_ptr_type,
|
||||
build1 (INDIRECT_REF, dtable_type,
|
||||
build (COMPONENT_REF, dtable_ptr_type,
|
||||
build1 (INDIRECT_REF, object_type_node, value),
|
||||
build_java_indirect_ref (object_type_node, value,
|
||||
flag_check_references),
|
||||
vtable_field)),
|
||||
class_field);
|
||||
}
|
||||
@ -1485,8 +1496,8 @@ build_field_ref (self_value, self_class, name)
|
||||
#ifdef JAVA_USE_HANDLES
|
||||
self_value = unhand_expr (self_value);
|
||||
#endif
|
||||
self_value = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (self_value)),
|
||||
self_value);
|
||||
self_value = build_java_indirect_ref (TREE_TYPE (TREE_TYPE (self_value)),
|
||||
self_value, flag_check_references);
|
||||
return fold (build (COMPONENT_REF, TREE_TYPE (field_decl),
|
||||
self_value, field_decl));
|
||||
}
|
||||
@ -1780,7 +1791,8 @@ invoke_build_dtable (is_invoke_interface, arg_list)
|
||||
|
||||
if (dtable_ident == NULL_TREE)
|
||||
dtable_ident = get_identifier ("vtable");
|
||||
dtable = build1 (INDIRECT_REF, object_type_node, objectref );
|
||||
dtable = build_java_indirect_ref (object_type_node, objectref,
|
||||
flag_check_references);
|
||||
dtable = build (COMPONENT_REF, dtable_ptr_type, dtable,
|
||||
lookup_field (&object_type_node, dtable_ident));
|
||||
|
||||
@ -1829,7 +1841,7 @@ build_invokeinterface (dtable, method)
|
||||
ggc_add_tree_root (&class_ident, 1);
|
||||
}
|
||||
|
||||
dtable = build1 (INDIRECT_REF, dtable_type, dtable);
|
||||
dtable = build_java_indirect_ref (dtable_type, dtable, flag_check_references);
|
||||
dtable = build (COMPONENT_REF, class_ptr_type, dtable,
|
||||
lookup_field (&dtable_type, class_ident));
|
||||
|
||||
@ -1875,7 +1887,7 @@ expand_invoke (opcode, method_ref_index, nargs)
|
||||
const char *self_name
|
||||
= IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (self_type)));
|
||||
tree call, func, method, arg_list, method_type;
|
||||
tree cond = NULL_TREE;
|
||||
tree check = NULL_TREE;
|
||||
|
||||
if (! CLASS_LOADED_P (self_type))
|
||||
{
|
||||
@ -1957,7 +1969,7 @@ expand_invoke (opcode, method_ref_index, nargs)
|
||||
the new `self' expression once. */
|
||||
tree save_arg = save_expr (TREE_VALUE (arg_list));
|
||||
TREE_VALUE (arg_list) = save_arg;
|
||||
cond = build (EQ_EXPR, boolean_type_node, save_arg, null_pointer_node);
|
||||
check = java_check_reference (save_arg, 1);
|
||||
func = build_known_method_ref (method, method_type, self_type,
|
||||
method_signature, arg_list);
|
||||
}
|
||||
@ -1974,20 +1986,9 @@ expand_invoke (opcode, method_ref_index, nargs)
|
||||
call = build (CALL_EXPR, TREE_TYPE (method_type), func, arg_list, NULL_TREE);
|
||||
TREE_SIDE_EFFECTS (call) = 1;
|
||||
|
||||
if (cond != NULL_TREE)
|
||||
if (check != NULL_TREE)
|
||||
{
|
||||
/* We have to make the `then' branch a compound expression to
|
||||
make the types turn out right. This seems bizarre. */
|
||||
call = build (COND_EXPR, TREE_TYPE (call), cond,
|
||||
build (COMPOUND_EXPR, TREE_TYPE (call),
|
||||
build (CALL_EXPR, void_type_node,
|
||||
build_address_of (soft_nullpointer_node),
|
||||
NULL_TREE, NULL_TREE),
|
||||
(FLOAT_TYPE_P (TREE_TYPE (call))
|
||||
? build_real (TREE_TYPE (call), dconst0)
|
||||
: build1 (CONVERT_EXPR, TREE_TYPE (call),
|
||||
integer_zero_node))),
|
||||
call);
|
||||
call = build (COMPOUND_EXPR, TREE_TYPE (call), check, call);
|
||||
TREE_SIDE_EFFECTS (call) = 1;
|
||||
}
|
||||
|
||||
@ -2428,8 +2429,9 @@ java_lang_expand_expr (exp, target, tmode, modifier)
|
||||
init = init_decl;
|
||||
}
|
||||
expand_assignment (build (COMPONENT_REF, TREE_TYPE (data_fld),
|
||||
build1 (INDIRECT_REF, array_type,
|
||||
array_decl), data_fld), init, 0, 0);
|
||||
build_java_indirect_ref (array_type,
|
||||
array_decl, flag_check_references),
|
||||
data_fld), init, 0, 0);
|
||||
return tmp;
|
||||
}
|
||||
case BLOCK:
|
||||
|
@ -758,6 +758,12 @@ hash table and not in the object itself.
|
||||
On some systems, a library routine is called to perform integer
|
||||
division. This is required to get exception handling correct when
|
||||
dividing by zero.
|
||||
|
||||
@item -fcheck-references
|
||||
On some systems it's necessary to insert inline checks whenever
|
||||
accessing an object via a reference. On other systems you won't need
|
||||
this because null pointer accesses are caught automatically by the
|
||||
processor.
|
||||
@end table
|
||||
|
||||
|
||||
|
@ -181,6 +181,9 @@ extern int flag_use_boehm_gc;
|
||||
object to its synchronization structure. */
|
||||
extern int flag_hash_synchronization;
|
||||
|
||||
/* When non zero, generate checks for references to NULL. */
|
||||
extern int flag_check_references;
|
||||
|
||||
/* Encoding used for source files. */
|
||||
extern const char *current_encoding;
|
||||
|
||||
@ -1010,6 +1013,8 @@ extern tree build_anewarray PARAMS ((tree, tree));
|
||||
extern tree build_new_array PARAMS ((tree, tree));
|
||||
extern tree build_java_array_length_access PARAMS ((tree));
|
||||
extern tree build_java_arraynull_check PARAMS ((tree, tree, tree));
|
||||
extern tree build_java_indirect_ref PARAMS ((tree, tree, int));
|
||||
extern tree java_check_reference PARAMS ((tree, int));
|
||||
extern tree build_get_class PARAMS ((tree));
|
||||
extern tree build_instanceof PARAMS ((tree, tree));
|
||||
extern tree create_label_decl PARAMS ((tree));
|
||||
|
@ -63,6 +63,7 @@ const char jvgenmain_spec[] =
|
||||
%{<fuse-boehm-gc} %{<fhash-synchronization} %{<fjni}\
|
||||
%{<fclasspath*} %{<fCLASSPATH*} %{<foutput-class-dir}\
|
||||
%{<fuse-divide-subroutine} %{<fno-use-divide-subroutine}\
|
||||
%{<fcheck-references} %{<fno-check-references}\
|
||||
%{f*} -fdollars-in-identifiers\
|
||||
%{aux-info*}\
|
||||
%{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
|
||||
|
@ -138,6 +138,9 @@ int flag_jni = 0;
|
||||
file. */
|
||||
int flag_newer = 1;
|
||||
|
||||
/* When non zero, generate checks for references to NULL. */
|
||||
int flag_check_references = 0;
|
||||
|
||||
/* The encoding of the source file. */
|
||||
const char *current_encoding = NULL;
|
||||
|
||||
@ -164,7 +167,8 @@ lang_f_options[] =
|
||||
{"use-divide-subroutine", &flag_use_divide_subroutine, 1},
|
||||
{"use-boehm-gc", &flag_use_boehm_gc, 1},
|
||||
{"hash-synchronization", &flag_hash_synchronization, 1},
|
||||
{"jni", &flag_jni, 1}
|
||||
{"jni", &flag_jni, 1},
|
||||
{"check-references", &flag_check_references, 1},
|
||||
};
|
||||
|
||||
static struct string_option
|
||||
|
Loading…
Reference in New Issue
Block a user