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:
Alexandre Petit-Bianco 1999-04-26 19:09:37 +00:00 committed by Alexandre Petit-Bianco
parent ccd63d90d1
commit 7f1d48663e
7 changed files with 605 additions and 520 deletions

View File

@ -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.

View File

@ -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)));

View File

@ -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,

View File

@ -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 (&current_jcf->cpool, field_ref_index));
tree self_type =
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)));
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 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);

File diff suppressed because it is too large Load Diff

View File

@ -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]

View File

@ -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));