class.c (make_field_value): DECL_INITIAL may be a string literal...

d
	* class.c (make_field_value):  DECL_INITIAL may be a string literal;
	temporarily zero it while calling rest_of_decl_compilation.
	* java-tree.h (string_ptr_type_node):  Add declaration.
	* decl.c:  Define and initialize string_ptr_type_node.
	* parse.y (patch_string_cst):  Use string_ptr_type_node.
	* parse.h (LOOP_HAS_LABEL_P, LOOP_HAS_LABEL_SKIP_P):  Removed.
	* parse.y (for_statement):  Now unconditionally exit_block.
	(finish_labeled_statement):  No longer exit_block if for-loop.
	(patch_loop_statement):  Check harder if the loop is already labeled.
	* parse.y (patch_initialized_static_field):  Removed function.
	(maybe_generate_clinit):  Removed special handling for interfaces.
	(java_complete_expand_methods):  Do a preliminary java_complete_tree
	on <clinit> to determine if it can be removed.
	(java_complete_expand_method):  Remove special handling for <clinit>.
	(java_complete_lhs):  For BLOCK and EXPR_WITH_FILE_LOCATION
	optimize if we get back empty_stmt_node.
	For MODIFY_EXPR, re-do checking of static initializers.
	(fold_constant_for_init):  Don't return immediate if VAR_DECL.
	For VAR_DECL, pass correct context.

From-SVN: r26790
This commit is contained in:
Per Bothner 1999-05-05 14:10:07 -07:00
parent c14cff58e5
commit cd9643f75b
6 changed files with 612 additions and 614 deletions

View File

@ -1025,9 +1025,16 @@ make_class_data (type)
tree init = make_field_value (field);
if (FIELD_STATIC (field))
{
tree initial = DECL_INITIAL (field);
static_field_count++;
static_fields = tree_cons (NULL_TREE, init, static_fields);
/* If the initial value is a string constant,
prevent output_constant from trying to assemble the value. */
if (initial != NULL_TREE
&& TREE_TYPE (initial) == string_ptr_type_node)
DECL_INITIAL (field) = NULL_TREE;
rest_of_decl_compilation (field, (char*) 0, 1, 1);
DECL_INITIAL (field) = initial;
}
else
{

View File

@ -254,6 +254,7 @@ tree object_type_node;
tree unqualified_object_id_node;
tree object_ptr_type_node;
tree string_type_node;
tree string_ptr_type_node;
tree throwable_type_node;
tree runtime_exception_type_node;
tree error_exception_type_node;
@ -549,6 +550,7 @@ init_decl_processing ()
object_type_node = lookup_class (get_identifier ("java.lang.Object"));
object_ptr_type_node = promote_type (object_type_node);
string_type_node = lookup_class (get_identifier ("java.lang.String"));
string_ptr_type_node = promote_type (string_type_node);
class_type_node = lookup_class (get_identifier ("java.lang.Class"));
throwable_type_node = lookup_class (get_identifier ("java.lang.Throwable"));
runtime_exception_type_node =

View File

@ -198,6 +198,7 @@ extern tree object_type_node;
extern tree unqualified_object_id_node;
extern tree object_ptr_type_node;
extern tree string_type_node;
extern tree string_ptr_type_node;
extern tree throwable_type_node;
extern tree runtime_exception_type_node;
extern tree error_exception_type_node;

File diff suppressed because it is too large Load Diff

View File

@ -258,18 +258,6 @@ extern tree stabilize_reference PROTO ((tree));
#define LOOP_EXPR_BODY_BODY_EXPR(NODE, R) \
LABELED_BLOCK_BODY (LOOP_EXPR_BODY_LABELED_BODY(NODE, R))
/* Does a loop have a label ? */
#define LOOP_HAS_LABEL_P(LOOP) \
(ctxp->current_labeled_block \
&& LABELED_BLOCK_BODY (ctxp->current_labeled_block) == (LOOP))
/* Same operation than the one performed above, but considering the
previous labeled block */
#define LOOP_HAS_LABEL_SKIP_P(LOOP) \
(ctxp->current_labeled_block \
&& TREE_CHAIN (ctxp->current_labeled_block) \
&& LABELED_BLOCK_BODY (TREE_CHAIN (ctxp->current_labeled_block)) == (LOOP))
#define PUSH_LABELED_BLOCK(B) \
{ \
TREE_CHAIN (B) = ctxp->current_labeled_block; \

View File

@ -237,7 +237,6 @@ static tree patch_new_array_init PROTO ((tree, tree));
static tree maybe_build_array_element_wfl PROTO ((tree));
static int array_constructor_check_entry PROTO ((tree, tree));
static char *purify_type_name PROTO ((char *));
static tree patch_initialized_static_field PROTO ((tree));
static tree fold_constant_for_init PROTO ((tree, tree));
static tree strip_out_static_field_access_decl PROTO ((tree));
static jdeplist *reverse_jdep_list PROTO ((struct parser_ctxt *));
@ -1220,13 +1219,7 @@ statement:
| if_then_else_statement
| while_statement
| for_statement
{
/* If the for loop is unlabeled, we must return the
block it was defined it. It our last chance to
get a hold on it. */
if (!LOOP_HAS_LABEL_P ($$))
$$ = exit_block ();
}
{ $$ = exit_block (); }
;
statement_nsi:
@ -3264,19 +3257,11 @@ 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);
@ -5728,18 +5713,41 @@ java_complete_expand_methods ()
decl = tree_last (TYPE_METHODS (class_type));
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));
tree fbody = DECL_FUNCTION_BODY (decl);
tree list;
if (fbody != NULL_TREE)
{
/* First check if we can ignore empty <clinit> */
tree block_body = BLOCK_EXPR_BODY (fbody);
current_this = NULL_TREE;
current_function_decl = decl;
if (block_body != NULL_TREE)
{
/* Prevent the use of `this' inside <clinit> */
ctxp->explicit_constructor_p = 1;
block_body = java_complete_tree (block_body);
ctxp->explicit_constructor_p = 0;
BLOCK_EXPR_BODY (fbody) = block_body;
if (block_body != NULL_TREE
&& TREE_CODE (block_body) == BLOCK
&& BLOCK_EXPR_BODY (block_body) == empty_stmt_node)
decl = NULL_TREE;
}
}
list = nreverse (TREE_CHAIN (nreverse (TYPE_METHODS (class_type))));
if (decl != NULL_TREE)
{
TREE_CHAIN (decl) = list;
TYPE_METHODS (class_type) = decl;
}
else
TYPE_METHODS (class_type) = 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;
current_function_decl = decl;
/* Don't generate debug info on line zero when expanding a
generated constructor. */
@ -5816,10 +5824,6 @@ java_complete_expand_method (mdecl)
if (block_body != NULL_TREE)
{
/* Prevent the use of `this' inside <clinit> */
if (IS_CLINIT (current_function_decl))
ctxp->explicit_constructor_p = 1;
block_body = java_complete_tree (block_body);
check_for_initialization (block_body);
ctxp->explicit_constructor_p = 0;
@ -7755,6 +7759,13 @@ java_complete_lhs (node)
tree cur = java_complete_tree (TREE_OPERAND (*ptr, 0));
tree *next = &TREE_OPERAND (*ptr, 1);
TREE_OPERAND (*ptr, 0) = cur;
if (cur == empty_stmt_node)
{
/* Optimization; makes it easier to detect empty bodies.
Most useful for <clinit> with all-constant initializer. */
*ptr = *next;
continue;
}
if (TREE_CODE (cur) == ERROR_MARK)
error_seen++;
else if (! CAN_COMPLETE_NORMALLY (cur))
@ -8022,6 +8033,11 @@ java_complete_lhs (node)
EXPR_WFL_NODE (node) = body;
TREE_SIDE_EFFECTS (node) = TREE_SIDE_EFFECTS (body);
CAN_COMPLETE_NORMALLY (node) = CAN_COMPLETE_NORMALLY (body);
if (body == empty_stmt_node)
{
/* Optimization; makes it easier to detect empty bodies. */
return body;
}
if (body == error_mark_node)
{
/* Its important for the evaluation of assignment that
@ -8091,8 +8107,22 @@ java_complete_lhs (node)
case MODIFY_EXPR:
/* Save potential wfls */
wfl_op1 = TREE_OPERAND (node, 0);
TREE_OPERAND (node, 0) = nn = java_complete_lhs (wfl_op1);
if (MODIFY_EXPR_FROM_INITIALIZATION_P (node)
&& TREE_CODE (nn) == VAR_DECL && TREE_STATIC (nn)
&& DECL_INITIAL (nn) != NULL_TREE)
{
tree value = fold_constant_for_init (nn, nn);
if (value != NULL_TREE)
{
tree type = TREE_TYPE (value);
if (JPRIMITIVE_TYPE_P (type) || type == string_ptr_type_node)
return empty_stmt_node;
}
DECL_INITIAL (nn) = NULL_TREE;
}
wfl_op2 = TREE_OPERAND (node, 1);
TREE_OPERAND (node, 0) = java_complete_lhs (wfl_op1);
if (TREE_OPERAND (node, 0) == error_mark_node)
return error_mark_node;
@ -8138,17 +8168,6 @@ java_complete_lhs (node)
TREE_OPERAND (node, 1) = nn;
node = patch_assignment (node, wfl_op1, wfl_op2);
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 (IS_CLINIT (current_function_decl)
&& MODIFY_EXPR_FROM_INITIALIZATION_P (node)
&& TREE_CODE (TREE_OPERAND (node, 0)) == VAR_DECL
&& !flag_emit_xref)
node = patch_initialized_static_field (node);
return node;
case MULT_EXPR:
@ -8800,35 +8819,6 @@ patch_assignment (node, wfl_op1, wfl_op2)
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 (DECL_INITIAL (field) != NULL_TREE)
{
tree type = TREE_TYPE (value);
if (FIELD_FINAL (field) && TREE_CONSTANT (value)
&& (JPRIMITIVE_TYPE_P (type)
|| (flag_emit_class_files
&& TREE_CODE (type) == POINTER_TYPE
&& TREE_TYPE (type) == string_type_node)))
{
DECL_INITIAL (field) = value;
return empty_stmt_node;
}
DECL_INITIAL (field) = NULL_TREE;
}
return node;
}
/* 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
produce accurate error messages on the reasons why an assignment
@ -9733,7 +9723,7 @@ patch_string_cst (node)
location = alloc_name_constant (CONSTANT_String, node);
node = build_ref_from_constant_pool (location);
}
TREE_TYPE (node) = promote_type (string_type_node);
TREE_TYPE (node) = string_ptr_type_node;
TREE_CONSTANT (node) = 1;
return node;
}
@ -10632,15 +10622,6 @@ finish_labeled_statement (lbe, statement)
{
/* In anyways, tie the loop to its statement */
LABELED_BLOCK_BODY (lbe) = statement;
/* Ok, if statement is a for loop, we have to attach the labeled
statement to the block the for loop belongs to and return the
block instead */
if (TREE_CODE (statement) == LOOP_EXPR && IS_FOR_LOOP_P (statement))
{
java_method_add_stmt (current_function_decl, lbe);
lbe = exit_block ();
}
pop_labeled_block ();
POP_LABELED_BLOCK ();
return lbe;
@ -10752,14 +10733,33 @@ static tree
patch_loop_statement (loop)
tree loop;
{
if (! LOOP_HAS_LABEL_P (loop))
{
tree loop_label = build_labeled_block (0, NULL_TREE);
LABELED_BLOCK_BODY (loop_label) = loop;
PUSH_LABELED_BLOCK (loop_label);
loop = loop_label;
}
tree loop_label;
tree block = ctxp->current_labeled_block;
TREE_TYPE (loop) = void_type_node;
if (block != NULL_TREE)
{
tree block_body = LABELED_BLOCK_BODY (block);
if (IS_FOR_LOOP_P (loop))
{
if (TREE_CODE (block_body) == BLOCK)
{
block_body = BLOCK_EXPR_BODY (block_body);
if (block_body == loop
|| (TREE_CODE (block_body) == COMPOUND_EXPR
&& TREE_OPERAND (block_body, 1) == loop))
return loop;
}
}
else
{
if (block_body == loop)
return loop;
}
}
loop_label = build_labeled_block (0, NULL_TREE);
LABELED_BLOCK_BODY (loop_label) = loop;
PUSH_LABELED_BLOCK (loop_label);
loop = loop_label;
return loop;
}
@ -11431,7 +11431,7 @@ fold_constant_for_init (node, context)
if (code == INTEGER_CST || code == REAL_CST || code == STRING_CST)
return node;
if (TREE_TYPE (node) != NULL_TREE)
if (TREE_TYPE (node) != NULL_TREE && code != VAR_DECL)
return NULL_TREE;
switch (code)
@ -11503,7 +11503,7 @@ fold_constant_for_init (node, context)
val = DECL_INITIAL (node);
/* Guard against infinite recursion. */
DECL_INITIAL (node) = NULL_TREE;
val = fold_constant_for_init (val, DECL_CONTEXT (node));
val = fold_constant_for_init (val, node);
DECL_INITIAL (node) = val;
return val;
@ -11519,7 +11519,7 @@ fold_constant_for_init (node, context)
else if (! QUALIFIED_P (name))
{
decl = lookup_field_wrapper (DECL_CONTEXT (context), name);
if (! FIELD_STATIC (decl))
if (decl == NULL_TREE || ! FIELD_STATIC (decl))
return NULL_TREE;
return fold_constant_for_init (decl, decl);
}