[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:
Alexandre Petit-Bianco 2000-12-06 10:55:42 -08:00
parent ee4570050a
commit c7303e411e
6 changed files with 573 additions and 114 deletions

View File

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

View File

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

View File

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

View File

@ -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): */

View File

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

View File

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