Commit 7525cc04 by Alexandre Petit-Bianco Committed by Per Bothner

parse.y (<type_declaration>): Do maybe_generate_clinit last.

�
	* parse.y (<type_declaration>):  Do maybe_generate_clinit last.
	(register_fields):  If a static fields has an initializer, just
	chain it on ctxp->static_initialized, and handle later.
	(java_complete_expand_methods):  Force <clinit> first.
	(resolve_expression_name, resolve_field_access):  Just get DECL_INITIAL
	- it's already been completed.
	(patch_initialized_static_field):  New function.
	(java_complete_field):  Call it.

From-SVN: r24274
parent fdec99c6
...@@ -237,6 +237,7 @@ static tree patch_new_array_init PROTO ((tree, tree)); ...@@ -237,6 +237,7 @@ static tree patch_new_array_init PROTO ((tree, tree));
static tree maybe_build_array_element_wfl PROTO ((tree)); static tree maybe_build_array_element_wfl PROTO ((tree));
static int array_constructor_check_entry PROTO ((tree, tree)); static int array_constructor_check_entry PROTO ((tree, tree));
static char *purify_type_name PROTO ((char *)); static char *purify_type_name PROTO ((char *));
static tree patch_initialized_static_field PROTO ((tree));
/* Number of error found so far. */ /* Number of error found so far. */
int java_error_count; int java_error_count;
...@@ -609,8 +610,8 @@ type_import_on_demand_declaration: ...@@ -609,8 +610,8 @@ type_import_on_demand_declaration:
type_declaration: type_declaration:
class_declaration class_declaration
{ {
maybe_generate_clinit ();
maybe_generate_finit (); maybe_generate_finit ();
maybe_generate_clinit ();
$$ = $1; $$ = $1;
} }
| interface_declaration | interface_declaration
...@@ -3133,34 +3134,24 @@ register_fields (flags, type, variable_list) ...@@ -3133,34 +3134,24 @@ register_fields (flags, type, variable_list)
/* The field is declared static */ /* The field is declared static */
if (flags & ACC_STATIC) if (flags & ACC_STATIC)
{ {
if (flags & ACC_FINAL) /* We include the field and its initialization part into
{ a list used to generate <clinit>. After <clinit> is
if (DECL_LANG_SPECIFIC (field_decl) == NULL) walked, fields initialization will be processed and
DECL_LANG_SPECIFIC (field_decl) = (struct lang_decl *) fields initialized with know constants will be taken
permalloc (sizeof (struct lang_decl_var)); out of <clinit> and have ther DECL_INITIAL set
DECL_LOCAL_STATIC_VALUE (field_decl) = appropriately. */
TREE_OPERAND (init, 1); TREE_CHAIN (init) = ctxp->static_initialized;
if (TREE_CONSTANT (TREE_OPERAND (init, 1))) ctxp->static_initialized = init;
DECL_INITIAL (field_decl) = TREE_OPERAND (init, 1);
}
/* Otherwise, the field should be initialized in <clinit>.
This field is remembered so we can generate <clinit> later */
else
{
INITIALIZED_P (field_decl) = 1;
TREE_CHAIN (init) = ctxp->static_initialized;
ctxp->static_initialized = init;
}
} }
/* A non-static field declared with an immediate initialization is /* A non-static field declared with an immediate initialization is
to be initialized in <init>, if any. This field is remembered to be initialized in <init>, if any. This field is remembered
to be processed at the time of the generation of <init>. */ to be processed at the time of the generation of <init>. */
else else
{ {
INITIALIZED_P (field_decl) = 1;
TREE_CHAIN (init) = ctxp->non_static_initialized; TREE_CHAIN (init) = ctxp->non_static_initialized;
ctxp->non_static_initialized = init; ctxp->non_static_initialized = init;
} }
INITIALIZED_P (field_decl) = 1;
} }
} }
lineno = saved_lineno; lineno = saved_lineno;
...@@ -5582,6 +5573,16 @@ java_complete_expand_methods () ...@@ -5582,6 +5573,16 @@ java_complete_expand_methods ()
/* 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. */
decl = tree_last (TYPE_METHODS (class_type));
if (decl && DECL_NAME (decl) == clinit_identifier_node)
{
tree list = nreverse (TYPE_METHODS (class_type));
list = TREE_CHAIN (list);
TREE_CHAIN (decl) = NULL_TREE;
TYPE_METHODS (class_type) = chainon (decl, nreverse (list));
}
/* Don't process function bodies in interfaces */ /* Don't process function bodies in interfaces */
if (!CLASS_INTERFACE (TYPE_NAME (current_class))) if (!CLASS_INTERFACE (TYPE_NAME (current_class)))
for (decl = TYPE_METHODS (class_type); decl; decl = TREE_CHAIN (decl)) for (decl = TYPE_METHODS (class_type); decl; decl = TREE_CHAIN (decl))
...@@ -5659,7 +5660,7 @@ java_complete_expand_method (mdecl) ...@@ -5659,7 +5660,7 @@ java_complete_expand_method (mdecl)
if ((block_body == NULL_TREE || CAN_COMPLETE_NORMALLY (block_body)) if ((block_body == NULL_TREE || CAN_COMPLETE_NORMALLY (block_body))
&& TREE_CODE (TREE_TYPE (TREE_TYPE (mdecl))) != VOID_TYPE) && TREE_CODE (TREE_TYPE (TREE_TYPE (mdecl))) != VOID_TYPE)
missing_return_error (current_function_decl); missing_return_error (current_function_decl);
/* Don't go any further if we've found error(s) during the /* Don't go any further if we've found error(s) during the
expansion */ expansion */
if (!java_error_count) if (!java_error_count)
...@@ -5975,8 +5976,8 @@ resolve_expression_name (id, orig) ...@@ -5975,8 +5976,8 @@ resolve_expression_name (id, orig)
return error_mark_node; return error_mark_node;
} }
/* The field is final. We may use its value instead */ /* The field is final. We may use its value instead */
if (fs && FIELD_FINAL (decl)) if (fs && FIELD_FINAL (decl) && DECL_INITIAL (decl))
value = java_complete_tree (DECL_LOCAL_STATIC_VALUE (decl)); value = DECL_INITIAL (decl);
/* 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),
...@@ -6049,9 +6050,9 @@ resolve_field_access (qual_wfl, field_decl, field_type) ...@@ -6049,9 +6050,9 @@ resolve_field_access (qual_wfl, field_decl, field_type)
if (FIELD_FINAL (decl) if (FIELD_FINAL (decl)
&& JPRIMITIVE_TYPE_P (TREE_TYPE (decl)) && JPRIMITIVE_TYPE_P (TREE_TYPE (decl))
&& DECL_LANG_SPECIFIC (decl) && DECL_LANG_SPECIFIC (decl)
&& DECL_LOCAL_STATIC_VALUE (decl)) && DECL_INITIAL (decl))
{ {
field_ref = java_complete_tree (DECL_LOCAL_STATIC_VALUE (decl)); field_ref = DECL_INITIAL (decl);
static_final_found = 1; static_final_found = 1;
} }
else else
...@@ -7765,6 +7766,15 @@ java_complete_tree (node) ...@@ -7765,6 +7766,15 @@ java_complete_tree (node)
TREE_OPERAND (node, 1) = nn; TREE_OPERAND (node, 1) = nn;
node = patch_assignment (node, wfl_op1, wfl_op2); node = patch_assignment (node, wfl_op1, wfl_op2);
CAN_COMPLETE_NORMALLY (node) = 1; CAN_COMPLETE_NORMALLY (node) = 1;
/* Before returning the node, in the context of a static field
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
&& TREE_CODE (TREE_OPERAND (node, 0)) == VAR_DECL)
node = patch_initialized_static_field (node);
return node; return node;
case MULT_EXPR: case MULT_EXPR:
...@@ -8161,7 +8171,8 @@ static int ...@@ -8161,7 +8171,8 @@ static int
check_final_assignment (lvalue, wfl) check_final_assignment (lvalue, wfl)
tree lvalue, wfl; tree lvalue, wfl;
{ {
if (DECL_P (lvalue) && FIELD_FINAL (lvalue)) if (DECL_P (lvalue) && FIELD_FINAL (lvalue) &&
DECL_NAME (current_function_decl) != clinit_identifier_node)
{ {
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'",
...@@ -8323,6 +8334,30 @@ patch_assignment (node, wfl_op1, wfl_op2) ...@@ -8323,6 +8334,30 @@ patch_assignment (node, wfl_op1, wfl_op2)
return node; return node;
} }
/* Optimize static (final) field initialized upon declaration.
- If the field is static final and is assigned to a primitive
constant type, then set its DECL_INITIAL to the value.
- More to come. */
static tree
patch_initialized_static_field (node)
tree node;
{
tree field = TREE_OPERAND (node, 0);
tree value = TREE_OPERAND (node, 1);
if (FIELD_FINAL (field) && TREE_CONSTANT (value)
&& JPRIMITIVE_TYPE_P (TREE_TYPE (value)))
{
if (DECL_LANG_SPECIFIC (field) == NULL)
DECL_LANG_SPECIFIC (field) = (struct lang_decl *)
permalloc (sizeof (struct lang_decl_var));
DECL_INITIAL (field) = value;
return empty_stmt_node;
}
return node;
}
/* Check that type SOURCE can be cast into type DEST. If the cast /* Check that type SOURCE can be cast into type DEST. If the cast
can't occur at all, return 0 otherwise 1. This function is used to can't occur at all, return 0 otherwise 1. This function is used to
produce accurate error messages on the reasons why an assignment produce accurate error messages on the reasons why an assignment
...@@ -9392,7 +9427,7 @@ patch_unaryop (node, wfl_op) ...@@ -9392,7 +9427,7 @@ patch_unaryop (node, wfl_op)
/* There are cases where node has been replaced by something else /* There are cases where node has been replaced by something else
and we don't end up returning here: UNARY_PLUS_EXPR, and we don't end up returning here: UNARY_PLUS_EXPR,
CONVERT_EXPR, {POST,PRE}{INCR,DECR}EMENT_EXPR. */ CONVERT_EXPR, {POST,PRE}{INCR,DECR}EMENT_EXPR. */
TREE_OPERAND (node, 0) = op; TREE_OPERAND (node, 0) = fold (op);
TREE_TYPE (node) = prom_type; TREE_TYPE (node) = prom_type;
return fold (node); return fold (node);
} }
...@@ -10547,7 +10582,7 @@ patch_try_statement (node) ...@@ -10547,7 +10582,7 @@ patch_try_statement (node)
CATCH_EXPR (catch node) CATCH_EXPR (catch node)
BLOCK (with the decl of the parameter) BLOCK (with the decl of the parameter)
COMPOUND_EXPR COMPOUND_EXPR
MODIFIY_EXPR (assignemnt of the catch parameter) MODIFY_EXPR (assignment of the catch parameter)
BLOCK (catch clause block) BLOCK (catch clause block)
LABEL_DECL (where to return after finally (if any)) LABEL_DECL (where to return after finally (if any))
......
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