class.c (layout_class_method): Generate <clinit>'s rtl for interfaces.
Sat Apr 24 16:50:19 1999 Alexandre Petit-Bianco <apbianco@cygnus.com> * class.c (layout_class_method): Generate <clinit>'s rtl for interfaces. * decl.c (complete_start_java_method): Don't call _Jv_InitClass for interfaces' <clinit>. * expr.c (lookup_field): Search for fields in interfaces. (expand_invoke): Fixed indentation. (expand_java_field_op): Likewise. Use IS_CLINIT. * parse.h (JPRIMITIVE_TYPE_OR_VOID_P): Macro removed. (IS_CLINIT): New macro. * parse.y (type_declaration:): Call maybe_generate_clinit after an interface was parsed. (maybe_generate_clinit): Don't generate if the current class is an interface with only fields of primitive types. (reset_method_name): Use IS_CLINIT. (java_complete_expand_method): Expand <clinit> when it exists for interfaces. Use IS_CLINIT. (resolve_expression_name): Use DECL_CONTEXT instead of current_class to build static field references. (java_complete_lhs): Use IS__CLINIT. Don't use SAVE_EXPR on ARRAY_REF when doing xreferencing. (check_final_assignment): Fixed typo in leading comment. Use IS_CLINIT. (patch_array_ref): Don't fully expand array references when xreferencing. (patch_return): Use IS_CLINIT. (patch_throw_statement): Likewise. From-SVN: r26661
This commit is contained in:
parent
ccd63d90d1
commit
7f1d48663e
@ -1,3 +1,32 @@
|
||||
Sat Apr 24 16:50:19 1999 Alexandre Petit-Bianco <apbianco@cygnus.com>
|
||||
|
||||
* class.c (layout_class_method): Generate <clinit>'s rtl for
|
||||
interfaces.
|
||||
* decl.c (complete_start_java_method): Don't call _Jv_InitClass
|
||||
for interfaces' <clinit>.
|
||||
* expr.c (lookup_field): Search for fields in interfaces.
|
||||
(expand_invoke): Fixed indentation.
|
||||
(expand_java_field_op): Likewise. Use IS_CLINIT.
|
||||
* parse.h (JPRIMITIVE_TYPE_OR_VOID_P): Macro removed.
|
||||
(IS_CLINIT): New macro.
|
||||
* parse.y (type_declaration:): Call maybe_generate_clinit after an
|
||||
interface was parsed.
|
||||
(maybe_generate_clinit): Don't generate if the current class is an
|
||||
interface with only fields of primitive types.
|
||||
(reset_method_name): Use IS_CLINIT.
|
||||
(java_complete_expand_method): Expand <clinit> when it exists for
|
||||
interfaces. Use IS_CLINIT.
|
||||
(resolve_expression_name): Use DECL_CONTEXT instead of
|
||||
current_class to build static field references.
|
||||
(java_complete_lhs): Use IS__CLINIT. Don't use SAVE_EXPR on
|
||||
ARRAY_REF when doing xreferencing.
|
||||
(check_final_assignment): Fixed typo in leading comment. Use
|
||||
IS_CLINIT.
|
||||
(patch_array_ref): Don't fully expand array references when
|
||||
xreferencing.
|
||||
(patch_return): Use IS_CLINIT.
|
||||
(patch_throw_statement): Likewise.
|
||||
|
||||
1999-04-22 Tom Tromey <tromey@cygnus.com>
|
||||
|
||||
* Make-lang.in (JAVA_SRCS): Added check-init.c.
|
||||
|
@ -1623,11 +1623,14 @@ layout_class_method (this_class, super_class, method_decl, dtable_count)
|
||||
obstack_1grow (&temporary_obstack, '\0');
|
||||
asm_name = obstack_finish (&temporary_obstack);
|
||||
DECL_ASSEMBLER_NAME (method_decl) = get_identifier (asm_name);
|
||||
/* We don't generate a RTL for the method if it's abstract, or if
|
||||
it's an interface method that isn't clinit. */
|
||||
if (! METHOD_ABSTRACT (method_decl)
|
||||
&& ! CLASS_INTERFACE (TYPE_NAME (this_class)))
|
||||
|| (CLASS_INTERFACE (TYPE_NAME (this_class))
|
||||
&& (IS_CLINIT (method_decl))))
|
||||
make_function_rtl (method_decl);
|
||||
obstack_free (&temporary_obstack, asm_name);
|
||||
|
||||
|
||||
if (method_name == init_identifier_node)
|
||||
{
|
||||
char *p = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (this_class)));
|
||||
|
@ -1526,7 +1526,8 @@ complete_start_java_method (fndecl)
|
||||
#endif
|
||||
|
||||
if (METHOD_STATIC (fndecl) && ! METHOD_PRIVATE (fndecl)
|
||||
&& ! flag_emit_class_files)
|
||||
&& ! flag_emit_class_files
|
||||
&& ! CLASS_INTERFACE (TYPE_NAME (current_class)))
|
||||
{
|
||||
tree clas = DECL_CONTEXT (fndecl);
|
||||
tree init = build (CALL_EXPR, void_type_node,
|
||||
|
@ -1167,10 +1167,20 @@ lookup_field (typep, name)
|
||||
}
|
||||
do
|
||||
{
|
||||
tree field;
|
||||
for (field = TYPE_FIELDS (*typep); field; field = TREE_CHAIN (field))
|
||||
tree field, basetype_vec;
|
||||
int n, i;
|
||||
|
||||
for (field = TYPE_FIELDS (*typep); field; field = TREE_CHAIN (field))
|
||||
if (DECL_NAME (field) == name)
|
||||
return field;
|
||||
|
||||
/* Process implemented interfaces. */
|
||||
basetype_vec = TYPE_BINFO_BASETYPES (*typep);
|
||||
n = TREE_VEC_LENGTH (basetype_vec);
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
if (DECL_NAME (field) == name)
|
||||
tree t = BINFO_TYPE (TREE_VEC_ELT (basetype_vec, i));
|
||||
if ((field = lookup_field (&t, name)))
|
||||
return field;
|
||||
}
|
||||
*typep = CLASSTYPE_SUPER (*typep);
|
||||
@ -1626,7 +1636,8 @@ expand_invoke (opcode, method_ref_index, nargs)
|
||||
if (opcode == OPCODE_invokestatic || opcode == OPCODE_invokespecial
|
||||
|| (opcode == OPCODE_invokevirtual
|
||||
&& (METHOD_PRIVATE (method)
|
||||
|| METHOD_FINAL (method) || CLASS_FINAL (TYPE_NAME (self_type)))))
|
||||
|| METHOD_FINAL (method)
|
||||
|| CLASS_FINAL (TYPE_NAME (self_type)))))
|
||||
func = build_known_method_ref (method, method_type, self_type,
|
||||
method_signature, arg_list);
|
||||
else
|
||||
@ -1663,11 +1674,14 @@ expand_java_field_op (is_static, is_putting, field_ref_index)
|
||||
int is_putting;
|
||||
int field_ref_index;
|
||||
{
|
||||
tree self_type = get_class_constant
|
||||
(current_jcf, COMPONENT_REF_CLASS_INDEX (¤t_jcf->cpool, field_ref_index));
|
||||
tree self_type =
|
||||
get_class_constant (current_jcf,
|
||||
COMPONENT_REF_CLASS_INDEX (¤t_jcf->cpool,
|
||||
field_ref_index));
|
||||
char *self_name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (self_type)));
|
||||
tree field_name = COMPONENT_REF_NAME (¤t_jcf->cpool, field_ref_index);
|
||||
tree field_signature = COMPONENT_REF_SIGNATURE (¤t_jcf->cpool, field_ref_index);
|
||||
tree field_signature = COMPONENT_REF_SIGNATURE (¤t_jcf->cpool,
|
||||
field_ref_index);
|
||||
tree field_type = get_type_from_signature (field_signature);
|
||||
tree new_value = is_putting ? pop_value (field_type) : NULL_TREE;
|
||||
tree field_ref;
|
||||
@ -1727,15 +1741,15 @@ expand_java_field_op (is_static, is_putting, field_ref_index)
|
||||
"assignment to final field `%s' not in field's class");
|
||||
else if (FIELD_STATIC (field_decl))
|
||||
{
|
||||
if (DECL_NAME (current_function_decl) != clinit_identifier_node)
|
||||
if (!IS_CLINIT (current_function_decl))
|
||||
error_with_decl (field_decl,
|
||||
"assignment to final static field `%s' not in class initializer");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (! DECL_CONSTRUCTOR_P (current_function_decl))
|
||||
error_with_decl (field_decl,
|
||||
"assignment to final field `%s' not in constructor");
|
||||
error_with_decl (field_decl, "assignment to final field `%s' "
|
||||
"not in constructor");
|
||||
}
|
||||
}
|
||||
expand_assignment (field_ref, new_value, 0, 0);
|
||||
|
950
gcc/java/parse.c
950
gcc/java/parse.c
File diff suppressed because it is too large
Load Diff
@ -177,9 +177,6 @@ extern tree stabilize_reference PROTO ((tree));
|
||||
&& (JNUMERIC_TYPE_P ((TYPE)) \
|
||||
|| TREE_CODE ((TYPE)) == BOOLEAN_TYPE))
|
||||
|
||||
#define JPRIMITIVE_TYPE_OR_VOID_P(TYPE) \
|
||||
(JPRIMITIVE_TYPE_P (TYPE) || ((TYPE) == void_type_node))
|
||||
|
||||
#define JBSC_TYPE_P(TYPE) ((TYPE) && (((TYPE) == byte_type_node) \
|
||||
|| ((TYPE) == short_type_node) \
|
||||
|| ((TYPE) == char_type_node)))
|
||||
@ -583,6 +580,10 @@ typedef struct _jdeplist {
|
||||
ctxp->import_list = node; \
|
||||
}
|
||||
|
||||
/* Safe check that DECL is <clinit> */
|
||||
#define IS_CLINIT(DECL) \
|
||||
(DECL != NULL_TREE && DECL_NAME (DECL) == clinit_identifier_node)
|
||||
|
||||
/* Macro to access the osb (opening square bracket) count */
|
||||
#define CURRENT_OSB(C) (C)->osb_number [(C)->osb_depth]
|
||||
|
||||
|
@ -632,6 +632,10 @@ type_declaration:
|
||||
$$ = $1;
|
||||
}
|
||||
| interface_declaration
|
||||
{
|
||||
maybe_generate_clinit ();
|
||||
$$ = $1;
|
||||
}
|
||||
| SC_TK
|
||||
{ $$ = NULL; }
|
||||
| error
|
||||
@ -3231,10 +3235,19 @@ static void
|
||||
maybe_generate_clinit ()
|
||||
{
|
||||
tree mdecl, c;
|
||||
int is_interface = CLASS_INTERFACE (ctxp->current_parsed_class);
|
||||
int has_non_primitive_fields = 0;
|
||||
|
||||
if (!ctxp->static_initialized || java_error_count)
|
||||
return;
|
||||
|
||||
if (is_interface)
|
||||
for (c = TYPE_FIELDS (TREE_TYPE (ctxp->current_parsed_class));
|
||||
c; c = TREE_CHAIN (c))
|
||||
has_non_primitive_fields |= !JPRIMITIVE_TYPE_P (TREE_TYPE (c));
|
||||
if (!has_non_primitive_fields && is_interface)
|
||||
return;
|
||||
|
||||
mdecl = create_artificial_method (TREE_TYPE (ctxp->current_parsed_class),
|
||||
ACC_STATIC, void_type_node,
|
||||
clinit_identifier_node, end_params_node);
|
||||
@ -4404,8 +4417,7 @@ static int
|
||||
reset_method_name (method)
|
||||
tree method;
|
||||
{
|
||||
if (DECL_NAME (method) != clinit_identifier_node
|
||||
&& DECL_NAME (method) != finit_identifier_node)
|
||||
if (!IS_CLINIT (method) && DECL_NAME (method) != finit_identifier_node)
|
||||
{
|
||||
/* NAME is just the plain name when Object is being defined */
|
||||
if (DECL_CONTEXT (method) != object_type_node)
|
||||
@ -5662,51 +5674,55 @@ java_complete_expand_methods ()
|
||||
|
||||
for (current = ctxp->class_list; current; current = TREE_CHAIN (current))
|
||||
{
|
||||
int is_interface;
|
||||
tree class_type = CLASS_TO_HANDLE_TYPE (TREE_TYPE (current));
|
||||
tree decl;
|
||||
|
||||
current_class = TREE_TYPE (current);
|
||||
is_interface = CLASS_INTERFACE (TYPE_NAME (current_class));
|
||||
|
||||
/* Initialize a new constant pool */
|
||||
init_outgoing_cpool ();
|
||||
|
||||
/* We want <clinit> (if any) to be processed first. */
|
||||
decl = tree_last (TYPE_METHODS (class_type));
|
||||
if (decl && DECL_NAME (decl) == clinit_identifier_node)
|
||||
if (IS_CLINIT (decl))
|
||||
{
|
||||
tree list = nreverse (TYPE_METHODS (class_type));
|
||||
list = TREE_CHAIN (list);
|
||||
TREE_CHAIN (decl) = NULL_TREE;
|
||||
TYPE_METHODS (class_type) = chainon (decl, nreverse (list));
|
||||
}
|
||||
|
||||
for (decl = TYPE_METHODS (class_type); decl; decl = TREE_CHAIN (decl))
|
||||
{
|
||||
/* Process only <clinit> method bodies in interfaces. */
|
||||
if (is_interface && decl != TYPE_METHODS (class_type))
|
||||
break;
|
||||
|
||||
/* Don't process function bodies in interfaces */
|
||||
if (!CLASS_INTERFACE (TYPE_NAME (current_class)))
|
||||
for (decl = TYPE_METHODS (class_type); decl; decl = TREE_CHAIN (decl))
|
||||
{
|
||||
current_function_decl = decl;
|
||||
/* Don't generate debug info on line zero when expanding a
|
||||
generated constructor. */
|
||||
if (DECL_CONSTRUCTOR_P (decl) && !DECL_FUNCTION_BODY (decl))
|
||||
{
|
||||
/* If we found errors, it's too dangerous to try to generate
|
||||
and expand a constructor */
|
||||
if (!java_error_count)
|
||||
{
|
||||
restore_line_number_status (1);
|
||||
java_complete_expand_method (decl);
|
||||
restore_line_number_status (0);
|
||||
current_function_decl = decl;
|
||||
/* Don't generate debug info on line zero when expanding a
|
||||
generated constructor. */
|
||||
if (DECL_CONSTRUCTOR_P (decl) && !DECL_FUNCTION_BODY (decl))
|
||||
{
|
||||
/* If we found errors, it's too dangerous to try to
|
||||
generate and expand a constructor */
|
||||
if (!java_error_count)
|
||||
{
|
||||
restore_line_number_status (1);
|
||||
java_complete_expand_method (decl);
|
||||
restore_line_number_status (0);
|
||||
}
|
||||
}
|
||||
else if (METHOD_ABSTRACT (decl) || METHOD_NATIVE (decl))
|
||||
continue;
|
||||
else
|
||||
java_complete_expand_method (decl);
|
||||
}
|
||||
}
|
||||
else if (METHOD_ABSTRACT (decl) || METHOD_NATIVE (decl))
|
||||
continue;
|
||||
else
|
||||
java_complete_expand_method (decl);
|
||||
}
|
||||
|
||||
/* Now verify constructor circularity (stop after the first one
|
||||
we find) */
|
||||
if (!CLASS_INTERFACE (TYPE_NAME (current_class)))
|
||||
if (!is_interface)
|
||||
for (decl = TYPE_METHODS (class_type); decl; decl = TREE_CHAIN (decl))
|
||||
if (DECL_CONSTRUCTOR_P (decl) &&
|
||||
verify_constructor_circularity (decl, decl))
|
||||
@ -5761,7 +5777,7 @@ java_complete_expand_method (mdecl)
|
||||
if (block_body != NULL_TREE)
|
||||
{
|
||||
/* Prevent the use of `this' inside <clinit> */
|
||||
if (DECL_NAME (current_function_decl) == clinit_identifier_node)
|
||||
if (IS_CLINIT (current_function_decl))
|
||||
ctxp->explicit_constructor_p = 1;
|
||||
|
||||
block_body = java_complete_tree (block_body);
|
||||
@ -6097,9 +6113,9 @@ resolve_expression_name (id, orig)
|
||||
|
||||
/* Otherwise build what it takes to access the field */
|
||||
decl = build_field_ref ((fs ? NULL_TREE : current_this),
|
||||
current_class, name);
|
||||
DECL_CONTEXT (decl), name);
|
||||
if (fs && !flag_emit_class_files && !flag_emit_xref)
|
||||
decl = build_class_init (current_class, decl);
|
||||
decl = build_class_init (DECL_CONTEXT (decl), decl);
|
||||
/* We may be asked to save the real field access node */
|
||||
if (orig)
|
||||
*orig = decl;
|
||||
@ -8074,7 +8090,7 @@ java_complete_lhs (node)
|
||||
assignment in <clinit>, we may want to carray further
|
||||
optimizations. (VAR_DECL means it's a static field. See
|
||||
add_field. */
|
||||
if (DECL_NAME (current_function_decl) == clinit_identifier_node
|
||||
if (IS_CLINIT (current_function_decl)
|
||||
&& MODIFY_EXPR_FROM_INITIALIZATION_P (node)
|
||||
&& TREE_CODE (TREE_OPERAND (node, 0)) == VAR_DECL)
|
||||
node = patch_initialized_static_field (node);
|
||||
@ -8159,14 +8175,14 @@ java_complete_lhs (node)
|
||||
TREE_OPERAND (node, 0) = java_complete_tree (wfl_op1);
|
||||
if (TREE_OPERAND (node, 0) == error_mark_node)
|
||||
return error_mark_node;
|
||||
if (!flag_emit_class_files)
|
||||
if (!flag_emit_class_files && !flag_emit_xref)
|
||||
TREE_OPERAND (node, 0) = save_expr (TREE_OPERAND (node, 0));
|
||||
/* The same applies to wfl_op2 */
|
||||
wfl_op2 = TREE_OPERAND (node, 1);
|
||||
TREE_OPERAND (node, 1) = java_complete_tree (wfl_op2);
|
||||
if (TREE_OPERAND (node, 1) == error_mark_node)
|
||||
return error_mark_node;
|
||||
if (!flag_emit_class_files)
|
||||
if (!flag_emit_class_files && !flag_emit_xref)
|
||||
TREE_OPERAND (node, 1) = save_expr (TREE_OPERAND (node, 1));
|
||||
return patch_array_ref (node);
|
||||
|
||||
@ -8507,14 +8523,15 @@ print_int_node (node)
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/* Return 1 if you an assignment of a FINAL is attempted */
|
||||
/* Return 1 if an assignment to a FINAL is attempted in a non suitable
|
||||
context. */
|
||||
|
||||
static int
|
||||
check_final_assignment (lvalue, wfl)
|
||||
tree lvalue, wfl;
|
||||
{
|
||||
if (JDECL_P (lvalue) && FIELD_FINAL (lvalue) &&
|
||||
DECL_NAME (current_function_decl) != clinit_identifier_node)
|
||||
if (JDECL_P (lvalue)
|
||||
&& FIELD_FINAL (lvalue) && !IS_CLINIT (current_function_decl))
|
||||
{
|
||||
parse_error_context
|
||||
(wfl, "Can't assign a value to the final variable `%s'",
|
||||
@ -10070,7 +10087,7 @@ patch_array_ref (node)
|
||||
|
||||
array_type = TYPE_ARRAY_ELEMENT (array_type);
|
||||
|
||||
if (flag_emit_class_files)
|
||||
if (flag_emit_class_files || flag_emit_xref)
|
||||
{
|
||||
TREE_OPERAND (node, 0) = array;
|
||||
TREE_OPERAND (node, 1) = index;
|
||||
@ -10396,7 +10413,7 @@ patch_return (node)
|
||||
error_found = 1;
|
||||
|
||||
/* It's invalid to use a return statement in a static block */
|
||||
if (DECL_NAME (current_function_decl) == clinit_identifier_node)
|
||||
if (IS_CLINIT (current_function_decl))
|
||||
error_found = 1;
|
||||
|
||||
/* It's invalid to have a no return value within a function that
|
||||
@ -10406,7 +10423,7 @@ patch_return (node)
|
||||
|
||||
if (error_found)
|
||||
{
|
||||
if (DECL_NAME (current_function_decl) == clinit_identifier_node)
|
||||
if (IS_CLINIT (current_function_decl))
|
||||
parse_error_context (wfl_operator,
|
||||
"`return' inside static initializer.");
|
||||
|
||||
@ -11134,7 +11151,7 @@ patch_throw_statement (node, wfl_op1)
|
||||
else if (!EXCEPTIONS_P (currently_caught_type_list)
|
||||
&& !tryblock_throws_ok)
|
||||
{
|
||||
if (DECL_NAME (current_function_decl) == clinit_identifier_node)
|
||||
if (IS_CLINIT (current_function_decl))
|
||||
parse_error_context (wfl_operator, "Checked exception `%s' can't "
|
||||
"be thrown in initializer",
|
||||
lang_printable_name (type, 0));
|
||||
|
Loading…
Reference in New Issue
Block a user