Commit 7f1d4866 by Alexandre Petit-Bianco Committed by Alexandre Petit-Bianco

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
parent ccd63d90
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> 1999-04-22 Tom Tromey <tromey@cygnus.com>
* Make-lang.in (JAVA_SRCS): Added check-init.c. * Make-lang.in (JAVA_SRCS): Added check-init.c.
......
...@@ -1623,11 +1623,14 @@ layout_class_method (this_class, super_class, method_decl, dtable_count) ...@@ -1623,11 +1623,14 @@ layout_class_method (this_class, super_class, method_decl, dtable_count)
obstack_1grow (&temporary_obstack, '\0'); obstack_1grow (&temporary_obstack, '\0');
asm_name = obstack_finish (&temporary_obstack); asm_name = obstack_finish (&temporary_obstack);
DECL_ASSEMBLER_NAME (method_decl) = get_identifier (asm_name); 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) 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); make_function_rtl (method_decl);
obstack_free (&temporary_obstack, asm_name); obstack_free (&temporary_obstack, asm_name);
if (method_name == init_identifier_node) if (method_name == init_identifier_node)
{ {
char *p = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (this_class))); char *p = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (this_class)));
......
...@@ -1526,7 +1526,8 @@ complete_start_java_method (fndecl) ...@@ -1526,7 +1526,8 @@ complete_start_java_method (fndecl)
#endif #endif
if (METHOD_STATIC (fndecl) && ! METHOD_PRIVATE (fndecl) 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 clas = DECL_CONTEXT (fndecl);
tree init = build (CALL_EXPR, void_type_node, tree init = build (CALL_EXPR, void_type_node,
......
...@@ -1167,10 +1167,20 @@ lookup_field (typep, name) ...@@ -1167,10 +1167,20 @@ lookup_field (typep, name)
} }
do do
{ {
tree field; tree field, basetype_vec;
for (field = TYPE_FIELDS (*typep); field; field = TREE_CHAIN (field)) 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; return field;
} }
*typep = CLASSTYPE_SUPER (*typep); *typep = CLASSTYPE_SUPER (*typep);
...@@ -1626,7 +1636,8 @@ expand_invoke (opcode, method_ref_index, nargs) ...@@ -1626,7 +1636,8 @@ expand_invoke (opcode, method_ref_index, nargs)
if (opcode == OPCODE_invokestatic || opcode == OPCODE_invokespecial if (opcode == OPCODE_invokestatic || opcode == OPCODE_invokespecial
|| (opcode == OPCODE_invokevirtual || (opcode == OPCODE_invokevirtual
&& (METHOD_PRIVATE (method) && (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, func = build_known_method_ref (method, method_type, self_type,
method_signature, arg_list); method_signature, arg_list);
else else
...@@ -1663,11 +1674,14 @@ expand_java_field_op (is_static, is_putting, field_ref_index) ...@@ -1663,11 +1674,14 @@ expand_java_field_op (is_static, is_putting, field_ref_index)
int is_putting; int is_putting;
int field_ref_index; int field_ref_index;
{ {
tree self_type = get_class_constant tree self_type =
(current_jcf, COMPONENT_REF_CLASS_INDEX (&current_jcf->cpool, field_ref_index)); get_class_constant (current_jcf,
COMPONENT_REF_CLASS_INDEX (&current_jcf->cpool,
field_ref_index));
char *self_name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (self_type))); char *self_name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (self_type)));
tree field_name = COMPONENT_REF_NAME (&current_jcf->cpool, field_ref_index); tree field_name = COMPONENT_REF_NAME (&current_jcf->cpool, field_ref_index);
tree field_signature = COMPONENT_REF_SIGNATURE (&current_jcf->cpool, field_ref_index); tree field_signature = COMPONENT_REF_SIGNATURE (&current_jcf->cpool,
field_ref_index);
tree field_type = get_type_from_signature (field_signature); tree field_type = get_type_from_signature (field_signature);
tree new_value = is_putting ? pop_value (field_type) : NULL_TREE; tree new_value = is_putting ? pop_value (field_type) : NULL_TREE;
tree field_ref; tree field_ref;
...@@ -1727,15 +1741,15 @@ expand_java_field_op (is_static, is_putting, field_ref_index) ...@@ -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"); "assignment to final field `%s' not in field's class");
else if (FIELD_STATIC (field_decl)) 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, error_with_decl (field_decl,
"assignment to final static field `%s' not in class initializer"); "assignment to final static field `%s' not in class initializer");
} }
else else
{ {
if (! DECL_CONSTRUCTOR_P (current_function_decl)) if (! DECL_CONSTRUCTOR_P (current_function_decl))
error_with_decl (field_decl, error_with_decl (field_decl, "assignment to final field `%s' "
"assignment to final field `%s' not in constructor"); "not in constructor");
} }
} }
expand_assignment (field_ref, new_value, 0, 0); expand_assignment (field_ref, new_value, 0, 0);
......
...@@ -177,9 +177,6 @@ extern tree stabilize_reference PROTO ((tree)); ...@@ -177,9 +177,6 @@ extern tree stabilize_reference PROTO ((tree));
&& (JNUMERIC_TYPE_P ((TYPE)) \ && (JNUMERIC_TYPE_P ((TYPE)) \
|| TREE_CODE ((TYPE)) == BOOLEAN_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) \ #define JBSC_TYPE_P(TYPE) ((TYPE) && (((TYPE) == byte_type_node) \
|| ((TYPE) == short_type_node) \ || ((TYPE) == short_type_node) \
|| ((TYPE) == char_type_node))) || ((TYPE) == char_type_node)))
...@@ -583,6 +580,10 @@ typedef struct _jdeplist { ...@@ -583,6 +580,10 @@ typedef struct _jdeplist {
ctxp->import_list = node; \ 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 */ /* Macro to access the osb (opening square bracket) count */
#define CURRENT_OSB(C) (C)->osb_number [(C)->osb_depth] #define CURRENT_OSB(C) (C)->osb_number [(C)->osb_depth]
......
...@@ -632,6 +632,10 @@ type_declaration: ...@@ -632,6 +632,10 @@ type_declaration:
$$ = $1; $$ = $1;
} }
| interface_declaration | interface_declaration
{
maybe_generate_clinit ();
$$ = $1;
}
| SC_TK | SC_TK
{ $$ = NULL; } { $$ = NULL; }
| error | error
...@@ -3231,10 +3235,19 @@ static void ...@@ -3231,10 +3235,19 @@ static void
maybe_generate_clinit () maybe_generate_clinit ()
{ {
tree mdecl, c; 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) if (!ctxp->static_initialized || java_error_count)
return; 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), mdecl = create_artificial_method (TREE_TYPE (ctxp->current_parsed_class),
ACC_STATIC, void_type_node, ACC_STATIC, void_type_node,
clinit_identifier_node, end_params_node); clinit_identifier_node, end_params_node);
...@@ -4404,8 +4417,7 @@ static int ...@@ -4404,8 +4417,7 @@ static int
reset_method_name (method) reset_method_name (method)
tree method; tree method;
{ {
if (DECL_NAME (method) != clinit_identifier_node if (!IS_CLINIT (method) && DECL_NAME (method) != finit_identifier_node)
&& DECL_NAME (method) != finit_identifier_node)
{ {
/* NAME is just the plain name when Object is being defined */ /* NAME is just the plain name when Object is being defined */
if (DECL_CONTEXT (method) != object_type_node) if (DECL_CONTEXT (method) != object_type_node)
...@@ -5662,51 +5674,55 @@ java_complete_expand_methods () ...@@ -5662,51 +5674,55 @@ java_complete_expand_methods ()
for (current = ctxp->class_list; current; current = TREE_CHAIN (current)) for (current = ctxp->class_list; current; current = TREE_CHAIN (current))
{ {
int is_interface;
tree class_type = CLASS_TO_HANDLE_TYPE (TREE_TYPE (current)); tree class_type = CLASS_TO_HANDLE_TYPE (TREE_TYPE (current));
tree decl; tree decl;
current_class = TREE_TYPE (current); current_class = TREE_TYPE (current);
is_interface = CLASS_INTERFACE (TYPE_NAME (current_class));
/* Initialize a new constant pool */ /* Initialize a new constant pool */
init_outgoing_cpool (); init_outgoing_cpool ();
/* We want <clinit> (if any) to be processed first. */ /* We want <clinit> (if any) to be processed first. */
decl = tree_last (TYPE_METHODS (class_type)); 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)); tree list = nreverse (TYPE_METHODS (class_type));
list = TREE_CHAIN (list); list = TREE_CHAIN (list);
TREE_CHAIN (decl) = NULL_TREE; TREE_CHAIN (decl) = NULL_TREE;
TYPE_METHODS (class_type) = chainon (decl, nreverse (list)); 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 */ current_function_decl = decl;
if (!CLASS_INTERFACE (TYPE_NAME (current_class))) /* Don't generate debug info on line zero when expanding a
for (decl = TYPE_METHODS (class_type); decl; decl = TREE_CHAIN (decl)) generated constructor. */
{ if (DECL_CONSTRUCTOR_P (decl) && !DECL_FUNCTION_BODY (decl))
current_function_decl = decl; {
/* Don't generate debug info on line zero when expanding a /* If we found errors, it's too dangerous to try to
generated constructor. */ generate and expand a constructor */
if (DECL_CONSTRUCTOR_P (decl) && !DECL_FUNCTION_BODY (decl)) if (!java_error_count)
{ {
/* If we found errors, it's too dangerous to try to generate restore_line_number_status (1);
and expand a constructor */ java_complete_expand_method (decl);
if (!java_error_count) restore_line_number_status (0);
{
restore_line_number_status (1);
java_complete_expand_method (decl);
restore_line_number_status (0);
} }
} }
else if (METHOD_ABSTRACT (decl) || METHOD_NATIVE (decl)) else if (METHOD_ABSTRACT (decl) || METHOD_NATIVE (decl))
continue; continue;
else else
java_complete_expand_method (decl); java_complete_expand_method (decl);
} }
/* Now verify constructor circularity (stop after the first one /* Now verify constructor circularity (stop after the first one
we find) */ we find) */
if (!CLASS_INTERFACE (TYPE_NAME (current_class))) if (!is_interface)
for (decl = TYPE_METHODS (class_type); decl; decl = TREE_CHAIN (decl)) for (decl = TYPE_METHODS (class_type); decl; decl = TREE_CHAIN (decl))
if (DECL_CONSTRUCTOR_P (decl) && if (DECL_CONSTRUCTOR_P (decl) &&
verify_constructor_circularity (decl, decl)) verify_constructor_circularity (decl, decl))
...@@ -5761,7 +5777,7 @@ java_complete_expand_method (mdecl) ...@@ -5761,7 +5777,7 @@ java_complete_expand_method (mdecl)
if (block_body != NULL_TREE) if (block_body != NULL_TREE)
{ {
/* Prevent the use of `this' inside <clinit> */ /* 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; ctxp->explicit_constructor_p = 1;
block_body = java_complete_tree (block_body); block_body = java_complete_tree (block_body);
...@@ -6097,9 +6113,9 @@ resolve_expression_name (id, orig) ...@@ -6097,9 +6113,9 @@ resolve_expression_name (id, orig)
/* Otherwise build what it takes to access the field */ /* Otherwise build what it takes to access the field */
decl = build_field_ref ((fs ? NULL_TREE : current_this), 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) 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 */ /* We may be asked to save the real field access node */
if (orig) if (orig)
*orig = decl; *orig = decl;
...@@ -8074,7 +8090,7 @@ java_complete_lhs (node) ...@@ -8074,7 +8090,7 @@ java_complete_lhs (node)
assignment in <clinit>, we may want to carray further assignment in <clinit>, we may want to carray further
optimizations. (VAR_DECL means it's a static field. See optimizations. (VAR_DECL means it's a static field. See
add_field. */ add_field. */
if (DECL_NAME (current_function_decl) == clinit_identifier_node if (IS_CLINIT (current_function_decl)
&& MODIFY_EXPR_FROM_INITIALIZATION_P (node) && MODIFY_EXPR_FROM_INITIALIZATION_P (node)
&& TREE_CODE (TREE_OPERAND (node, 0)) == VAR_DECL) && TREE_CODE (TREE_OPERAND (node, 0)) == VAR_DECL)
node = patch_initialized_static_field (node); node = patch_initialized_static_field (node);
...@@ -8159,14 +8175,14 @@ java_complete_lhs (node) ...@@ -8159,14 +8175,14 @@ java_complete_lhs (node)
TREE_OPERAND (node, 0) = java_complete_tree (wfl_op1); TREE_OPERAND (node, 0) = java_complete_tree (wfl_op1);
if (TREE_OPERAND (node, 0) == error_mark_node) if (TREE_OPERAND (node, 0) == error_mark_node)
return 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)); TREE_OPERAND (node, 0) = save_expr (TREE_OPERAND (node, 0));
/* The same applies to wfl_op2 */ /* The same applies to wfl_op2 */
wfl_op2 = TREE_OPERAND (node, 1); wfl_op2 = TREE_OPERAND (node, 1);
TREE_OPERAND (node, 1) = java_complete_tree (wfl_op2); TREE_OPERAND (node, 1) = java_complete_tree (wfl_op2);
if (TREE_OPERAND (node, 1) == error_mark_node) if (TREE_OPERAND (node, 1) == error_mark_node)
return 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)); TREE_OPERAND (node, 1) = save_expr (TREE_OPERAND (node, 1));
return patch_array_ref (node); return patch_array_ref (node);
...@@ -8507,14 +8523,15 @@ print_int_node (node) ...@@ -8507,14 +8523,15 @@ print_int_node (node)
return buffer; 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 static int
check_final_assignment (lvalue, wfl) check_final_assignment (lvalue, wfl)
tree lvalue, wfl; tree lvalue, wfl;
{ {
if (JDECL_P (lvalue) && FIELD_FINAL (lvalue) && if (JDECL_P (lvalue)
DECL_NAME (current_function_decl) != clinit_identifier_node) && FIELD_FINAL (lvalue) && !IS_CLINIT (current_function_decl))
{ {
parse_error_context parse_error_context
(wfl, "Can't assign a value to the final variable `%s'", (wfl, "Can't assign a value to the final variable `%s'",
...@@ -10070,7 +10087,7 @@ patch_array_ref (node) ...@@ -10070,7 +10087,7 @@ patch_array_ref (node)
array_type = TYPE_ARRAY_ELEMENT (array_type); 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, 0) = array;
TREE_OPERAND (node, 1) = index; TREE_OPERAND (node, 1) = index;
...@@ -10396,7 +10413,7 @@ patch_return (node) ...@@ -10396,7 +10413,7 @@ patch_return (node)
error_found = 1; error_found = 1;
/* It's invalid to use a return statement in a static block */ /* 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; error_found = 1;
/* It's invalid to have a no return value within a function that /* It's invalid to have a no return value within a function that
...@@ -10406,7 +10423,7 @@ patch_return (node) ...@@ -10406,7 +10423,7 @@ patch_return (node)
if (error_found) if (error_found)
{ {
if (DECL_NAME (current_function_decl) == clinit_identifier_node) if (IS_CLINIT (current_function_decl))
parse_error_context (wfl_operator, parse_error_context (wfl_operator,
"`return' inside static initializer."); "`return' inside static initializer.");
...@@ -11134,7 +11151,7 @@ patch_throw_statement (node, wfl_op1) ...@@ -11134,7 +11151,7 @@ patch_throw_statement (node, wfl_op1)
else if (!EXCEPTIONS_P (currently_caught_type_list) else if (!EXCEPTIONS_P (currently_caught_type_list)
&& !tryblock_throws_ok) && !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 " parse_error_context (wfl_operator, "Checked exception `%s' can't "
"be thrown in initializer", "be thrown in initializer",
lang_printable_name (type, 0)); lang_printable_name (type, 0));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment