[multiple changes]
2000-10-18 Alexandre Petit-Bianco <apbianco@cygnus.com> * jcf-write.c (OP1): Update `last_bc'. (struct jcf_block): Fixed indentation and typo in comments. New field `last_bc'. (generate_bytecode_insns): Insert `nop' if `jsr' immediately follows `monitorenter'. * parse.y (patch_synchronized_statement): New local `tmp'. Call `patch_string'. Fixes gcj/232. 2000-10-13 Alexandre Petit-Bianco <apbianco@cygnus.com> * check-init.c (check_init): Fixed leading comment. Use LOCAL_FINAL_P. * decl.c (push_jvm_slot): Use MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC. (give_name_to_locals): Likewise. (lang_mark_tree): Handle FIELD_DECL. Register `am' and `wfl' fields in lang_decl_var. * java-tree.h (DECL_FUNCTION_SYNTHETIC_CTOR, DECL_FUNCTION_ALL_FINAL_INITIALIZED): New macros. (FIELD_INNER_ACCESS): Removed ugly cast, macro rewritten. (FIELD_INNER_ACCESS_P, DECL_FIELD_FINAL_IUD, DECL_FIELD_FINAL_LIIC, DECL_FIELD_FINAL_IERR, DECL_FIELD_FINAL_WFL): New macros. (LOCAL_FINAL): Rewritten. (LOCAL_FINAL_P, FINAL_VARIABLE_P, CLASS_FINAL_VARIABLE_P MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC): New macros. (struct lang_decl): Fixed comments. Added `synthetic_ctor' and `init_final' fields. (struct lang_decl_var): Fixed leading comment. Added `am', `wfl', `final_uid', `final_liic', `final_ierr' and `local_final' fields. (TYPE_HAS_FINAL_VARIABLE): New macro. (struct lang_type): Added `afv' field. * parse.y (check_static_final_variable_assignment_flag): New function. (reset_static_final_variable_assignment_flag): Likewise. (check_final_variable_local_assignment_flag): Likewise. (reset_final_variable_local_assignment_flag): Likewise. (check_final_variable_indirect_assignment): Likewise. (check_final_variable_global_assignment_flag): Likewise. (add_inner_class_fields): Use LOCAL_FINAL_P. (register_fields): Handle local finals and final variables. (craft_constructor): Set DECL_FUNCTION_SYNTHETIC_CTOR. (declare_local_variables): Call MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC. (source_start_java_method): Call MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC on local finals. (java_complete_expand_methods): Loop to set TYPE_HAS_FINAL_VARIABLE. Call `reset_final_variable_local_assignment_flag' and `check_final_variable_local_assignment_flag' accordingly before and after constructor expansion. Call `reset_static_final_variable_assignment_flag' before expanding <clinit> and after call `check_static_final_variable_assignment_flag' if the current_class isn't an interface. After all methods have been expanded, call `check_final_variable_global_assignment_flag' and `check_static_final_variable_assignment_flag' if the current class is an interface. (maybe_yank_clinit): Fixed typo in comment. (build_outer_field_access_methods): Removed old sanity check. Use FIELD_INNER_ACCESS_P. Call MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC. Don't create access methods for finals. (resolve_field_access): Use `CLASS_FINAL_VARIABLE_P'. (java_complete_tree): Likewise. Reset DECL_FIELD_FINAL_IUD if existing DECL_INIT has been processed. (java_complete_lhs): Likewise. (check_final_assignment): Filter input on `lvalue''s TREE_CODE. Test for COMPONENT_REF to get to the FIELD_DECL. Implemented new logic. (patch_assignment): Use LOCAL_FINAL_P. (fold_constant_for_init): Reset DECL_FIELD_FINAL_IUD if DECL_INITIAL is nullified. Fixes gcj/163. 2000-10-09 Alexandre Petit-Bianco <apbianco@cygnus.com> * parse.y (pop_current_osb): New function. (array_type:): Use `dims:', changed actions accordingly. Suggested by Anthony Green. (array_creation_expression:): Used pop_current_osb. (cast_expression:): Likewise. (search_applicable_method_list): Fixed indentation. 2000-10-08 Anthony Green <green@redhat.com> * parse.y (array_type_literal): Remove production. (type_literals): Refer to array_type, not array_type_literal. (http://gcc.gnu.org/ml/gcc-patches/2000-12/msg00317.html) From-SVN: r38070
This commit is contained in:
parent
ee4570050a
commit
c7303e411e
@ -235,6 +235,17 @@ Thu Nov 23 02:19:14 2000 J"orn Rennecke <amylaar@redhat.com>
|
||||
|
||||
* verify.c (CHECK_PC_IN_RANGE): Cast result of stmt-expr to void.
|
||||
|
||||
2000-10-18 Alexandre Petit-Bianco <apbianco@cygnus.com>
|
||||
|
||||
* jcf-write.c (OP1): Update `last_bc'.
|
||||
(struct jcf_block): Fixed indentation and typo in comments. New
|
||||
field `last_bc'.
|
||||
(generate_bytecode_insns): Insert `nop' if `jsr' immediately
|
||||
follows `monitorenter'.
|
||||
* parse.y (patch_synchronized_statement): New local `tmp'. Call
|
||||
`patch_string'.
|
||||
Fixes gcj/232.
|
||||
|
||||
2000-10-16 Tom Tromey <tromey@cygnus.com>
|
||||
|
||||
* jvspec.c (lang_specific_driver): Recognize -MF and -MT.
|
||||
@ -298,6 +309,68 @@ Thu Nov 23 02:19:14 2000 J"orn Rennecke <amylaar@redhat.com>
|
||||
* decl.c (init_decl_processing): Call init_class_processing before
|
||||
anything else.
|
||||
|
||||
2000-10-13 Alexandre Petit-Bianco <apbianco@cygnus.com>
|
||||
|
||||
* check-init.c (check_init): Fixed leading comment. Use
|
||||
LOCAL_FINAL_P.
|
||||
* decl.c (push_jvm_slot): Use MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC.
|
||||
(give_name_to_locals): Likewise.
|
||||
(lang_mark_tree): Handle FIELD_DECL. Register `am' and `wfl'
|
||||
fields in lang_decl_var.
|
||||
* java-tree.h (DECL_FUNCTION_SYNTHETIC_CTOR,
|
||||
DECL_FUNCTION_ALL_FINAL_INITIALIZED): New macros.
|
||||
(FIELD_INNER_ACCESS): Removed ugly cast, macro rewritten.
|
||||
(FIELD_INNER_ACCESS_P, DECL_FIELD_FINAL_IUD, DECL_FIELD_FINAL_LIIC,
|
||||
DECL_FIELD_FINAL_IERR, DECL_FIELD_FINAL_WFL): New macros.
|
||||
(LOCAL_FINAL): Rewritten.
|
||||
(LOCAL_FINAL_P, FINAL_VARIABLE_P, CLASS_FINAL_VARIABLE_P
|
||||
MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC): New macros.
|
||||
(struct lang_decl): Fixed comments. Added `synthetic_ctor' and
|
||||
`init_final' fields.
|
||||
(struct lang_decl_var): Fixed leading comment. Added `am', `wfl',
|
||||
`final_uid', `final_liic', `final_ierr' and `local_final' fields.
|
||||
(TYPE_HAS_FINAL_VARIABLE): New macro.
|
||||
(struct lang_type): Added `afv' field.
|
||||
* parse.y (check_static_final_variable_assignment_flag): New function.
|
||||
(reset_static_final_variable_assignment_flag): Likewise.
|
||||
(check_final_variable_local_assignment_flag): Likewise.
|
||||
(reset_final_variable_local_assignment_flag): Likewise.
|
||||
(check_final_variable_indirect_assignment): Likewise.
|
||||
(check_final_variable_global_assignment_flag): Likewise.
|
||||
(add_inner_class_fields): Use LOCAL_FINAL_P.
|
||||
(register_fields): Handle local finals and final variables.
|
||||
(craft_constructor): Set DECL_FUNCTION_SYNTHETIC_CTOR.
|
||||
(declare_local_variables): Call MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC.
|
||||
(source_start_java_method): Call MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC
|
||||
on local finals.
|
||||
(java_complete_expand_methods): Loop to set
|
||||
TYPE_HAS_FINAL_VARIABLE. Call
|
||||
`reset_final_variable_local_assignment_flag' and
|
||||
`check_final_variable_local_assignment_flag' accordingly before
|
||||
and after constructor expansion. Call
|
||||
`reset_static_final_variable_assignment_flag'
|
||||
before expanding <clinit> and after call
|
||||
`check_static_final_variable_assignment_flag' if the
|
||||
current_class isn't an interface. After all methods have been
|
||||
expanded, call `check_final_variable_global_assignment_flag' and
|
||||
`check_static_final_variable_assignment_flag' if the current class
|
||||
is an interface.
|
||||
(maybe_yank_clinit): Fixed typo in comment.
|
||||
(build_outer_field_access_methods): Removed old sanity check. Use
|
||||
FIELD_INNER_ACCESS_P. Call MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC.
|
||||
Don't create access methods for finals.
|
||||
(resolve_field_access): Use `CLASS_FINAL_VARIABLE_P'.
|
||||
(java_complete_tree): Likewise. Reset DECL_FIELD_FINAL_IUD if
|
||||
existing DECL_INIT has been processed.
|
||||
(java_complete_lhs): Likewise.
|
||||
(check_final_assignment): Filter input on `lvalue''s TREE_CODE.
|
||||
Test for COMPONENT_REF to get to the FIELD_DECL. Implemented new
|
||||
logic.
|
||||
(patch_assignment): Use LOCAL_FINAL_P.
|
||||
(fold_constant_for_init): Reset DECL_FIELD_FINAL_IUD if
|
||||
DECL_INITIAL is nullified.
|
||||
Fixes gcj/163.
|
||||
|
||||
2000-10-13 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
|
||||
|
||||
* Make-lang.in (parse.c, parse-scan.c): Create atomically.
|
||||
@ -403,6 +476,20 @@ Thu Nov 23 02:19:14 2000 J"orn Rennecke <amylaar@redhat.com>
|
||||
fields.
|
||||
* lex.h (java_lexer): Added out_buffer, out_first, out_last.
|
||||
|
||||
2000-10-09 Alexandre Petit-Bianco <apbianco@cygnus.com>
|
||||
|
||||
* parse.y (pop_current_osb): New function.
|
||||
(array_type:): Use `dims:', changed actions
|
||||
accordingly. Suggested by Anthony Green.
|
||||
(array_creation_expression:): Used pop_current_osb.
|
||||
(cast_expression:): Likewise.
|
||||
(search_applicable_method_list): Fixed indentation.
|
||||
|
||||
2000-10-08 Anthony Green <green@redhat.com>
|
||||
|
||||
* parse.y (array_type_literal): Remove production.
|
||||
(type_literals): Refer to array_type, not array_type_literal.
|
||||
|
||||
2000-10-07 Alexandre Petit-Bianco <apbianco@cygnus.com>
|
||||
|
||||
Patch contributed by Corey Minyard.
|
||||
|
@ -356,8 +356,7 @@ done_alternative (after, current)
|
||||
start_current_locals = current.save_start_current_locals; \
|
||||
}
|
||||
|
||||
/* Check for (un)initialized local variables in EXP.
|
||||
*/
|
||||
/* Check for (un)initialized local variables in EXP. */
|
||||
|
||||
static void
|
||||
check_init (exp, before)
|
||||
@ -387,14 +386,14 @@ check_init (exp, before)
|
||||
/* We're interested in variable declaration and parameter
|
||||
declaration when they're declared with the `final' modifier. */
|
||||
if ((TREE_CODE (tmp) == VAR_DECL && ! FIELD_STATIC (tmp))
|
||||
|| (TREE_CODE (tmp) == PARM_DECL && LOCAL_FINAL (tmp)))
|
||||
|| (TREE_CODE (tmp) == PARM_DECL && LOCAL_FINAL_P (tmp)))
|
||||
{
|
||||
int index;
|
||||
check_init (TREE_OPERAND (exp, 1), before);
|
||||
index = DECL_BIT_INDEX (tmp);
|
||||
/* A final local already assigned or a final parameter
|
||||
assigned must be reported as errors */
|
||||
if (LOCAL_FINAL (tmp)
|
||||
if (LOCAL_FINAL_P (tmp)
|
||||
&& (index == -1 || TREE_CODE (tmp) == PARM_DECL))
|
||||
parse_error_context (wfl, "Can't assign here a value to the `final' variable `%s'", IDENTIFIER_POINTER (DECL_NAME (tmp)));
|
||||
|
||||
|
@ -127,8 +127,7 @@ push_jvm_slot (index, decl)
|
||||
/* Now link the decl into the decl_map. */
|
||||
if (DECL_LANG_SPECIFIC (decl) == NULL)
|
||||
{
|
||||
DECL_LANG_SPECIFIC (decl)
|
||||
= (struct lang_decl *) ggc_alloc (sizeof (struct lang_decl_var));
|
||||
MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (decl);
|
||||
DECL_LOCAL_START_PC (decl) = 0;
|
||||
DECL_LOCAL_END_PC (decl) = DECL_CODE_LENGTH (current_function_decl);
|
||||
DECL_LOCAL_SLOT_NUMBER (decl) = index;
|
||||
@ -1620,8 +1619,7 @@ give_name_to_locals (jcf)
|
||||
comments for expr.c:maybe_adjust_start_pc. */
|
||||
start_pc = maybe_adjust_start_pc (jcf, code_offset, start_pc, slot);
|
||||
|
||||
DECL_LANG_SPECIFIC (decl)
|
||||
= (struct lang_decl *) ggc_alloc (sizeof (struct lang_decl_var));
|
||||
MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (decl);
|
||||
DECL_LOCAL_SLOT_NUMBER (decl) = slot;
|
||||
DECL_LOCAL_START_PC (decl) = start_pc;
|
||||
#if 0
|
||||
@ -1901,7 +1899,8 @@ lang_mark_tree (t)
|
||||
ggc_mark_tree (li->utf8_ref);
|
||||
}
|
||||
else if (TREE_CODE (t) == VAR_DECL
|
||||
|| TREE_CODE (t) == PARM_DECL)
|
||||
|| TREE_CODE (t) == PARM_DECL
|
||||
|| TREE_CODE (t) == FIELD_DECL)
|
||||
{
|
||||
struct lang_decl_var *ldv =
|
||||
((struct lang_decl_var *) DECL_LANG_SPECIFIC (t));
|
||||
@ -1909,6 +1908,8 @@ lang_mark_tree (t)
|
||||
{
|
||||
ggc_mark (ldv);
|
||||
ggc_mark_tree (ldv->slot_chain);
|
||||
ggc_mark_tree (ldv->am);
|
||||
ggc_mark_tree (ldv->wfl);
|
||||
}
|
||||
}
|
||||
else if (TREE_CODE (t) == FUNCTION_DECL)
|
||||
|
@ -88,7 +88,6 @@ struct JCF;
|
||||
3: METHOD_FINAL (in FUNCTION_DECL)
|
||||
FIELD_FINAL (in FIELD_DECL)
|
||||
CLASS_FINAL (in TYPE_DECL)
|
||||
LOCAL_FINAL (in VAR_DECL)
|
||||
4: METHOD_SYNCHRONIZED (in FUNCTION_DECL).
|
||||
LABEL_IN_SUBR (in LABEL_DECL)
|
||||
CLASS_INTERFACE (in TYPE_DECL)
|
||||
@ -701,11 +700,12 @@ struct lang_identifier
|
||||
is excluded, because sometimes created as a parameter before the
|
||||
function decl exists. */
|
||||
#define DECL_FUNCTION_NAP(DECL) (DECL_LANG_SPECIFIC(DECL)->nap)
|
||||
|
||||
/* For a FIELD_DECL, holds the name of the access method used to
|
||||
read/write the content of the field from an inner class.
|
||||
The cast is ugly. FIXME */
|
||||
#define FIELD_INNER_ACCESS(DECL) ((tree)DECL_LANG_SPECIFIC (DECL))
|
||||
/* True if DECL is a synthetic ctor. */
|
||||
#define DECL_FUNCTION_SYNTHETIC_CTOR(DECL) \
|
||||
(DECL_LANG_SPECIFIC(DECL)->synthetic_ctor)
|
||||
/* True if DECL initializes all its finals */
|
||||
#define DECL_FUNCTION_ALL_FINAL_INITIALIZED(DECL) \
|
||||
(DECL_LANG_SPECIFIC(DECL)->init_final)
|
||||
|
||||
/* True when DECL aliases an outer context local variable. */
|
||||
#define FIELD_LOCAL_ALIAS(DECL) DECL_LANG_FLAG_6 (DECL)
|
||||
@ -779,6 +779,46 @@ struct lang_identifier
|
||||
slot_number in decl_map. */
|
||||
#define DECL_LOCAL_SLOT_CHAIN(NODE) \
|
||||
(((struct lang_decl_var*)DECL_LANG_SPECIFIC(NODE))->slot_chain)
|
||||
/* For a FIELD_DECL, holds the name of the access method. Used to
|
||||
read/write the content of the field from an inner class. */
|
||||
#define FIELD_INNER_ACCESS(DECL) \
|
||||
(((struct lang_decl_var*)DECL_LANG_SPECIFIC(DECL))->am)
|
||||
/* Safely tests whether FIELD_INNER_ACCESS exists or not. */
|
||||
#define FIELD_INNER_ACCESS_P(DECL) \
|
||||
DECL_LANG_SPECIFIC (DECL) && FIELD_INNER_ACCESS (DECL)
|
||||
/* True if a final variable was initialized upon its declaration. */
|
||||
#define DECL_FIELD_FINAL_IUD(NODE) \
|
||||
(((struct lang_decl_var*)DECL_LANG_SPECIFIC(NODE))->final_iud)
|
||||
/* Set to true if a final variable is seen locally initialized on a
|
||||
ctor. */
|
||||
#define DECL_FIELD_FINAL_LIIC(NODE) \
|
||||
(((struct lang_decl_var*)DECL_LANG_SPECIFIC(NODE))->final_liic)
|
||||
/* Set to true if an initialization error was already found with this
|
||||
final variable. */
|
||||
#define DECL_FIELD_FINAL_IERR(NODE) \
|
||||
(((struct lang_decl_var*)DECL_LANG_SPECIFIC(NODE))->final_ierr)
|
||||
/* The original WFL of a final variable. */
|
||||
#define DECL_FIELD_FINAL_WFL(NODE) \
|
||||
(((struct lang_decl_var*)DECL_LANG_SPECIFIC(NODE))->wfl)
|
||||
/* True if NODE is a local final (as opposed to a final variable.)
|
||||
This macro accesses the flag to read or set it. */
|
||||
#define LOCAL_FINAL(NODE) \
|
||||
(((struct lang_decl_var*)DECL_LANG_SPECIFIC(NODE))->local_final)
|
||||
/* True if NODE is a local final. */
|
||||
#define LOCAL_FINAL_P(NODE) (DECL_LANG_SPECIFIC (NODE) && LOCAL_FINAL (NODE))
|
||||
/* True if NODE is a final variable */
|
||||
#define FINAL_VARIABLE_P(NODE) (FIELD_FINAL (NODE) && !FIELD_STATIC (NODE))
|
||||
/* True if NODE is a class final variable */
|
||||
#define CLASS_FINAL_VARIABLE_P(NODE) \
|
||||
(FIELD_FINAL (NODE) && FIELD_STATIC (NODE))
|
||||
/* Create a DECL_LANG_SPECIFIC if necessary. */
|
||||
#define MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC(T) \
|
||||
if (DECL_LANG_SPECIFIC (T) == NULL) \
|
||||
{ \
|
||||
DECL_LANG_SPECIFIC ((T)) \
|
||||
= ((struct lang_decl *) \
|
||||
ggc_alloc_cleared (sizeof (struct lang_decl_var))); \
|
||||
}
|
||||
|
||||
/* For a local VAR_DECL, holds the index into a words bitstring that
|
||||
specifies if this decl is definitively assigned.
|
||||
@ -798,15 +838,15 @@ struct lang_decl
|
||||
tree throws_list; /* Exception specified by `throws' */
|
||||
tree function_decl_body; /* Hold all function's statements */
|
||||
tree called_constructor; /* When decl is a constructor, the
|
||||
list of other constructor it calls. */
|
||||
list of other constructor it calls */
|
||||
struct hash_table init_test_table;
|
||||
/* Class initialization test variables. */
|
||||
/* Class initialization test variables */
|
||||
tree inner_access; /* The identifier of the access method
|
||||
used for invocation from inner classes */
|
||||
int nap; /* Number of artificial parameters */
|
||||
|
||||
int native : 1; /* Nonzero if this is a native
|
||||
method. */
|
||||
int native : 1; /* Nonzero if this is a native method */
|
||||
int synthetic_ctor : 1; /* Nonzero if this is a synthetic ctor */
|
||||
int init_final : 1; /* Nonzero all finals are initialized */
|
||||
};
|
||||
|
||||
/* init_test_table hash table entry structure. */
|
||||
@ -816,13 +856,20 @@ struct init_test_hash_entry
|
||||
tree init_test_decl;
|
||||
};
|
||||
|
||||
/* DECL_LANG_SPECIFIC for VAR_DECL and PARM_DECL. */
|
||||
/* DECL_LANG_SPECIFIC for VAR_DECL, PARM_DECL and sometimes FIELD_DECL
|
||||
(access methods on outer class fields) and final fields. */
|
||||
struct lang_decl_var
|
||||
{
|
||||
int slot_number;
|
||||
int start_pc;
|
||||
int end_pc;
|
||||
tree slot_chain;
|
||||
tree am; /* Access method for this field (1.1) */
|
||||
tree wfl; /* Original wfl */
|
||||
int final_iud : 1; /* Final initialized upon declaration */
|
||||
int final_liic : 1; /* Final locally initialized in ctors */
|
||||
int final_ierr : 1; /* Initialization error already detected */
|
||||
int local_final : 1; /* True if the decl is a local final */
|
||||
};
|
||||
|
||||
/* Macro to access fields in `struct lang_type'. */
|
||||
@ -847,6 +894,7 @@ struct lang_decl_var
|
||||
#define TYPE_DOT_CLASS(T) (TYPE_LANG_SPECIFIC(T)->dot_class)
|
||||
#define TYPE_PRIVATE_INNER_CLASS(T) (TYPE_LANG_SPECIFIC(T)->pic)
|
||||
#define TYPE_PROTECTED_INNER_CLASS(T) (TYPE_LANG_SPECIFIC(T)->poic)
|
||||
#define TYPE_HAS_FINAL_VARIABLE(T) (TYPE_LANG_SPECIFIC(T)->afv)
|
||||
|
||||
struct lang_type
|
||||
{
|
||||
@ -863,6 +911,7 @@ struct lang_type
|
||||
<non_primitive_type>.class */
|
||||
unsigned pic:1; /* Private Inner Class. */
|
||||
unsigned poic:1; /* Protected Inner Class. */
|
||||
unsigned afv:1; /* Has final variables */
|
||||
};
|
||||
|
||||
#ifdef JAVA_USE_HANDLES
|
||||
@ -1110,7 +1159,6 @@ struct rtx_def * java_lang_expand_expr PARAMS ((tree, rtx, enum machine_mode,
|
||||
#define FIELD_FINAL(DECL) DECL_LANG_FLAG_3 (DECL)
|
||||
#define FIELD_VOLATILE(DECL) DECL_LANG_FLAG_4 (DECL)
|
||||
#define FIELD_TRANSIENT(DECL) DECL_LANG_FLAG_5 (DECL)
|
||||
#define LOCAL_FINAL(DECL) FIELD_FINAL(DECL)
|
||||
|
||||
/* Access flags etc for a class (a TYPE_DECL): */
|
||||
|
||||
|
@ -57,7 +57,7 @@ char *jcf_write_base_directory = NULL;
|
||||
/* Add a 1-byte instruction/operand I to bytecode.data,
|
||||
assuming space has already been RESERVE'd. */
|
||||
|
||||
#define OP1(I) (*state->bytecode.ptr++ = (I), CHECK_OP(state))
|
||||
#define OP1(I) (state->last_bc = *state->bytecode.ptr++ = (I), CHECK_OP(state))
|
||||
|
||||
/* Like OP1, but I is a 2-byte big endian integer. */
|
||||
|
||||
@ -131,13 +131,14 @@ struct jcf_block
|
||||
|
||||
int linenumber;
|
||||
|
||||
/* After finish_jcf_block is called, The actual instructions contained in this block.
|
||||
Before than NULL, and the instructions are in state->bytecode. */
|
||||
/* After finish_jcf_block is called, The actual instructions
|
||||
contained in this block. Before than NULL, and the instructions
|
||||
are in state->bytecode. */
|
||||
union {
|
||||
struct chunk *chunk;
|
||||
|
||||
/* If pc==PENDING_CLEANUP_PC, start_label is the start of the region
|
||||
coveed by the cleanup. */
|
||||
covered by the cleanup. */
|
||||
struct jcf_block *start_label;
|
||||
} v;
|
||||
|
||||
@ -272,8 +273,10 @@ struct jcf_partial
|
||||
/* If non-NULL, use this for the return value. */
|
||||
tree return_value_decl;
|
||||
|
||||
/* Information about the current switch statemenet. */
|
||||
/* Information about the current switch statement. */
|
||||
struct jcf_switch_state *sw_state;
|
||||
|
||||
enum java_opcode last_bc; /* The last emitted bytecode */
|
||||
};
|
||||
|
||||
static void generate_bytecode_insns PARAMS ((tree, int, struct jcf_partial *));
|
||||
@ -2158,7 +2161,16 @@ generate_bytecode_insns (exp, target, state)
|
||||
tree src = TREE_OPERAND (exp, 0);
|
||||
tree src_type = TREE_TYPE (src);
|
||||
tree dst_type = TREE_TYPE (exp);
|
||||
generate_bytecode_insns (TREE_OPERAND (exp, 0), target, state);
|
||||
/* Detect the situation of compiling an empty synchronized
|
||||
block. A nop should be emitted in order to produce
|
||||
verifiable bytecode. */
|
||||
if (exp == empty_stmt_node
|
||||
&& state->last_bc == OPCODE_monitorenter
|
||||
&& state->labeled_blocks
|
||||
&& state->labeled_blocks->pc == PENDING_CLEANUP_PC)
|
||||
OP1 (OPCODE_nop);
|
||||
else
|
||||
generate_bytecode_insns (TREE_OPERAND (exp, 0), target, state);
|
||||
if (target == IGNORE_TARGET || src_type == dst_type)
|
||||
break;
|
||||
if (TREE_CODE (dst_type) == POINTER_TYPE)
|
||||
|
484
gcc/java/parse.y
484
gcc/java/parse.y
@ -102,6 +102,12 @@ static int process_imports PARAMS ((void));
|
||||
static void read_import_dir PARAMS ((tree));
|
||||
static int find_in_imports_on_demand PARAMS ((tree));
|
||||
static void find_in_imports PARAMS ((tree));
|
||||
static void check_static_final_variable_assignment_flag PARAMS ((tree));
|
||||
static void reset_static_final_variable_assignment_flag PARAMS ((tree));
|
||||
static void check_final_variable_local_assignment_flag PARAMS ((tree, tree));
|
||||
static void reset_final_variable_local_assignment_flag PARAMS ((tree));
|
||||
static int check_final_variable_indirect_assignment PARAMS ((tree));
|
||||
static void check_final_variable_global_assignment_flag PARAMS ((tree));
|
||||
static void check_inner_class_access PARAMS ((tree, tree, tree));
|
||||
static int check_pkg_class_access PARAMS ((tree, tree));
|
||||
static void register_package PARAMS ((tree));
|
||||
@ -287,6 +293,7 @@ static void java_parser_context_pop_initialized_field PARAMS ((void));
|
||||
static tree reorder_static_initialized PARAMS ((tree));
|
||||
static void java_parser_context_suspend PARAMS ((void));
|
||||
static void java_parser_context_resume PARAMS ((void));
|
||||
static int pop_current_osb PARAMS ((struct parser_ctxt *));
|
||||
|
||||
/* JDK 1.1 work. FIXME */
|
||||
|
||||
@ -580,7 +587,7 @@ static tree currently_caught_type_list;
|
||||
BOOLEAN_TK INTEGRAL_TK FP_TK
|
||||
|
||||
/* Added or modified JDK 1.1 rule types */
|
||||
%type <node> type_literals array_type_literal
|
||||
%type <node> type_literals
|
||||
|
||||
%%
|
||||
/* 19.2 Production from 2.3: The Syntactic Grammar */
|
||||
@ -652,19 +659,23 @@ interface_type:
|
||||
;
|
||||
|
||||
array_type:
|
||||
primitive_type OSB_TK CSB_TK
|
||||
primitive_type dims
|
||||
{
|
||||
$$ = build_java_array_type ($1, -1);
|
||||
CLASS_LOADED_P ($$) = 1;
|
||||
int osb = pop_current_osb (ctxp);
|
||||
tree t = build_java_array_type (($1), -1);
|
||||
CLASS_LOADED_P (t) = 1;
|
||||
while (--osb)
|
||||
t = build_unresolved_array_type (t);
|
||||
$$ = t;
|
||||
}
|
||||
| name dims
|
||||
{
|
||||
int osb = pop_current_osb (ctxp);
|
||||
tree t = $1;
|
||||
while (osb--)
|
||||
t = build_unresolved_array_type (t);
|
||||
$$ = t;
|
||||
}
|
||||
| name OSB_TK CSB_TK
|
||||
{ $$ = build_unresolved_array_type ($1); }
|
||||
| array_type OSB_TK CSB_TK
|
||||
{ $$ = build_unresolved_array_type ($1); }
|
||||
| primitive_type OSB_TK error
|
||||
{RULE ("']' expected"); RECOVER;}
|
||||
| array_type OSB_TK error
|
||||
{RULE ("']' expected"); RECOVER;}
|
||||
;
|
||||
|
||||
/* 19.5 Productions from 6: Names */
|
||||
@ -1935,28 +1946,10 @@ primary_no_new_array:
|
||||
{yyerror ("'class' expected" ); RECOVER;}
|
||||
;
|
||||
|
||||
/* Added, JDK1.1 type literals. We can't use `type' directly, so we
|
||||
broke the rule down a bit. */
|
||||
|
||||
array_type_literal:
|
||||
primitive_type OSB_TK CSB_TK
|
||||
{
|
||||
$$ = build_java_array_type ($1, -1);
|
||||
CLASS_LOADED_P ($$) = 1;
|
||||
}
|
||||
| name OSB_TK CSB_TK
|
||||
{ $$ = build_unresolved_array_type ($1); }
|
||||
/* This triggers two reduce/reduce conflict between array_type_literal and
|
||||
dims. FIXME.
|
||||
| array_type OSB_TK CSB_TK
|
||||
{ $$ = build_unresolved_array_type ($1); }
|
||||
*/
|
||||
;
|
||||
|
||||
type_literals:
|
||||
name DOT_TK CLASS_TK
|
||||
{ $$ = build_incomplete_class_ref ($2.location, $1); }
|
||||
| array_type_literal DOT_TK CLASS_TK
|
||||
| array_type DOT_TK CLASS_TK
|
||||
{ $$ = build_incomplete_class_ref ($2.location, $1); }
|
||||
| primitive_type DOT_TK CLASS_TK
|
||||
{ $$ = build_class_ref ($1); }
|
||||
@ -2085,15 +2078,16 @@ array_creation_expression:
|
||||
| NEW_TK class_or_interface_type dim_exprs
|
||||
{ $$ = build_newarray_node ($2, $3, 0); }
|
||||
| NEW_TK primitive_type dim_exprs dims
|
||||
{ $$ = build_newarray_node ($2, $3, CURRENT_OSB (ctxp));}
|
||||
{ $$ = build_newarray_node ($2, $3, pop_current_osb (ctxp));}
|
||||
| NEW_TK class_or_interface_type dim_exprs dims
|
||||
{ $$ = build_newarray_node ($2, $3, CURRENT_OSB (ctxp));}
|
||||
{ $$ = build_newarray_node ($2, $3, pop_current_osb (ctxp));}
|
||||
/* Added, JDK1.1 anonymous array. Initial documentation rule
|
||||
modified */
|
||||
| NEW_TK class_or_interface_type dims array_initializer
|
||||
{
|
||||
char *sig;
|
||||
while (CURRENT_OSB (ctxp)--)
|
||||
int osb = pop_current_osb (ctxp);
|
||||
while (osb--)
|
||||
obstack_1grow (&temporary_obstack, '[');
|
||||
sig = obstack_finish (&temporary_obstack);
|
||||
$$ = build (NEW_ANONYMOUS_ARRAY_EXPR, NULL_TREE,
|
||||
@ -2101,8 +2095,9 @@ array_creation_expression:
|
||||
}
|
||||
| NEW_TK primitive_type dims array_initializer
|
||||
{
|
||||
int osb = pop_current_osb (ctxp);
|
||||
tree type = $2;
|
||||
while (CURRENT_OSB (ctxp)--)
|
||||
while (osb--)
|
||||
type = build_java_array_type (type, -1);
|
||||
$$ = build (NEW_ANONYMOUS_ARRAY_EXPR, NULL_TREE,
|
||||
build_pointer_type (type), NULL_TREE, $4);
|
||||
@ -2325,9 +2320,9 @@ cast_expression: /* Error handling here is potentially weak */
|
||||
OP_TK primitive_type dims CP_TK unary_expression
|
||||
{
|
||||
tree type = $2;
|
||||
while (CURRENT_OSB (ctxp)--)
|
||||
int osb = pop_current_osb (ctxp);
|
||||
while (osb--)
|
||||
type = build_java_array_type (type, -1);
|
||||
ctxp->osb_depth--;
|
||||
$$ = build_cast ($1.location, type, $5);
|
||||
}
|
||||
| OP_TK primitive_type CP_TK unary_expression
|
||||
@ -2337,9 +2332,9 @@ cast_expression: /* Error handling here is potentially weak */
|
||||
| OP_TK name dims CP_TK unary_expression_not_plus_minus
|
||||
{
|
||||
const char *ptr;
|
||||
while (CURRENT_OSB (ctxp)--)
|
||||
int osb = pop_current_osb (ctxp);
|
||||
while (osb--)
|
||||
obstack_1grow (&temporary_obstack, '[');
|
||||
ctxp->osb_depth--;
|
||||
obstack_grow0 (&temporary_obstack,
|
||||
IDENTIFIER_POINTER (EXPR_WFL_NODE ($2)),
|
||||
IDENTIFIER_LENGTH (EXPR_WFL_NODE ($2)));
|
||||
@ -2593,6 +2588,25 @@ constant_expression:
|
||||
;
|
||||
|
||||
%%
|
||||
|
||||
/* Helper function to retrieve an OSB count. Should be used when the
|
||||
`dims:' rule is being used. */
|
||||
|
||||
static int
|
||||
pop_current_osb (ctxp)
|
||||
struct parser_ctxt *ctxp;
|
||||
{
|
||||
int to_return;
|
||||
|
||||
if (ctxp->osb_depth < 0)
|
||||
fatal ("osb stack underflow");
|
||||
|
||||
to_return = CURRENT_OSB (ctxp);
|
||||
ctxp->osb_depth--;
|
||||
|
||||
return to_return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* This section of the code deal with save/restoring parser contexts.
|
||||
@ -3952,7 +3966,7 @@ add_inner_class_fields (class_decl, fct_decl)
|
||||
tree wfl, init, list;
|
||||
|
||||
/* Avoid non final arguments. */
|
||||
if (!LOCAL_FINAL (decl))
|
||||
if (!LOCAL_FINAL_P (decl))
|
||||
continue;
|
||||
|
||||
MANGLE_OUTER_LOCAL_VARIABLE_NAME (name, DECL_NAME (decl));
|
||||
@ -4185,11 +4199,29 @@ register_fields (flags, type, variable_list)
|
||||
field_decl = add_field (class_type, current_name, real_type, flags);
|
||||
CHECK_DEPRECATED (field_decl);
|
||||
|
||||
/* If the couple initializer/initialized is marked ARG_FINAL_P, we
|
||||
mark the created field FIELD_LOCAL_ALIAS, so that we can
|
||||
hide parameters to this inner class finit$ and constructors. */
|
||||
/* If the field denotes a final instance variable, then we
|
||||
allocate a LANG_DECL_SPECIFIC part to keep track of its
|
||||
initialization. We also mark whether the field was
|
||||
initialized upon it's declaration. We don't do that if the
|
||||
created field is an alias to a final local. */
|
||||
if (!ARG_FINAL_P (current) && (flags & ACC_FINAL))
|
||||
{
|
||||
MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (field_decl);
|
||||
DECL_FIELD_FINAL_WFL (field_decl) = cl;
|
||||
if ((flags & ACC_STATIC) && init)
|
||||
DECL_FIELD_FINAL_IUD (field_decl) = 1;
|
||||
}
|
||||
|
||||
/* If the couple initializer/initialized is marked ARG_FINAL_P,
|
||||
we mark the created field FIELD_LOCAL_ALIAS, so that we can
|
||||
hide parameters to this inner class finit$ and
|
||||
constructors. It also means that the field isn't final per
|
||||
say. */
|
||||
if (ARG_FINAL_P (current))
|
||||
FIELD_LOCAL_ALIAS (field_decl) = 1;
|
||||
{
|
||||
FIELD_LOCAL_ALIAS (field_decl) = 1;
|
||||
FIELD_FINAL (field_decl) = 0;
|
||||
}
|
||||
|
||||
/* Check if we must chain. */
|
||||
if (must_chain)
|
||||
@ -5182,7 +5214,7 @@ craft_constructor (class_decl, args)
|
||||
fix_method_argument_names (parm, decl);
|
||||
/* Now, mark the artificial parameters. */
|
||||
DECL_FUNCTION_NAP (decl) = artificial;
|
||||
DECL_CONSTRUCTOR_P (decl) = 1;
|
||||
DECL_FUNCTION_SYNTHETIC_CTOR (decl) = DECL_CONSTRUCTOR_P (decl) = 1;
|
||||
}
|
||||
|
||||
|
||||
@ -7039,6 +7071,7 @@ declare_local_variables (modifier, type, vlist)
|
||||
/* Never layout this decl. This will be done when its scope
|
||||
will be entered */
|
||||
decl = build_decl (VAR_DECL, name, real_type);
|
||||
MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (decl);
|
||||
LOCAL_FINAL (decl) = final_p;
|
||||
BLOCK_CHAIN_DECL (decl);
|
||||
|
||||
@ -7116,7 +7149,10 @@ source_start_java_method (fndecl)
|
||||
/* Remember if a local variable was declared final (via its
|
||||
TREE_LIST of type/name.) Set LOCAL_FINAL accordingly. */
|
||||
if (ARG_FINAL_P (tem))
|
||||
LOCAL_FINAL (parm_decl) = 1;
|
||||
{
|
||||
MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (parm_decl);
|
||||
LOCAL_FINAL (parm_decl) = 1;
|
||||
}
|
||||
|
||||
BLOCK_CHAIN_DECL (parm_decl);
|
||||
}
|
||||
@ -7164,7 +7200,7 @@ static void
|
||||
end_artificial_method_body (mdecl)
|
||||
tree mdecl;
|
||||
{
|
||||
BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (mdecl)) = exit_block ();
|
||||
BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (mdecl)) = exit_blcok ();
|
||||
exit_block ();
|
||||
}
|
||||
|
||||
@ -7472,6 +7508,14 @@ java_complete_expand_methods (class_decl)
|
||||
|
||||
current_class = TREE_TYPE (class_decl);
|
||||
|
||||
/* Find whether the class has final variables */
|
||||
for (decl = TYPE_FIELDS (current_class); decl; decl = TREE_CHAIN (decl))
|
||||
if (FIELD_FINAL (decl))
|
||||
{
|
||||
TYPE_HAS_FINAL_VARIABLE (current_class) = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Initialize a new constant pool */
|
||||
init_outgoing_cpool ();
|
||||
|
||||
@ -7504,7 +7548,15 @@ java_complete_expand_methods (class_decl)
|
||||
if (no_body)
|
||||
restore_line_number_status (1);
|
||||
|
||||
/* Reset the final local variable assignment flags */
|
||||
if (TYPE_HAS_FINAL_VARIABLE (current_class))
|
||||
reset_final_variable_local_assignment_flag (current_class);
|
||||
|
||||
java_complete_expand_method (decl);
|
||||
|
||||
/* Check for missed out final variable assignment */
|
||||
if (TYPE_HAS_FINAL_VARIABLE (current_class))
|
||||
check_final_variable_local_assignment_flag (current_class, decl);
|
||||
|
||||
if (no_body)
|
||||
restore_line_number_status (0);
|
||||
@ -7532,10 +7584,17 @@ java_complete_expand_methods (class_decl)
|
||||
/* If there is indeed a <clinit>, fully expand it now */
|
||||
if (clinit)
|
||||
{
|
||||
/* Reset the final local variable assignment flags */
|
||||
if (TYPE_HAS_FINAL_VARIABLE (current_class))
|
||||
reset_static_final_variable_assignment_flag (current_class);
|
||||
/* Prevent the use of `this' inside <clinit> */
|
||||
ctxp->explicit_constructor_p = 1;
|
||||
java_complete_expand_method (clinit);
|
||||
ctxp->explicit_constructor_p = 0;
|
||||
/* Check for missed out static final variable assignment */
|
||||
if (TYPE_HAS_FINAL_VARIABLE (current_class)
|
||||
&& !CLASS_INTERFACE (class_decl))
|
||||
check_static_final_variable_assignment_flag (current_class);
|
||||
}
|
||||
|
||||
/* We might have generated a class$ that we now want to expand */
|
||||
@ -7550,6 +7609,15 @@ java_complete_expand_methods (class_decl)
|
||||
&& verify_constructor_circularity (decl, decl))
|
||||
break;
|
||||
|
||||
/* Final check on the initialization of final variables. */
|
||||
if (TYPE_HAS_FINAL_VARIABLE (current_class))
|
||||
{
|
||||
check_final_variable_global_assignment_flag (current_class);
|
||||
/* If we have an interface, check for uninitialized fields. */
|
||||
if (CLASS_INTERFACE (class_decl))
|
||||
check_static_final_variable_assignment_flag (current_class);
|
||||
}
|
||||
|
||||
/* Save the constant pool. We'll need to restore it later. */
|
||||
TYPE_CPOOL (current_class) = outgoing_cpool;
|
||||
}
|
||||
@ -7690,7 +7758,7 @@ maybe_yank_clinit (mdecl)
|
||||
continue;
|
||||
|
||||
/* Anything that isn't String or a basic type is ruled out -- or
|
||||
if we now how to deal with it (when doing things natively) we
|
||||
if we know how to deal with it (when doing things natively) we
|
||||
should generated an empty <clinit> so that SUID are computed
|
||||
correctly. */
|
||||
if (! JSTRING_TYPE_P (TREE_TYPE (current))
|
||||
@ -8045,14 +8113,11 @@ build_outer_field_access_methods (decl)
|
||||
{
|
||||
tree id, args, stmt, mdecl;
|
||||
|
||||
/* Check point, to be removed. FIXME */
|
||||
if (FIELD_INNER_ACCESS (decl)
|
||||
&& TREE_CODE (FIELD_INNER_ACCESS (decl)) != IDENTIFIER_NODE)
|
||||
abort ();
|
||||
|
||||
if (FIELD_INNER_ACCESS (decl))
|
||||
if (FIELD_INNER_ACCESS_P (decl))
|
||||
return FIELD_INNER_ACCESS (decl);
|
||||
|
||||
MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (decl);
|
||||
|
||||
/* Create the identifier and a function named after it. */
|
||||
id = build_new_access_id ();
|
||||
|
||||
@ -8070,17 +8135,21 @@ build_outer_field_access_methods (decl)
|
||||
TREE_TYPE (decl), id, args, stmt);
|
||||
DECL_FUNCTION_ACCESS_DECL (mdecl) = decl;
|
||||
|
||||
/* Create the write access method */
|
||||
args = build_tree_list (inst_id, build_pointer_type (DECL_CONTEXT (decl)));
|
||||
TREE_CHAIN (args) = build_tree_list (wpv_id, TREE_TYPE (decl));
|
||||
TREE_CHAIN (TREE_CHAIN (args)) = end_params_node;
|
||||
stmt = make_qualified_primary (build_wfl_node (inst_id),
|
||||
build_wfl_node (DECL_NAME (decl)), 0);
|
||||
stmt = build_return (0, build_assignment (ASSIGN_TK, 0, stmt,
|
||||
build_wfl_node (wpv_id)));
|
||||
|
||||
mdecl = build_outer_field_access_method (DECL_CONTEXT (decl),
|
||||
TREE_TYPE (decl), id, args, stmt);
|
||||
/* Create the write access method. No write access for final variable */
|
||||
if (!FIELD_FINAL (decl))
|
||||
{
|
||||
args = build_tree_list (inst_id,
|
||||
build_pointer_type (DECL_CONTEXT (decl)));
|
||||
TREE_CHAIN (args) = build_tree_list (wpv_id, TREE_TYPE (decl));
|
||||
TREE_CHAIN (TREE_CHAIN (args)) = end_params_node;
|
||||
stmt = make_qualified_primary (build_wfl_node (inst_id),
|
||||
build_wfl_node (DECL_NAME (decl)), 0);
|
||||
stmt = build_return (0, build_assignment (ASSIGN_TK, 0, stmt,
|
||||
build_wfl_node (wpv_id)));
|
||||
mdecl = build_outer_field_access_method (DECL_CONTEXT (decl),
|
||||
TREE_TYPE (decl), id,
|
||||
args, stmt);
|
||||
}
|
||||
DECL_FUNCTION_ACCESS_DECL (mdecl) = decl;
|
||||
|
||||
/* Return the access name */
|
||||
@ -8986,7 +9055,7 @@ resolve_field_access (qual_wfl, field_decl, field_type)
|
||||
if (!type_found)
|
||||
type_found = DECL_CONTEXT (decl);
|
||||
is_static = JDECL_P (decl) && FIELD_STATIC (decl);
|
||||
if (FIELD_FINAL (decl) && FIELD_STATIC (decl)
|
||||
if (CLASS_FINAL_VARIABLE_P (decl)
|
||||
&& JPRIMITIVE_TYPE_P (TREE_TYPE (decl))
|
||||
&& DECL_INITIAL (decl))
|
||||
{
|
||||
@ -10587,7 +10656,7 @@ search_applicable_methods_list (lc, method, name, arglist, list, all_list)
|
||||
else if (!lc && (DECL_CONSTRUCTOR_P (method)
|
||||
|| (GET_METHOD_NAME (method) != name)))
|
||||
continue;
|
||||
|
||||
|
||||
if (argument_types_convertible (method, arglist))
|
||||
{
|
||||
/* Retain accessible methods only */
|
||||
@ -10996,7 +11065,7 @@ java_complete_tree (node)
|
||||
tree node;
|
||||
{
|
||||
node = java_complete_lhs (node);
|
||||
if (JDECL_P (node) && FIELD_STATIC (node) && FIELD_FINAL (node)
|
||||
if (JDECL_P (node) && CLASS_FINAL_VARIABLE_P (node)
|
||||
&& DECL_INITIAL (node) != NULL_TREE
|
||||
&& !flag_emit_xref)
|
||||
{
|
||||
@ -11015,6 +11084,8 @@ java_complete_tree (node)
|
||||
else
|
||||
return value;
|
||||
}
|
||||
else
|
||||
DECL_FIELD_FINAL_IUD (node) = 0;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
@ -11505,6 +11576,8 @@ java_complete_lhs (node)
|
||||
}
|
||||
if (! flag_emit_class_files)
|
||||
DECL_INITIAL (nn) = NULL_TREE;
|
||||
if (CLASS_FINAL_VARIABLE_P (nn))
|
||||
DECL_FIELD_FINAL_IUD (nn) = 0;
|
||||
}
|
||||
wfl_op2 = TREE_OPERAND (node, 1);
|
||||
|
||||
@ -12062,6 +12135,214 @@ print_int_node (node)
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* This section of the code handle assignment check with FINAL
|
||||
variables. */
|
||||
|
||||
static void
|
||||
reset_static_final_variable_assignment_flag (class)
|
||||
tree class;
|
||||
{
|
||||
tree field;
|
||||
for (field = TYPE_FIELDS (class); field; field = TREE_CHAIN (field))
|
||||
if (CLASS_FINAL_VARIABLE_P (field))
|
||||
DECL_FIELD_FINAL_LIIC (field) = 0;
|
||||
}
|
||||
|
||||
/* Figure whether all final static variable have been initialized. */
|
||||
|
||||
static void
|
||||
check_static_final_variable_assignment_flag (class)
|
||||
tree class;
|
||||
{
|
||||
tree field;
|
||||
|
||||
for (field = TYPE_FIELDS (class); field; field = TREE_CHAIN (field))
|
||||
if (CLASS_FINAL_VARIABLE_P (field)
|
||||
&& !DECL_FIELD_FINAL_IUD (field) && !DECL_FIELD_FINAL_LIIC (field))
|
||||
parse_error_context
|
||||
(DECL_FIELD_FINAL_WFL (field),
|
||||
"Blank static final variable `%s' may not have be initialized",
|
||||
IDENTIFIER_POINTER (DECL_NAME (field)));
|
||||
}
|
||||
|
||||
/* This function marks all final variable locally unassigned. */
|
||||
|
||||
static void
|
||||
reset_final_variable_local_assignment_flag (class)
|
||||
tree class;
|
||||
{
|
||||
tree field;
|
||||
for (field = TYPE_FIELDS (class); field; field = TREE_CHAIN (field))
|
||||
if (FINAL_VARIABLE_P (field))
|
||||
DECL_FIELD_FINAL_LIIC (field) = 0;
|
||||
}
|
||||
|
||||
/* Figure whether all final variables have beem initialized in MDECL
|
||||
and mark MDECL accordingly. */
|
||||
|
||||
static void
|
||||
check_final_variable_local_assignment_flag (class, mdecl)
|
||||
tree class;
|
||||
tree mdecl;
|
||||
{
|
||||
tree field;
|
||||
int initialized = 0;
|
||||
int non_initialized = 0;
|
||||
|
||||
if (DECL_FUNCTION_SYNTHETIC_CTOR (mdecl))
|
||||
return;
|
||||
|
||||
/* First find out whether all final variables or no final variable
|
||||
are initialized in this ctor. We don't take into account final
|
||||
variable that have been initialized upon declaration. */
|
||||
for (field = TYPE_FIELDS (class); field; field = TREE_CHAIN (field))
|
||||
if (FINAL_VARIABLE_P (field) && !DECL_FIELD_FINAL_IUD (field))
|
||||
{
|
||||
if (DECL_FIELD_FINAL_LIIC (field))
|
||||
initialized++;
|
||||
else
|
||||
non_initialized++;
|
||||
}
|
||||
|
||||
/* There were no non initialized variable and no initialized variable.
|
||||
This ctor is fine. */
|
||||
if (!non_initialized && !initialized)
|
||||
DECL_FUNCTION_ALL_FINAL_INITIALIZED (mdecl) = 1;
|
||||
/* If no variables have been initialized, that fine. We'll check
|
||||
later whether this ctor calls a constructor which initializes
|
||||
them. We mark the ctor as not initializing all its finals. */
|
||||
else if (initialized == 0)
|
||||
DECL_FUNCTION_ALL_FINAL_INITIALIZED (mdecl) = 0;
|
||||
/* If we have a mixed bag, then we have a problem. We need to report
|
||||
all the variables we're not initializing. */
|
||||
else if (initialized && non_initialized)
|
||||
{
|
||||
DECL_FUNCTION_ALL_FINAL_INITIALIZED (mdecl) = 0;
|
||||
for (field = TYPE_FIELDS (class); field; field = TREE_CHAIN (field))
|
||||
if (FIELD_FINAL (field)
|
||||
&& !DECL_FIELD_FINAL_IUD (field) && !DECL_FIELD_FINAL_LIIC (field))
|
||||
{
|
||||
parse_error_context
|
||||
(lookup_cl (mdecl),
|
||||
"Blank final variable `%s' may not have been initialized in this constructor",
|
||||
IDENTIFIER_POINTER (DECL_NAME (field)));
|
||||
DECL_FIELD_FINAL_IERR (field) = 1;
|
||||
}
|
||||
}
|
||||
/* Otherwise we know this ctor is initializing all its final
|
||||
variable. We mark it so. */
|
||||
else
|
||||
DECL_FUNCTION_ALL_FINAL_INITIALIZED (mdecl) = 1;
|
||||
}
|
||||
|
||||
/* This function recurses in a simple what through STMT and stops when
|
||||
it finds a constructor call. It then verifies that the called
|
||||
constructor initialized its final properly. Return 1 upon success,
|
||||
0 or -1 otherwise. */
|
||||
|
||||
static int
|
||||
check_final_variable_indirect_assignment (stmt)
|
||||
tree stmt;
|
||||
{
|
||||
int res;
|
||||
switch (TREE_CODE (stmt))
|
||||
{
|
||||
case EXPR_WITH_FILE_LOCATION:
|
||||
return check_final_variable_indirect_assignment (EXPR_WFL_NODE (stmt));
|
||||
case COMPOUND_EXPR:
|
||||
res = check_final_variable_indirect_assignment (TREE_OPERAND (stmt, 0));
|
||||
if (res)
|
||||
return res;
|
||||
return check_final_variable_indirect_assignment (TREE_OPERAND (stmt, 1));
|
||||
case SAVE_EXPR:
|
||||
return check_final_variable_indirect_assignment (TREE_OPERAND (stmt, 0));
|
||||
case CALL_EXPR:
|
||||
{
|
||||
tree decl = TREE_OPERAND (stmt, 0);
|
||||
tree fbody;
|
||||
|
||||
if (TREE_CODE (decl) != FUNCTION_DECL)
|
||||
decl = TREE_OPERAND (TREE_OPERAND (decl, 0), 0);
|
||||
if (TREE_CODE (decl) != FUNCTION_DECL)
|
||||
fatal ("Can't find FUNCTION_DECL in CALL_EXPR - check_final_variable_indirect_assignment");
|
||||
if (DECL_FUNCTION_ALL_FINAL_INITIALIZED (decl))
|
||||
return 1;
|
||||
if (DECL_FINIT_P (decl) || DECL_CONTEXT (decl) != current_class)
|
||||
return -1;
|
||||
fbody = BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (decl));
|
||||
if (fbody == error_mark_node)
|
||||
return -1;
|
||||
fbody = BLOCK_EXPR_BODY (fbody);
|
||||
return check_final_variable_indirect_assignment (fbody);
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This is the last chance to catch a final variable initialization
|
||||
problem. This routine will report an error if a final variable was
|
||||
never (globally) initialized and never reported as not having been
|
||||
initialized properly. */
|
||||
|
||||
static void
|
||||
check_final_variable_global_assignment_flag (class)
|
||||
tree class;
|
||||
{
|
||||
tree field, mdecl;
|
||||
int nnctor = 0;
|
||||
|
||||
/* We go through all natural ctors and see whether they're
|
||||
initializing all their final variables or not. */
|
||||
current_function_decl = NULL_TREE; /* For the error report. */
|
||||
for (mdecl = TYPE_METHODS (class); mdecl; mdecl = TREE_CHAIN (mdecl))
|
||||
if (DECL_CONSTRUCTOR_P (mdecl) && ! DECL_FUNCTION_SYNTHETIC_CTOR (mdecl))
|
||||
{
|
||||
if (!DECL_FUNCTION_ALL_FINAL_INITIALIZED (mdecl))
|
||||
{
|
||||
/* It doesn't. Maybe it calls a constructor that initializes
|
||||
them. find out. */
|
||||
tree fbody = BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (mdecl));
|
||||
if (fbody == error_mark_node)
|
||||
continue;
|
||||
fbody = BLOCK_EXPR_BODY (fbody);
|
||||
if (check_final_variable_indirect_assignment (fbody) == 1)
|
||||
{
|
||||
DECL_FUNCTION_ALL_FINAL_INITIALIZED (mdecl) = 1;
|
||||
nnctor++;
|
||||
}
|
||||
else
|
||||
parse_error_context
|
||||
(lookup_cl (mdecl),
|
||||
"Final variable initialization error in this constructor");
|
||||
}
|
||||
else
|
||||
nnctor++;
|
||||
}
|
||||
|
||||
/* Finally we catch final variables that never were initialized */
|
||||
for (field = TYPE_FIELDS (class); field; field = TREE_CHAIN (field))
|
||||
if (FINAL_VARIABLE_P (field)
|
||||
/* If the field wasn't initialized upon declaration */
|
||||
&& !DECL_FIELD_FINAL_IUD (field)
|
||||
/* There wasn't natural ctor in which the field could have been
|
||||
initialized */
|
||||
&& !nnctor
|
||||
/* If we never reported a problem with this field */
|
||||
&& !DECL_FIELD_FINAL_IERR (field))
|
||||
{
|
||||
current_function_decl = NULL;
|
||||
parse_error_context
|
||||
(DECL_FIELD_FINAL_WFL (field),
|
||||
"Final variable `%s' hasn't been initialized upon its declaration",
|
||||
IDENTIFIER_POINTER (DECL_NAME (field)));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Return 1 if an assignment to a FINAL is attempted in a non suitable
|
||||
context. */
|
||||
|
||||
@ -12069,27 +12350,52 @@ static int
|
||||
check_final_assignment (lvalue, wfl)
|
||||
tree lvalue, wfl;
|
||||
{
|
||||
if (TREE_CODE (lvalue) == COMPOUND_EXPR
|
||||
if (TREE_CODE (lvalue) != COMPONENT_REF && !JDECL_P (lvalue))
|
||||
return 0;
|
||||
|
||||
if (TREE_CODE (lvalue) == COMPONENT_REF
|
||||
&& JDECL_P (TREE_OPERAND (lvalue, 1)))
|
||||
lvalue = TREE_OPERAND (lvalue, 1);
|
||||
|
||||
/* When generating class files, references to the `length' field
|
||||
look a bit different. */
|
||||
if ((flag_emit_class_files
|
||||
&& TREE_CODE (lvalue) == COMPONENT_REF
|
||||
&& TYPE_ARRAY_P (TREE_TYPE (TREE_OPERAND (lvalue, 0)))
|
||||
&& FIELD_FINAL (TREE_OPERAND (lvalue, 1)))
|
||||
|| (TREE_CODE (lvalue) == FIELD_DECL
|
||||
&& FIELD_FINAL (lvalue)
|
||||
&& !DECL_CLINIT_P (current_function_decl)
|
||||
&& !DECL_FINIT_P (current_function_decl)))
|
||||
if (!FIELD_FINAL (lvalue))
|
||||
return 0;
|
||||
|
||||
/* Now the logic. We can modify a final VARIABLE:
|
||||
1) in finit$, (its declaration was followed by an initialization,)
|
||||
2) consistently in each natural ctor, if it wasn't initialized in
|
||||
finit$ or once in <clinit>. In any other cases, an error should be
|
||||
reported. */
|
||||
if (DECL_FINIT_P (current_function_decl))
|
||||
{
|
||||
parse_error_context
|
||||
(wfl, "Can't assign a value to the final variable `%s'",
|
||||
IDENTIFIER_POINTER (EXPR_WFL_NODE (wfl)));
|
||||
return 1;
|
||||
DECL_FIELD_FINAL_IUD (lvalue) = 1;
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
|
||||
if (!DECL_FUNCTION_SYNTHETIC_CTOR (current_function_decl)
|
||||
/* Only if it wasn't given a value upon initialization */
|
||||
&& DECL_LANG_SPECIFIC (lvalue) && !DECL_FIELD_FINAL_IUD (lvalue)
|
||||
/* If it was never assigned a value in this constructor */
|
||||
&& !DECL_FIELD_FINAL_LIIC (lvalue))
|
||||
{
|
||||
/* Turn the locally assigned flag on, it will be checked later
|
||||
on to point out at discrepancies. */
|
||||
DECL_FIELD_FINAL_LIIC (lvalue) = 1;
|
||||
if (DECL_CLINIT_P (current_function_decl))
|
||||
DECL_FIELD_FINAL_IUD (lvalue) = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Other problems should be reported right away. */
|
||||
parse_error_context
|
||||
(wfl, "Can't %sassign a value to the final variable `%s'",
|
||||
(FIELD_STATIC (lvalue) ? "re" : ""),
|
||||
IDENTIFIER_POINTER (EXPR_WFL_NODE (wfl)));
|
||||
|
||||
/* Note that static field can be initialized once and only once. */
|
||||
if (FIELD_STATIC (lvalue))
|
||||
DECL_FIELD_FINAL_IERR (lvalue) = 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Inline references to java.lang.PRIMTYPE.TYPE when accessed in
|
||||
@ -12297,7 +12603,7 @@ patch_assignment (node, wfl_op1, wfl_op2)
|
||||
/* Final locals can be used as case values in switch
|
||||
statement. Prepare them for this eventuality. */
|
||||
if (TREE_CODE (lvalue) == VAR_DECL
|
||||
&& LOCAL_FINAL (lvalue)
|
||||
&& LOCAL_FINAL_P (lvalue)
|
||||
&& TREE_CONSTANT (new_rhs)
|
||||
&& IDENTIFIER_LOCAL_VALUE (DECL_NAME (lvalue))
|
||||
&& JINTEGRAL_TYPE_P (TREE_TYPE (lvalue))
|
||||
@ -14820,7 +15126,7 @@ patch_synchronized_statement (node, wfl_op1)
|
||||
tree expr = java_complete_tree (TREE_OPERAND (node, 0));
|
||||
tree block = TREE_OPERAND (node, 1);
|
||||
|
||||
tree enter, exit, expr_decl, assignment;
|
||||
tree tmp, enter, exit, expr_decl, assignment;
|
||||
|
||||
if (expr == error_mark_node)
|
||||
{
|
||||
@ -14828,6 +15134,10 @@ patch_synchronized_statement (node, wfl_op1)
|
||||
return expr;
|
||||
}
|
||||
|
||||
/* We might be trying to synchronize on a STRING_CST */
|
||||
if ((tmp = patch_string (expr)))
|
||||
expr = tmp;
|
||||
|
||||
/* The TYPE of expr must be a reference type */
|
||||
if (!JREFERENCE_TYPE_P (TREE_TYPE (expr)))
|
||||
{
|
||||
@ -15265,6 +15575,8 @@ fold_constant_for_init (node, context)
|
||||
DECL_INITIAL (node) = NULL_TREE;
|
||||
val = fold_constant_for_init (val, node);
|
||||
DECL_INITIAL (node) = val;
|
||||
if (!val && CLASS_FINAL_VARIABLE_P (node))
|
||||
DECL_FIELD_FINAL_IUD (node) = 0;
|
||||
return val;
|
||||
|
||||
case EXPR_WITH_FILE_LOCATION:
|
||||
|
Loading…
Reference in New Issue
Block a user