X-Git-Url: https://gcc.gnu.org/git/?a=blobdiff_plain;f=gcc%2Fjava%2Fparse.y;h=88c8c31978a54127ba646c606271b4981c8515be;hb=f32c53c2153535de4c9016cd174330be4c9a6027;hp=acf00d9f8d56c4bfe64fb1a0f10e8f9edbbcc617;hpb=c083a819b26a58d8a6caa58e15c5e8821bff01eb;p=gcc.git diff --git a/gcc/java/parse.y b/gcc/java/parse.y index acf00d9f8d56..88c8c31978a5 100644 --- a/gcc/java/parse.y +++ b/gcc/java/parse.y @@ -1,22 +1,23 @@ /* Source code parsing and tree node generation for the GNU compiler for the Java(TM) language. - Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003 + Free Software Foundation, Inc. Contributed by Alexandre Petit-Bianco (apbianco@cygnus.com) -This file is part of GNU CC. +This file is part of GCC. -GNU CC is free software; you can redistribute it and/or modify +GCC is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. -GNU CC is distributed in the hope that it will be useful, +GCC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to +along with GCC; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. @@ -35,7 +36,7 @@ Language Specification. J. Gosling, B. Joy, G. Steele. Addison Wesley The following modifications were brought to the original grammar: method_body: added the rule '| block SC_TK' -static_initializer: added the rule 'static block SC_TK'. +static_initializer: added the rule 'static block SC_TK'. Note: All the extra rules described above should go away when the empty_statement rule will work. @@ -48,9 +49,12 @@ definitions and other extensions. */ %{ #include "config.h" #include "system.h" +#include "coretypes.h" +#include "tm.h" #include #include "tree.h" #include "rtl.h" +#include "real.h" #include "obstack.h" #include "toplev.h" #include "flags.h" @@ -65,287 +69,277 @@ definitions and other extensions. */ #include "function.h" #include "except.h" #include "ggc.h" - -#ifndef DIR_SEPARATOR -#define DIR_SEPARATOR '/' -#endif +#include "debug.h" +#include "tree-inline.h" /* Local function prototypes */ -static char *java_accstring_lookup PARAMS ((int)); -static void classitf_redefinition_error PARAMS ((const char *,tree, tree, tree)); -static void variable_redefinition_error PARAMS ((tree, tree, tree, int)); -static tree create_class PARAMS ((int, tree, tree, tree)); -static tree create_interface PARAMS ((int, tree, tree)); -static void end_class_declaration PARAMS ((int)); -static tree find_field PARAMS ((tree, tree)); -static tree lookup_field_wrapper PARAMS ((tree, tree)); -static int duplicate_declaration_error_p PARAMS ((tree, tree, tree)); -static void register_fields PARAMS ((int, tree, tree)); -static tree parser_qualified_classname PARAMS ((tree)); -static int parser_check_super PARAMS ((tree, tree, tree)); -static int parser_check_super_interface PARAMS ((tree, tree, tree)); -static void check_modifiers_consistency PARAMS ((int)); -static tree lookup_cl PARAMS ((tree)); -static tree lookup_java_method2 PARAMS ((tree, tree, int)); -static tree method_header PARAMS ((int, tree, tree, tree)); -static void fix_method_argument_names PARAMS ((tree ,tree)); -static tree method_declarator PARAMS ((tree, tree)); -static void parse_warning_context PARAMS ((tree cl, const char *msg, ...)) +static char *java_accstring_lookup (int); +static void classitf_redefinition_error (const char *,tree, tree, tree); +static void variable_redefinition_error (tree, tree, tree, int); +static tree create_class (int, tree, tree, tree); +static tree create_interface (int, tree, tree); +static void end_class_declaration (int); +static tree find_field (tree, tree); +static tree lookup_field_wrapper (tree, tree); +static int duplicate_declaration_error_p (tree, tree, tree); +static void register_fields (int, tree, tree); +static tree parser_qualified_classname (tree); +static int parser_check_super (tree, tree, tree); +static int parser_check_super_interface (tree, tree, tree); +static void check_modifiers_consistency (int); +static tree lookup_cl (tree); +static tree lookup_java_method2 (tree, tree, int); +static tree method_header (int, tree, tree, tree); +static void fix_method_argument_names (tree ,tree); +static tree method_declarator (tree, tree); +static void parse_warning_context (tree cl, const char *msg, ...) ATTRIBUTE_PRINTF_2; -static void issue_warning_error_from_context PARAMS ((tree, const char *msg, va_list)) +static void issue_warning_error_from_context (tree, const char *msg, va_list) ATTRIBUTE_PRINTF (2, 0); -static void parse_ctor_invocation_error PARAMS ((void)); -static tree parse_jdk1_1_error PARAMS ((const char *)); -static void complete_class_report_errors PARAMS ((jdep *)); -static int process_imports PARAMS ((void)); -static void read_import_dir PARAMS ((tree)); -static int find_in_imports_on_demand PARAMS ((tree, tree)); -static void find_in_imports PARAMS ((tree, tree)); -static void check_inner_class_access PARAMS ((tree, tree, tree)); -static int check_pkg_class_access PARAMS ((tree, tree, bool)); -static void register_package PARAMS ((tree)); -static tree resolve_package PARAMS ((tree, tree *)); -static tree lookup_package_type PARAMS ((const char *, int)); -static tree resolve_class PARAMS ((tree, tree, tree, tree)); -static void declare_local_variables PARAMS ((int, tree, tree)); -static void source_start_java_method PARAMS ((tree)); -static void source_end_java_method PARAMS ((void)); -static tree find_name_in_single_imports PARAMS ((tree)); -static void check_abstract_method_header PARAMS ((tree)); -static tree lookup_java_interface_method2 PARAMS ((tree, tree)); -static tree resolve_expression_name PARAMS ((tree, tree *)); -static tree maybe_create_class_interface_decl PARAMS ((tree, tree, tree, tree)); -static int check_class_interface_creation PARAMS ((int, int, tree, - tree, tree, tree)); -static tree patch_method_invocation PARAMS ((tree, tree, tree, int, - int *, tree *)); -static int breakdown_qualified PARAMS ((tree *, tree *, tree)); -static int in_same_package PARAMS ((tree, tree)); -static tree resolve_and_layout PARAMS ((tree, tree)); -static tree qualify_and_find PARAMS ((tree, tree, tree)); -static tree resolve_no_layout PARAMS ((tree, tree)); -static int invocation_mode PARAMS ((tree, int)); -static tree find_applicable_accessible_methods_list PARAMS ((int, tree, - tree, tree)); -static void search_applicable_methods_list PARAMS ((int, tree, tree, tree, - tree *, tree *)); -static tree find_most_specific_methods_list PARAMS ((tree)); -static int argument_types_convertible PARAMS ((tree, tree)); -static tree patch_invoke PARAMS ((tree, tree, tree)); -static int maybe_use_access_method PARAMS ((int, tree *, tree *)); -static tree lookup_method_invoke PARAMS ((int, tree, tree, tree, tree)); -static tree register_incomplete_type PARAMS ((int, tree, tree, tree)); -static tree check_inner_circular_reference PARAMS ((tree, tree)); -static tree check_circular_reference PARAMS ((tree)); -static tree obtain_incomplete_type PARAMS ((tree)); -static tree java_complete_lhs PARAMS ((tree)); -static tree java_complete_tree PARAMS ((tree)); -static tree maybe_generate_pre_expand_clinit PARAMS ((tree)); -static int analyze_clinit_body PARAMS ((tree, tree)); -static int maybe_yank_clinit PARAMS ((tree)); -static void start_complete_expand_method PARAMS ((tree)); -static void java_complete_expand_method PARAMS ((tree)); -static void java_expand_method_bodies PARAMS ((tree)); -static int unresolved_type_p PARAMS ((tree, tree *)); -static void create_jdep_list PARAMS ((struct parser_ctxt *)); -static tree build_expr_block PARAMS ((tree, tree)); -static tree enter_block PARAMS ((void)); -static tree exit_block PARAMS ((void)); -static tree lookup_name_in_blocks PARAMS ((tree)); -static void maybe_absorb_scoping_blocks PARAMS ((void)); -static tree build_method_invocation PARAMS ((tree, tree)); -static tree build_new_invocation PARAMS ((tree, tree)); -static tree build_assignment PARAMS ((int, int, tree, tree)); -static tree build_binop PARAMS ((enum tree_code, int, tree, tree)); -static tree patch_assignment PARAMS ((tree, tree)); -static tree patch_binop PARAMS ((tree, tree, tree)); -static tree build_unaryop PARAMS ((int, int, tree)); -static tree build_incdec PARAMS ((int, int, tree, int)); -static tree patch_unaryop PARAMS ((tree, tree)); -static tree build_cast PARAMS ((int, tree, tree)); -static tree build_null_of_type PARAMS ((tree)); -static tree patch_cast PARAMS ((tree, tree)); -static int valid_ref_assignconv_cast_p PARAMS ((tree, tree, int)); -static int valid_builtin_assignconv_identity_widening_p PARAMS ((tree, tree)); -static int valid_cast_to_p PARAMS ((tree, tree)); -static int valid_method_invocation_conversion_p PARAMS ((tree, tree)); -static tree try_builtin_assignconv PARAMS ((tree, tree, tree)); -static tree try_reference_assignconv PARAMS ((tree, tree)); -static tree build_unresolved_array_type PARAMS ((tree)); -static int build_type_name_from_array_name PARAMS ((tree, tree *)); -static tree build_array_from_name PARAMS ((tree, tree, tree, tree *)); -static tree build_array_ref PARAMS ((int, tree, tree)); -static tree patch_array_ref PARAMS ((tree)); -static tree make_qualified_name PARAMS ((tree, tree, int)); -static tree merge_qualified_name PARAMS ((tree, tree)); -static tree make_qualified_primary PARAMS ((tree, tree, int)); -static int resolve_qualified_expression_name PARAMS ((tree, tree *, - tree *, tree *)); -static void qualify_ambiguous_name PARAMS ((tree)); -static tree resolve_field_access PARAMS ((tree, tree *, tree *)); -static tree build_newarray_node PARAMS ((tree, tree, int)); -static tree patch_newarray PARAMS ((tree)); -static tree resolve_type_during_patch PARAMS ((tree)); -static tree build_this PARAMS ((int)); -static tree build_wfl_wrap PARAMS ((tree, int)); -static tree build_return PARAMS ((int, tree)); -static tree patch_return PARAMS ((tree)); -static tree maybe_access_field PARAMS ((tree, tree, tree)); -static int complete_function_arguments PARAMS ((tree)); -static int check_for_static_method_reference PARAMS ((tree, tree, tree, - tree, tree)); -static int not_accessible_p PARAMS ((tree, tree, tree, int)); -static void check_deprecation PARAMS ((tree, tree)); -static int class_in_current_package PARAMS ((tree)); -static tree build_if_else_statement PARAMS ((int, tree, tree, tree)); -static tree patch_if_else_statement PARAMS ((tree)); -static tree add_stmt_to_compound PARAMS ((tree, tree, tree)); -static tree add_stmt_to_block PARAMS ((tree, tree, tree)); -static tree patch_exit_expr PARAMS ((tree)); -static tree build_labeled_block PARAMS ((int, tree)); -static tree finish_labeled_statement PARAMS ((tree, tree)); -static tree build_bc_statement PARAMS ((int, int, tree)); -static tree patch_bc_statement PARAMS ((tree)); -static tree patch_loop_statement PARAMS ((tree)); -static tree build_new_loop PARAMS ((tree)); -static tree build_loop_body PARAMS ((int, tree, int)); -static tree finish_loop_body PARAMS ((int, tree, tree, int)); -static tree build_debugable_stmt PARAMS ((int, tree)); -static tree finish_for_loop PARAMS ((int, tree, tree, tree)); -static tree patch_switch_statement PARAMS ((tree)); -static tree string_constant_concatenation PARAMS ((tree, tree)); -static tree build_string_concatenation PARAMS ((tree, tree)); -static tree patch_string_cst PARAMS ((tree)); -static tree patch_string PARAMS ((tree)); -static tree encapsulate_with_try_catch PARAMS ((int, tree, tree, tree)); -static tree build_try_statement PARAMS ((int, tree, tree)); -static tree build_try_finally_statement PARAMS ((int, tree, tree)); -static tree patch_try_statement PARAMS ((tree)); -static tree patch_synchronized_statement PARAMS ((tree, tree)); -static tree patch_throw_statement PARAMS ((tree, tree)); -static void check_thrown_exceptions PARAMS ((int, tree)); -static int check_thrown_exceptions_do PARAMS ((tree)); -static void purge_unchecked_exceptions PARAMS ((tree)); -static bool ctors_unchecked_throws_clause_p PARAMS ((tree)); -static void check_throws_clauses PARAMS ((tree, tree, tree)); -static void finish_method_declaration PARAMS ((tree)); -static tree build_super_invocation PARAMS ((tree)); -static int verify_constructor_circularity PARAMS ((tree, tree)); -static char *constructor_circularity_msg PARAMS ((tree, tree)); -static tree build_this_super_qualified_invocation PARAMS ((int, tree, tree, - int, int)); -static const char *get_printable_method_name PARAMS ((tree)); -static tree patch_conditional_expr PARAMS ((tree, tree, tree)); -static tree generate_finit PARAMS ((tree)); -static tree generate_instinit PARAMS ((tree)); -static tree build_instinit_invocation PARAMS ((tree)); -static void fix_constructors PARAMS ((tree)); -static tree build_alias_initializer_parameter_list PARAMS ((int, tree, - tree, int *)); -static void craft_constructor PARAMS ((tree, tree)); -static int verify_constructor_super PARAMS ((tree)); -static tree create_artificial_method PARAMS ((tree, int, tree, tree, tree)); -static void start_artificial_method_body PARAMS ((tree)); -static void end_artificial_method_body PARAMS ((tree)); -static int check_method_redefinition PARAMS ((tree, tree)); -static int check_method_types_complete PARAMS ((tree)); -static void java_check_regular_methods PARAMS ((tree)); -static void java_check_abstract_methods PARAMS ((tree)); -static void unreachable_stmt_error PARAMS ((tree)); -static tree find_expr_with_wfl PARAMS ((tree)); -static void missing_return_error PARAMS ((tree)); -static tree build_new_array_init PARAMS ((int, tree)); -static tree patch_new_array_init PARAMS ((tree, tree)); -static tree maybe_build_array_element_wfl PARAMS ((tree)); -static int array_constructor_check_entry PARAMS ((tree, tree)); -static const char *purify_type_name PARAMS ((const char *)); -static tree fold_constant_for_init PARAMS ((tree, tree)); -static tree strip_out_static_field_access_decl PARAMS ((tree)); -static jdeplist *reverse_jdep_list PARAMS ((struct parser_ctxt *)); -static void static_ref_err PARAMS ((tree, tree, tree)); -static void parser_add_interface PARAMS ((tree, tree, tree)); -static void add_superinterfaces PARAMS ((tree, tree)); -static tree jdep_resolve_class PARAMS ((jdep *)); -static int note_possible_classname PARAMS ((const char *, int)); -static void java_complete_expand_classes PARAMS ((void)); -static void java_complete_expand_class PARAMS ((tree)); -static void java_complete_expand_methods PARAMS ((tree)); -static tree cut_identifier_in_qualified PARAMS ((tree)); -static tree java_stabilize_reference PARAMS ((tree)); -static tree do_unary_numeric_promotion PARAMS ((tree)); -static char * operator_string PARAMS ((tree)); -static tree do_merge_string_cste PARAMS ((tree, const char *, int, int)); -static tree merge_string_cste PARAMS ((tree, tree, int)); -static tree java_refold PARAMS ((tree)); -static int java_decl_equiv PARAMS ((tree, tree)); -static int binop_compound_p PARAMS ((enum tree_code)); -static tree search_loop PARAMS ((tree)); -static int labeled_block_contains_loop_p PARAMS ((tree, tree)); -static int check_abstract_method_definitions PARAMS ((int, tree, tree)); -static void java_check_abstract_method_definitions PARAMS ((tree)); -static void java_debug_context_do PARAMS ((int)); -static void java_parser_context_push_initialized_field PARAMS ((void)); -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 *)); +static void parse_ctor_invocation_error (void); +static tree parse_jdk1_1_error (const char *); +static void complete_class_report_errors (jdep *); +static int process_imports (void); +static void read_import_dir (tree); +static int find_in_imports_on_demand (tree, tree); +static void find_in_imports (tree, tree); +static void check_inner_class_access (tree, tree, tree); +static int check_pkg_class_access (tree, tree, bool); +static void register_package (tree); +static tree resolve_package (tree, tree *, tree *); +static tree resolve_class (tree, tree, tree, tree); +static void declare_local_variables (int, tree, tree); +static void dump_java_tree (enum tree_dump_index, tree); +static void source_start_java_method (tree); +static void source_end_java_method (void); +static tree find_name_in_single_imports (tree); +static void check_abstract_method_header (tree); +static tree lookup_java_interface_method2 (tree, tree); +static tree resolve_expression_name (tree, tree *); +static tree maybe_create_class_interface_decl (tree, tree, tree, tree); +static int check_class_interface_creation (int, int, tree, tree, tree, tree); +static tree patch_method_invocation (tree, tree, tree, int, int *, tree *); +static int breakdown_qualified (tree *, tree *, tree); +static int in_same_package (tree, tree); +static tree resolve_and_layout (tree, tree); +static tree qualify_and_find (tree, tree, tree); +static tree resolve_no_layout (tree, tree); +static int invocation_mode (tree, int); +static tree find_applicable_accessible_methods_list (int, tree, tree, tree); +static void search_applicable_methods_list (int, tree, tree, tree, tree *, tree *); +static tree find_most_specific_methods_list (tree); +static int argument_types_convertible (tree, tree); +static tree patch_invoke (tree, tree, tree); +static int maybe_use_access_method (int, tree *, tree *); +static tree lookup_method_invoke (int, tree, tree, tree, tree); +static tree register_incomplete_type (int, tree, tree, tree); +static tree check_inner_circular_reference (tree, tree); +static tree check_circular_reference (tree); +static tree obtain_incomplete_type (tree); +static tree java_complete_lhs (tree); +static tree java_complete_tree (tree); +static tree maybe_generate_pre_expand_clinit (tree); +static int analyze_clinit_body (tree, tree); +static int maybe_yank_clinit (tree); +static void start_complete_expand_method (tree); +static void java_complete_expand_method (tree); +static void java_expand_method_bodies (tree); +static int unresolved_type_p (tree, tree *); +static void create_jdep_list (struct parser_ctxt *); +static tree build_expr_block (tree, tree); +static tree enter_block (void); +static tree exit_block (void); +static tree lookup_name_in_blocks (tree); +static void maybe_absorb_scoping_blocks (void); +static tree build_method_invocation (tree, tree); +static tree build_new_invocation (tree, tree); +static tree build_assignment (int, int, tree, tree); +static tree build_binop (enum tree_code, int, tree, tree); +static tree patch_assignment (tree, tree); +static tree patch_binop (tree, tree, tree); +static tree build_unaryop (int, int, tree); +static tree build_incdec (int, int, tree, int); +static tree patch_unaryop (tree, tree); +static tree build_cast (int, tree, tree); +static tree build_null_of_type (tree); +static tree patch_cast (tree, tree); +static int valid_ref_assignconv_cast_p (tree, tree, int); +static int valid_builtin_assignconv_identity_widening_p (tree, tree); +static int valid_cast_to_p (tree, tree); +static int valid_method_invocation_conversion_p (tree, tree); +static tree try_builtin_assignconv (tree, tree, tree); +static tree try_reference_assignconv (tree, tree); +static tree build_unresolved_array_type (tree); +static int build_type_name_from_array_name (tree, tree *); +static tree build_array_from_name (tree, tree, tree, tree *); +static tree build_array_ref (int, tree, tree); +static tree patch_array_ref (tree); +static tree make_qualified_name (tree, tree, int); +static tree merge_qualified_name (tree, tree); +static tree make_qualified_primary (tree, tree, int); +static int resolve_qualified_expression_name (tree, tree *, tree *, tree *); +static void qualify_ambiguous_name (tree); +static tree resolve_field_access (tree, tree *, tree *); +static tree build_newarray_node (tree, tree, int); +static tree patch_newarray (tree); +static tree resolve_type_during_patch (tree); +static tree build_this (int); +static tree build_wfl_wrap (tree, int); +static tree build_return (int, tree); +static tree patch_return (tree); +static tree maybe_access_field (tree, tree, tree); +static int complete_function_arguments (tree); +static int check_for_static_method_reference (tree, tree, tree, tree, tree); +static int not_accessible_p (tree, tree, tree, int); +static void check_deprecation (tree, tree); +static int class_in_current_package (tree); +static tree build_if_else_statement (int, tree, tree, tree); +static tree patch_if_else_statement (tree); +static tree add_stmt_to_compound (tree, tree, tree); +static tree add_stmt_to_block (tree, tree, tree); +static tree patch_exit_expr (tree); +static tree build_labeled_block (int, tree); +static tree finish_labeled_statement (tree, tree); +static tree build_bc_statement (int, int, tree); +static tree patch_bc_statement (tree); +static tree patch_loop_statement (tree); +static tree build_new_loop (tree); +static tree build_loop_body (int, tree, int); +static tree finish_loop_body (int, tree, tree, int); +static tree build_debugable_stmt (int, tree); +static tree finish_for_loop (int, tree, tree, tree); +static tree patch_switch_statement (tree); +static tree string_constant_concatenation (tree, tree); +static tree build_string_concatenation (tree, tree); +static tree patch_string_cst (tree); +static tree patch_string (tree); +static tree encapsulate_with_try_catch (int, tree, tree, tree); +static tree build_assertion (int, tree, tree); +static tree build_try_statement (int, tree, tree); +static tree build_try_finally_statement (int, tree, tree); +static tree patch_try_statement (tree); +static tree patch_synchronized_statement (tree, tree); +static tree patch_throw_statement (tree, tree); +static void check_thrown_exceptions (int, tree); +static int check_thrown_exceptions_do (tree); +static void purge_unchecked_exceptions (tree); +static bool ctors_unchecked_throws_clause_p (tree); +static void check_throws_clauses (tree, tree, tree); +static void finish_method_declaration (tree); +static tree build_super_invocation (tree); +static int verify_constructor_circularity (tree, tree); +static char *constructor_circularity_msg (tree, tree); +static tree build_this_super_qualified_invocation (int, tree, tree, int, int); +static const char *get_printable_method_name (tree); +static tree patch_conditional_expr (tree, tree, tree); +static tree generate_finit (tree); +static tree generate_instinit (tree); +static tree build_instinit_invocation (tree); +static void fix_constructors (tree); +static tree build_alias_initializer_parameter_list (int, tree, tree, int *); +static tree craft_constructor (tree, tree); +static int verify_constructor_super (tree); +static tree create_artificial_method (tree, int, tree, tree, tree); +static void start_artificial_method_body (tree); +static void end_artificial_method_body (tree); +static int check_method_redefinition (tree, tree); +static int check_method_types_complete (tree); +static void java_check_regular_methods (tree); +static void java_check_abstract_methods (tree); +static void unreachable_stmt_error (tree); +static tree find_expr_with_wfl (tree); +static void missing_return_error (tree); +static tree build_new_array_init (int, tree); +static tree patch_new_array_init (tree, tree); +static tree maybe_build_array_element_wfl (tree); +static int array_constructor_check_entry (tree, tree); +static const char *purify_type_name (const char *); +static tree fold_constant_for_init (tree, tree); +static tree strip_out_static_field_access_decl (tree); +static jdeplist *reverse_jdep_list (struct parser_ctxt *); +static void static_ref_err (tree, tree, tree); +static void parser_add_interface (tree, tree, tree); +static void add_superinterfaces (tree, tree); +static tree jdep_resolve_class (jdep *); +static int note_possible_classname (const char *, int); +static void java_complete_expand_classes (void); +static void java_complete_expand_class (tree); +static void java_complete_expand_methods (tree); +static tree cut_identifier_in_qualified (tree); +static tree java_stabilize_reference (tree); +static tree do_unary_numeric_promotion (tree); +static char * operator_string (tree); +static tree do_merge_string_cste (tree, const char *, int, int); +static tree merge_string_cste (tree, tree, int); +static tree java_refold (tree); +static int java_decl_equiv (tree, tree); +static int binop_compound_p (enum tree_code); +static tree search_loop (tree); +static int labeled_block_contains_loop_p (tree, tree); +static int check_abstract_method_definitions (int, tree, tree); +static void java_check_abstract_method_definitions (tree); +static void java_debug_context_do (int); +static void java_parser_context_push_initialized_field (void); +static void java_parser_context_pop_initialized_field (void); +static tree reorder_static_initialized (tree); +static void java_parser_context_suspend (void); +static void java_parser_context_resume (void); +static int pop_current_osb (struct parser_ctxt *); /* JDK 1.1 work. FIXME */ -static tree maybe_make_nested_class_name PARAMS ((tree)); -static void make_nested_class_name PARAMS ((tree)); -static void set_nested_class_simple_name_value PARAMS ((tree, int)); -static void link_nested_class_to_enclosing PARAMS ((void)); -static tree resolve_inner_class PARAMS ((struct hash_table *, tree, tree *, - tree *, tree)); -static tree find_as_inner_class PARAMS ((tree, tree, tree)); -static tree find_as_inner_class_do PARAMS ((tree, tree)); -static int check_inner_class_redefinition PARAMS ((tree, tree)); - -static tree build_thisn_assign PARAMS ((void)); -static tree build_current_thisn PARAMS ((tree)); -static tree build_access_to_thisn PARAMS ((tree, tree, int)); -static tree maybe_build_thisn_access_method PARAMS ((tree)); - -static tree build_outer_field_access PARAMS ((tree, tree)); -static tree build_outer_field_access_methods PARAMS ((tree)); -static tree build_outer_field_access_expr PARAMS ((int, tree, tree, - tree, tree)); -static tree build_outer_method_access_method PARAMS ((tree)); -static tree build_new_access_id PARAMS ((void)); -static tree build_outer_field_access_method PARAMS ((tree, tree, tree, - tree, tree)); - -static int outer_field_access_p PARAMS ((tree, tree)); -static int outer_field_expanded_access_p PARAMS ((tree, tree *, - tree *, tree *)); -static tree outer_field_access_fix PARAMS ((tree, tree, tree)); -static tree build_incomplete_class_ref PARAMS ((int, tree)); -static tree patch_incomplete_class_ref PARAMS ((tree)); -static tree create_anonymous_class PARAMS ((int, tree)); -static void patch_anonymous_class PARAMS ((tree, tree, tree)); -static void add_inner_class_fields PARAMS ((tree, tree)); - -static tree build_dot_class_method PARAMS ((tree)); -static tree build_dot_class_method_invocation PARAMS ((tree)); -static void create_new_parser_context PARAMS ((int)); -static void mark_parser_ctxt PARAMS ((void *)); -static tree maybe_build_class_init_for_field PARAMS ((tree, tree)); - -static bool attach_init_test_initialization_flags PARAMS ((struct hash_entry *, - PTR)); -static bool emit_test_initialization PARAMS ((struct hash_entry *, PTR)); +static tree maybe_make_nested_class_name (tree); +static int make_nested_class_name (tree); +static void set_nested_class_simple_name_value (tree, int); +static void link_nested_class_to_enclosing (void); +static tree resolve_inner_class (htab_t, tree, tree *, tree *, tree); +static tree find_as_inner_class (tree, tree, tree); +static tree find_as_inner_class_do (tree, tree); +static int check_inner_class_redefinition (tree, tree); + +static tree build_thisn_assign (void); +static tree build_current_thisn (tree); +static tree build_access_to_thisn (tree, tree, int); +static tree maybe_build_thisn_access_method (tree); + +static tree build_outer_field_access (tree, tree); +static tree build_outer_field_access_methods (tree); +static tree build_outer_field_access_expr (int, tree, tree, + tree, tree); +static tree build_outer_method_access_method (tree); +static tree build_new_access_id (void); +static tree build_outer_field_access_method (tree, tree, tree, + tree, tree); + +static int outer_field_access_p (tree, tree); +static int outer_field_expanded_access_p (tree, tree *, + tree *, tree *); +static tree outer_field_access_fix (tree, tree, tree); +static tree build_incomplete_class_ref (int, tree); +static tree patch_incomplete_class_ref (tree); +static tree create_anonymous_class (int, tree); +static void patch_anonymous_class (tree, tree, tree); +static void add_inner_class_fields (tree, tree); + +static tree build_dot_class_method (tree); +static tree build_dot_class_method_invocation (tree); +static void create_new_parser_context (int); +static tree maybe_build_class_init_for_field (tree, tree); + +static int attach_init_test_initialization_flags (void **, void *); +static int emit_test_initialization (void **, void *); + +static char *string_convert_int_cst (tree); /* Number of error found so far. */ -int java_error_count; +int java_error_count; /* Number of warning found so far. */ int java_warning_count; /* Tell when not to fold, when doing xrefs */ int do_not_fold; /* Cyclic inheritance report, as it can be set by layout_class */ const char *cyclic_inheritance_report; - + /* The current parser context */ struct parser_ctxt *ctxp; @@ -357,10 +351,10 @@ struct parser_ctxt *ctxp_for_generation = NULL; covers both integral/floating point division. The code is changed once the type of both operator is worked out. */ -static const enum tree_code binop_lookup[19] = - { +static const enum tree_code binop_lookup[19] = + { PLUS_EXPR, MINUS_EXPR, MULT_EXPR, RDIV_EXPR, TRUNC_MOD_EXPR, - LSHIFT_EXPR, RSHIFT_EXPR, URSHIFT_EXPR, + LSHIFT_EXPR, RSHIFT_EXPR, URSHIFT_EXPR, BIT_AND_EXPR, BIT_XOR_EXPR, BIT_IOR_EXPR, TRUTH_ANDIF_EXPR, TRUTH_ORIF_EXPR, EQ_EXPR, NE_EXPR, GT_EXPR, GE_EXPR, LT_EXPR, LE_EXPR, @@ -373,54 +367,52 @@ static const enum tree_code binop_lookup[19] = #define BINOP_COMPOUND_CANDIDATES 11 /* The "$L" identifier we use to create labels. */ -static tree label_id = NULL_TREE; +static GTY(()) tree label_id; /* The "StringBuffer" identifier used for the String `+' operator. */ -static tree wfl_string_buffer = NULL_TREE; +static GTY(()) tree wfl_string_buffer; /* The "append" identifier used for String `+' operator. */ -static tree wfl_append = NULL_TREE; +static GTY(()) tree wfl_append; /* The "toString" identifier used for String `+' operator. */ -static tree wfl_to_string = NULL_TREE; +static GTY(()) tree wfl_to_string; /* The "java.lang" import qualified name. */ -static tree java_lang_id = NULL_TREE; +static GTY(()) tree java_lang_id; /* The generated `inst$' identifier used for generated enclosing instance/field access functions. */ -static tree inst_id = NULL_TREE; - -/* The "java.lang.Cloneable" qualified name. */ -static tree java_lang_cloneable = NULL_TREE; - -/* The "java.io.Serializable" qualified name. */ -static tree java_io_serializable = NULL_TREE; +static GTY(()) tree inst_id; /* Context and flag for static blocks */ -static tree current_static_block = NULL_TREE; +static GTY(()) tree current_static_block; /* The generated `write_parm_value$' identifier. */ -static tree wpv_id; +static GTY(()) tree wpv_id; /* The list of all packages we've seen so far */ -static tree package_list = NULL_TREE; - +static GTY(()) tree package_list; + /* Hold THIS for the scope of the current method decl. */ -static tree current_this; +static GTY(()) tree current_this; /* Hold a list of catch clauses list. The first element of this list is the list of the catch clauses of the currently analysed try block. */ -static tree currently_caught_type_list; +static GTY(()) tree currently_caught_type_list; /* This holds a linked list of all the case labels for the current switch statement. It is only used when checking to see if there are duplicate labels. FIXME: probably this should just be attached to the switch itself; then it could be referenced via `ctxp->current_loop'. */ -static tree case_label_list; +static GTY(()) tree case_label_list; + +/* Anonymous class counter. Will be reset to 1 every time a non + anonymous class gets created. */ +static int anonymous_class_counter = 1; -static tree src_parse_roots[1] = { NULL_TREE }; +static GTY(()) tree src_parse_roots[1]; /* All classes seen from source code */ #define gclass_list src_parse_roots[0] @@ -433,8 +425,8 @@ static tree src_parse_roots[1] = { NULL_TREE }; #define check_modifiers(__message, __value, __mask) do { \ if ((__value) & ~(__mask)) \ { \ - int i, remainder = (__value) & ~(__mask); \ - for (i = 0; i <= 10; i++) \ + size_t i, remainder = (__value) & ~(__mask); \ + for (i = 0; i < ARRAY_SIZE (ctxp->modifier_ctx); i++) \ if ((1 << i) & remainder) \ parse_error_context (ctxp->modifier_ctx [i], (__message), \ java_accstring_lookup (1 << i)); \ @@ -465,13 +457,13 @@ static tree src_parse_roots[1] = { NULL_TREE }; %token PLUS_TK MINUS_TK MULT_TK DIV_TK REM_TK %token LS_TK SRS_TK ZRS_TK %token AND_TK XOR_TK OR_TK -%token BOOL_AND_TK BOOL_OR_TK +%token BOOL_AND_TK BOOL_OR_TK %token EQ_TK NEQ_TK GT_TK GTE_TK LT_TK LTE_TK /* This maps to the same binop_lookup entry than the token above */ %token PLUS_ASSIGN_TK MINUS_ASSIGN_TK MULT_ASSIGN_TK DIV_ASSIGN_TK -%token REM_ASSIGN_TK +%token REM_ASSIGN_TK %token LS_ASSIGN_TK SRS_ASSIGN_TK ZRS_ASSIGN_TK %token AND_ASSIGN_TK XOR_ASSIGN_TK OR_ASSIGN_TK @@ -481,8 +473,8 @@ static tree src_parse_roots[1] = { NULL_TREE }; %token PUBLIC_TK PRIVATE_TK PROTECTED_TK %token STATIC_TK FINAL_TK SYNCHRONIZED_TK %token VOLATILE_TK TRANSIENT_TK NATIVE_TK -%token PAD_TK ABSTRACT_TK MODIFIER_TK -%token STRICT_TK +%token PAD_TK ABSTRACT_TK STRICT_TK +%token MODIFIER_TK /* Keep those two in order, too */ %token DECR_TK INCR_TK @@ -491,7 +483,7 @@ static tree src_parse_roots[1] = { NULL_TREE }; %token DEFAULT_TK IF_TK THROW_TK %token BOOLEAN_TK DO_TK IMPLEMENTS_TK -%token THROWS_TK BREAK_TK IMPORT_TK +%token THROWS_TK BREAK_TK IMPORT_TK %token ELSE_TK INSTANCEOF_TK RETURN_TK %token VOID_TK CATCH_TK INTERFACE_TK %token CASE_TK EXTENDS_TK FINALLY_TK @@ -499,6 +491,7 @@ static tree src_parse_roots[1] = { NULL_TREE }; %token SWITCH_TK CONST_TK TRY_TK %token FOR_TK NEW_TK CONTINUE_TK %token GOTO_TK PACKAGE_TK THIS_TK +%token ASSERT_TK %token BYTE_TK SHORT_TK INT_TK LONG_TK %token CHAR_TK INTEGRAL_TK @@ -522,12 +515,11 @@ static tree src_parse_roots[1] = { NULL_TREE }; %type type_declaration compilation_unit field_declaration method_declaration extends_interfaces interfaces interface_type_list - class_member_declaration - import_declarations package_declaration + import_declarations package_declaration type_declarations interface_body interface_member_declaration constant_declaration interface_member_declarations interface_type - abstract_method_declaration interface_type_list + abstract_method_declaration %type class_body_declaration class_member_declaration static_initializer constructor_declaration block %type class_body_declarations constructor_header @@ -552,41 +544,42 @@ static tree src_parse_roots[1] = { NULL_TREE }; array_creation_expression array_type class_instance_creation_expression field_access method_invocation array_access something_dot_new - argument_list postfix_expression while_expression + argument_list postfix_expression while_expression post_increment_expression post_decrement_expression unary_expression_not_plus_minus unary_expression pre_increment_expression pre_decrement_expression - unary_expression_not_plus_minus cast_expression + cast_expression multiplicative_expression additive_expression - shift_expression relational_expression - equality_expression and_expression + shift_expression relational_expression + equality_expression and_expression exclusive_or_expression inclusive_or_expression conditional_and_expression conditional_or_expression conditional_expression assignment_expression left_hand_side assignment for_header for_begin constant_expression do_statement_begin empty_statement switch_statement synchronized_statement throw_statement - try_statement switch_expression switch_block + try_statement assert_statement + switch_expression switch_block catches catch_clause catch_clause_parameter finally anonymous_class_creation trap_overflow_corner_case %type return_statement break_statement continue_statement -%type ASSIGN_TK MULT_ASSIGN_TK DIV_ASSIGN_TK +%type ASSIGN_TK MULT_ASSIGN_TK DIV_ASSIGN_TK %type REM_ASSIGN_TK PLUS_ASSIGN_TK MINUS_ASSIGN_TK %type LS_ASSIGN_TK SRS_ASSIGN_TK ZRS_ASSIGN_TK %type AND_ASSIGN_TK XOR_ASSIGN_TK OR_ASSIGN_TK %type ASSIGN_ANY_TK assignment_operator -%token EQ_TK GTE_TK ZRS_TK SRS_TK GT_TK LTE_TK LS_TK +%token EQ_TK GTE_TK ZRS_TK SRS_TK GT_TK LTE_TK LS_TK %token BOOL_AND_TK AND_TK BOOL_OR_TK OR_TK INCR_TK PLUS_TK %token DECR_TK MINUS_TK MULT_TK DIV_TK XOR_TK REM_TK NEQ_TK %token NEG_TK REL_QM_TK REL_CL_TK NOT_TK LT_TK OCB_TK CCB_TK %token OP_TK OSB_TK DOT_TK THROW_TK INSTANCEOF_TK -%type THIS_TK SUPER_TK RETURN_TK BREAK_TK CONTINUE_TK +%type THIS_TK SUPER_TK RETURN_TK BREAK_TK CONTINUE_TK %type CASE_TK DEFAULT_TK TRY_TK CATCH_TK SYNCHRONIZED_TK -%type NEW_TK +%type NEW_TK ASSERT_TK + +%type method_body -%type method_body - %type literal INT_LIT_TK FP_LIT_TK BOOL_LIT_TK CHAR_LIT_TK STRING_LIT_TK NULL_TK VOID_TK @@ -595,7 +588,7 @@ static tree src_parse_roots[1] = { NULL_TREE }; %type formal_parameter_list formal_parameter method_declarator method_header -%type primitive_type reference_type type +%type primitive_type reference_type type BOOLEAN_TK INTEGRAL_TK FP_TK /* Added or modified JDK 1.1 rule types */ @@ -603,32 +596,7 @@ static tree src_parse_roots[1] = { NULL_TREE }; %% /* 19.2 Production from 2.3: The Syntactic Grammar */ -goal: - { - /* Register static variables with the garbage - collector. */ - ggc_add_tree_root (&label_id, 1); - ggc_add_tree_root (&wfl_string_buffer, 1); - ggc_add_tree_root (&wfl_append, 1); - ggc_add_tree_root (&wfl_to_string, 1); - ggc_add_tree_root (&java_lang_id, 1); - ggc_add_tree_root (&inst_id, 1); - ggc_add_tree_root (&java_lang_cloneable, 1); - ggc_add_tree_root (&java_io_serializable, 1); - ggc_add_tree_root (¤t_static_block, 1); - ggc_add_tree_root (&wpv_id, 1); - ggc_add_tree_root (&package_list, 1); - ggc_add_tree_root (¤t_this, 1); - ggc_add_tree_root (¤tly_caught_type_list, 1); - ggc_add_tree_root (&case_label_list, 1); - ggc_add_root (&ctxp, 1, - sizeof (struct parser_ctxt *), - mark_parser_ctxt); - ggc_add_root (&ctxp_for_generation, 1, - sizeof (struct parser_ctxt *), - mark_parser_ctxt); - } - compilation_unit +goal: compilation_unit {} ; @@ -673,7 +641,7 @@ interface_type: array_type: primitive_type dims - { + { int osb = pop_current_osb (ctxp); tree t = build_java_array_type (($1), -1); while (--osb) @@ -681,7 +649,7 @@ array_type: $$ = t; } | name dims - { + { int osb = pop_current_osb (ctxp); tree t = $1; while (osb--) @@ -739,7 +707,7 @@ type_declarations: package_declaration: PACKAGE_TK name SC_TK - { + { ctxp->package = EXPR_WFL_NODE ($2); register_package (ctxp->package); } @@ -773,7 +741,7 @@ single_type_import_declaration: if (err && err != name) parse_error_context ($2, "Ambiguous class: `%s' and `%s'", - IDENTIFIER_POINTER (name), + IDENTIFIER_POINTER (name), IDENTIFIER_POINTER (err)); else REGISTER_IMPORT ($2, last_name); @@ -801,7 +769,7 @@ type_import_on_demand_declaration: if (! it) { read_import_dir ($2); - ctxp->import_demand_list = + ctxp->import_demand_list = chainon (ctxp->import_demand_list, build_tree_list ($2, NULL_TREE)); } @@ -837,7 +805,7 @@ modifiers: { int acc = (1 << $2); if ($$ & acc) - parse_error_context + parse_error_context (ctxp->modifier_ctx [$2], "Modifier `%s' declared twice", java_accstring_lookup (acc)); else @@ -852,20 +820,22 @@ class_declaration: modifiers CLASS_TK identifier super interfaces { create_class ($1, $3, $4, $5); } class_body -| CLASS_TK identifier super interfaces + {;} +| CLASS_TK identifier super interfaces { create_class (0, $2, $3, $4); } class_body + {;} | modifiers CLASS_TK error - {yyerror ("Missing class name"); RECOVER;} + { yyerror ("Missing class name"); RECOVER; } | CLASS_TK error - {yyerror ("Missing class name"); RECOVER;} + { yyerror ("Missing class name"); RECOVER; } | CLASS_TK identifier error { - if (!ctxp->class_err) yyerror ("'{' expected"); + if (!ctxp->class_err) yyerror ("'{' expected"); DRECOVER(class1); } | modifiers CLASS_TK identifier error - {if (!ctxp->class_err) yyerror ("'{' expected"); RECOVER;} + { if (!ctxp->class_err) yyerror ("'{' expected"); RECOVER; } ; super: @@ -885,18 +855,18 @@ interfaces: | IMPLEMENTS_TK error { ctxp->class_err=1; - yyerror ("Missing interface name"); + yyerror ("Missing interface name"); } ; interface_type_list: interface_type - { + { ctxp->interface_number = 1; $$ = build_tree_list ($1, NULL_TREE); } | interface_type_list C_TK interface_type - { + { ctxp->interface_number++; $$ = chainon ($1, build_tree_list ($3, NULL_TREE)); } @@ -906,18 +876,18 @@ interface_type_list: class_body: OCB_TK CCB_TK - { + { /* Store the location of the `}' when doing xrefs */ if (flag_emit_xref) - DECL_END_SOURCE_LINE (GET_CPC ()) = + DECL_END_SOURCE_LINE (GET_CPC ()) = EXPR_WFL_ADD_COL ($2.location, 1); $$ = GET_CPC (); } | OCB_TK class_body_declarations CCB_TK - { + { /* Store the location of the `}' when doing xrefs */ if (flag_emit_xref) - DECL_END_SOURCE_LINE (GET_CPC ()) = + DECL_END_SOURCE_LINE (GET_CPC ()) = EXPR_WFL_ADD_COL ($3.location, 1); $$ = GET_CPC (); } @@ -958,7 +928,7 @@ field_declaration: { register_fields (0, $1, $2); } | modifiers type variable_declarators SC_TK { - check_modifiers + check_modifiers ("Illegal modifier `%s' for field declaration", $1, FIELD_MODIFIERS); check_modifiers_consistency ($1); @@ -979,10 +949,10 @@ variable_declarator: variable_declarator_id { $$ = build_tree_list ($1, NULL_TREE); } | variable_declarator_id ASSIGN_TK variable_initializer - { + { if (java_error_count) $3 = NULL_TREE; - $$ = build_tree_list + $$ = build_tree_list ($1, build_assignment ($2.token, $2.location, $1, $3)); } | variable_declarator_id ASSIGN_TK error @@ -1006,13 +976,8 @@ variable_declarator_id: | identifier error {yyerror ("Invalid declaration"); DRECOVER(vdi);} | variable_declarator_id OSB_TK error - { - tree node = java_lval.node; - if (node && (TREE_CODE (node) == INTEGER_CST - || TREE_CODE (node) == EXPR_WITH_FILE_LOCATION)) - yyerror ("Can't specify array dimension in a declaration"); - else - yyerror ("']' expected"); + { + yyerror ("']' expected"); DRECOVER(vdi); } | variable_declarator_id CSB_TK error @@ -1026,7 +991,7 @@ variable_initializer: /* 19.8.3 Productions from 8.4: Method Declarations */ method_declaration: - method_header + method_header { current_function_decl = $1; if (current_function_decl @@ -1041,7 +1006,7 @@ method_declaration: {YYNOT_TWICE yyerror ("'{' expected"); RECOVER;} ; -method_header: +method_header: type method_declarator throws { $$ = method_header (0, $1, $2, $3); } | VOID_TK method_declarator throws @@ -1056,11 +1021,20 @@ method_header: RECOVER; } | modifiers type error - {RECOVER;} + { + yyerror ("Identifier expected"); + RECOVER; + } | VOID_TK error - {yyerror ("Identifier expected"); RECOVER;} + { + yyerror ("Identifier expected"); + RECOVER; + } | modifiers VOID_TK error - {yyerror ("Identifier expected"); RECOVER;} + { + yyerror ("Identifier expected"); + RECOVER; + } | modifiers error { yyerror ("Invalid method declaration, return type required"); @@ -1070,7 +1044,7 @@ method_header: method_declarator: identifier OP_TK CP_TK - { + { ctxp->formal_parameter_number = 0; $$ = method_declarator ($1, NULL_TREE); } @@ -1079,10 +1053,10 @@ method_declarator: | method_declarator OSB_TK CSB_TK { EXPR_WFL_LINECOL (wfl_operator) = $2.location; - TREE_PURPOSE ($1) = + TREE_PURPOSE ($1) = build_unresolved_array_type (TREE_PURPOSE ($1)); - parse_warning_context - (wfl_operator, + parse_warning_context + (wfl_operator, "Discouraged form of returned type specification"); } | identifier OP_TK error @@ -1111,7 +1085,7 @@ formal_parameter: $$ = build_tree_list ($2, $1); } | final type variable_declarator_id /* Added, JDK1.1 final parms */ - { + { $$ = build_tree_list ($3, $2); ARG_FINAL_P ($$) = 1; } @@ -1176,7 +1150,7 @@ static: /* Test lval.sub_token here */ /* Can't have a static initializer in an innerclass */ if ($1 | ACC_STATIC && GET_CPC_LIST () && !TOPLEVEL_CLASS_DECL_P (GET_CPC ())) - parse_error_context + parse_error_context (MODIFIER_WFL (STATIC_TK), "Can't define static initializer in class `%s'. Static initializer can only be defined in top-level classes", IDENTIFIER_POINTER (DECL_NAME (GET_CPC ()))); @@ -1204,8 +1178,8 @@ constructor_header: constructor_declarator: simple_name OP_TK CP_TK - { - ctxp->formal_parameter_number = 0; + { + ctxp->formal_parameter_number = 0; $$ = method_declarator ($1, NULL_TREE); } | simple_name OP_TK formal_parameter_list CP_TK @@ -1217,7 +1191,7 @@ constructor_body: body so we can safely perform all the required code addition (super invocation and field initialization) */ block_begin constructor_block_end - { + { BLOCK_EXPR_BODY ($2) = empty_stmt_node; $$ = $2; } @@ -1236,14 +1210,14 @@ constructor_block_end: /* Error recovery for that rule moved down expression_statement: rule. */ explicit_constructor_invocation: this_or_super OP_TK CP_TK SC_TK - { - $$ = build_method_invocation ($1, NULL_TREE); + { + $$ = build_method_invocation ($1, NULL_TREE); $$ = build_debugable_stmt (EXPR_WFL_LINECOL ($1), $$); $$ = java_method_add_stmt (current_function_decl, $$); } | this_or_super OP_TK argument_list CP_TK SC_TK - { - $$ = build_method_invocation ($1, $3); + { + $$ = build_method_invocation ($1, $3); $$ = build_debugable_stmt (EXPR_WFL_LINECOL ($1), $$); $$ = java_method_add_stmt (current_function_decl, $$); } @@ -1276,29 +1250,33 @@ interface_declaration: INTERFACE_TK identifier { create_interface (0, $2, NULL_TREE); } interface_body + { ; } | modifiers INTERFACE_TK identifier { create_interface ($1, $3, NULL_TREE); } interface_body + { ; } | INTERFACE_TK identifier extends_interfaces { create_interface (0, $2, $3); } interface_body + { ; } | modifiers INTERFACE_TK identifier extends_interfaces { create_interface ($1, $3, $4); } interface_body + { ; } | INTERFACE_TK identifier error - {yyerror ("'{' expected"); RECOVER;} + { yyerror ("'{' expected"); RECOVER; } | modifiers INTERFACE_TK identifier error - {yyerror ("'{' expected"); RECOVER;} + { yyerror ("'{' expected"); RECOVER; } ; extends_interfaces: EXTENDS_TK interface_type - { + { ctxp->interface_number = 1; $$ = build_tree_list ($2, NULL_TREE); } | extends_interfaces C_TK interface_type - { + { ctxp->interface_number++; $$ = chainon ($1, build_tree_list ($3, NULL_TREE)); } @@ -1335,7 +1313,7 @@ constant_declaration: abstract_method_declaration: method_header SC_TK - { + { check_abstract_method_header ($1); current_function_decl = NULL_TREE; /* FIXME ? */ } @@ -1357,8 +1335,8 @@ array_initializer: variable_initializers: variable_initializer - { - $$ = tree_cons (maybe_build_array_element_wfl ($1), + { + $$ = tree_cons (maybe_build_array_element_wfl ($1), $1, NULL_TREE); } | variable_initializers C_TK variable_initializer @@ -1372,12 +1350,12 @@ variable_initializers: /* 19.11 Production from 14: Blocks and Statements */ block: OCB_TK CCB_TK - { + { /* Store the location of the `}' when doing xrefs */ if (current_function_decl && flag_emit_xref) - DECL_END_SOURCE_LINE (current_function_decl) = + DECL_END_SOURCE_LINE (current_function_decl) = EXPR_WFL_ADD_COL ($2.location, 1); - $$ = empty_stmt_node; + $$ = empty_stmt_node; } | block_begin block_statements block_end { $$ = $3; } @@ -1390,12 +1368,12 @@ block_begin: block_end: CCB_TK - { + { maybe_absorb_scoping_blocks (); /* Store the location of the `}' when doing xrefs */ if (current_function_decl && flag_emit_xref) - DECL_END_SOURCE_LINE (current_function_decl) = - EXPR_WFL_ADD_COL ($1.location, 1); + DECL_END_SOURCE_LINE (current_function_decl) = + EXPR_WFL_ADD_COL ($1.location, 1); $$ = exit_block (); if (!BLOCK_SUBBLOCKS ($$)) BLOCK_SUBBLOCKS ($$) = empty_stmt_node; @@ -1412,7 +1390,7 @@ block_statement: | statement { java_method_add_stmt (current_function_decl, $1); } | class_declaration /* Added, JDK1.1 local classes */ - { + { LOCAL_CLASS_P (TREE_TYPE (GET_CPC ())) = 1; end_class_declaration (1); } @@ -1460,20 +1438,21 @@ statement_without_trailing_substatement: | synchronized_statement | throw_statement | try_statement +| assert_statement ; empty_statement: SC_TK - { - if (flag_extraneous_semicolon - && ! current_static_block - && (! current_function_decl || + { + if (flag_extraneous_semicolon + && ! current_static_block + && (! current_function_decl || /* Verify we're not in a inner class declaration */ (GET_CPC () != TYPE_NAME (DECL_CONTEXT (current_function_decl))))) - + { - EXPR_WFL_SET_LINECOL (wfl_operator, lineno, -1); + EXPR_WFL_SET_LINECOL (wfl_operator, input_line, -1); parse_warning_context (wfl_operator, "An empty declaration is a deprecated feature that should not be used"); } $$ = empty_stmt_node; @@ -1483,7 +1462,7 @@ empty_statement: label_decl: identifier REL_CL_TK { - $$ = build_labeled_block (EXPR_WFL_LINECOL ($1), + $$ = build_labeled_block (EXPR_WFL_LINECOL ($1), EXPR_WFL_NODE ($1)); pushlevel (2); push_labeled_block ($$); @@ -1510,12 +1489,12 @@ expression_statement: { /* We have a statement. Generate a WFL around it so we can debug it */ - $$ = build_expr_wfl ($1, input_filename, lineno, 0); + $$ = build_expr_wfl ($1, input_filename, input_line, 0); /* We know we have a statement, so set the debug info to be eventually generate here. */ $$ = JAVA_MAYBE_GENERATE_DEBUG_INFO ($$); } -| error SC_TK +| error SC_TK { YYNOT_TWICE yyerror ("Invalid expression statement"); DRECOVER (expr_stmt); @@ -1556,7 +1535,7 @@ expression_statement: {yyerror ("';' expected"); RECOVER;} ; -statement_expression: +statement_expression: assignment | pre_increment_expression | pre_decrement_expression @@ -1568,8 +1547,8 @@ statement_expression: if_then_statement: IF_TK OP_TK expression CP_TK statement - { - $$ = build_if_else_statement ($2.location, $3, + { + $$ = build_if_else_statement ($2.location, $3, $5, NULL_TREE); } | IF_TK error @@ -1596,7 +1575,7 @@ switch_statement: enter_block (); } switch_block - { + { /* Make into "proper list" of COMPOUND_EXPRs. I.e. make the last statement also have its own COMPOUND_EXPR. */ @@ -1608,7 +1587,7 @@ switch_statement: switch_expression: SWITCH_TK OP_TK expression CP_TK - { + { $$ = build (SWITCH_EXPR, NULL_TREE, $3, NULL_TREE); EXPR_WFL_LINECOL ($$) = $2.location; } @@ -1634,7 +1613,7 @@ switch_block: { $$ = NULL_TREE; } ; -switch_block_statement_groups: +switch_block_statement_groups: switch_block_statement_group | switch_block_statement_groups switch_block_statement_group ; @@ -1650,13 +1629,13 @@ switch_labels: switch_label: CASE_TK constant_expression REL_CL_TK - { + { tree lab = build1 (CASE_EXPR, NULL_TREE, $2); EXPR_WFL_LINECOL (lab) = $1.location; java_method_add_stmt (current_function_decl, lab); } | DEFAULT_TK REL_CL_TK - { + { tree lab = build (DEFAULT_EXPR, NULL_TREE, NULL_TREE); EXPR_WFL_LINECOL (lab) = $1.location; java_method_add_stmt (current_function_decl, lab); @@ -1671,7 +1650,7 @@ switch_label: while_expression: WHILE_TK OP_TK expression CP_TK - { + { tree body = build_loop_body ($2.location, $3, 0); $$ = build_new_loop (body); } @@ -1695,14 +1674,14 @@ while_statement_nsi: do_statement_begin: DO_TK - { + { tree body = build_loop_body (0, NULL_TREE, 1); $$ = build_new_loop (body); } /* Need error handing here. FIXME */ ; -do_statement: +do_statement: do_statement_begin statement WHILE_TK OP_TK expression CP_TK SC_TK { $$ = finish_loop_body ($4.location, $5, $2, 1); } ; @@ -1715,10 +1694,10 @@ for_statement: $$ = finish_for_loop (EXPR_WFL_LINECOL ($3), $3, $5, $7); } | for_begin SC_TK SC_TK for_update CP_TK statement - { + { $$ = finish_for_loop (0, NULL_TREE, $4, $6); /* We have not condition, so we get rid of the EXIT_EXPR */ - LOOP_EXPR_BODY_CONDITION_EXPR (LOOP_EXPR_BODY ($$), 0) = + LOOP_EXPR_BODY_CONDITION_EXPR (LOOP_EXPR_BODY ($$), 0) = empty_stmt_node; } | for_begin SC_TK error @@ -1733,20 +1712,20 @@ for_statement_nsi: for_begin SC_TK expression SC_TK for_update CP_TK statement_nsi { $$ = finish_for_loop (EXPR_WFL_LINECOL ($3), $3, $5, $7);} | for_begin SC_TK SC_TK for_update CP_TK statement_nsi - { + { $$ = finish_for_loop (0, NULL_TREE, $4, $6); /* We have not condition, so we get rid of the EXIT_EXPR */ - LOOP_EXPR_BODY_CONDITION_EXPR (LOOP_EXPR_BODY ($$), 0) = + LOOP_EXPR_BODY_CONDITION_EXPR (LOOP_EXPR_BODY ($$), 0) = empty_stmt_node; } ; for_header: FOR_TK OP_TK - { + { /* This scope defined for local variable that may be defined within the scope of the for loop */ - enter_block (); + enter_block (); } | FOR_TK error {yyerror ("'(' expected"); DRECOVER(for_1);} @@ -1756,7 +1735,7 @@ for_header: for_begin: for_header for_init - { + { /* We now declare the loop body. The loop is declared as a for loop. */ tree body = build_loop_body (0, NULL_TREE, 0); @@ -1770,13 +1749,13 @@ for_begin: for_init: /* Can be empty */ { $$ = empty_stmt_node; } | statement_expression_list - { + { /* Init statement recorded within the previously defined block scope */ $$ = java_method_add_stmt (current_function_decl, $1); } | local_variable_declaration - { + { /* Local variable are recorded within the previously defined block scope */ $$ = NULL_TREE; @@ -1835,7 +1814,7 @@ return_statement: throw_statement: THROW_TK expression SC_TK - { + { $$ = build1 (THROW_EXPR, NULL_TREE, $2); EXPR_WFL_LINECOL ($$) = $1.location; } @@ -1845,11 +1824,26 @@ throw_statement: {yyerror ("';' expected"); RECOVER;} ; +assert_statement: + ASSERT_TK expression REL_CL_TK expression SC_TK + { + $$ = build_assertion ($1.location, $2, $4); + } +| ASSERT_TK expression SC_TK + { + $$ = build_assertion ($1.location, $2, NULL_TREE); + } +| ASSERT_TK error + {yyerror ("Missing term"); RECOVER;} +| ASSERT_TK expression error + {yyerror ("';' expected"); RECOVER;} +; + synchronized_statement: synchronized OP_TK expression CP_TK block - { + { $$ = build (SYNCHRONIZED_EXPR, NULL_TREE, $3, $5); - EXPR_WFL_LINECOL ($$) = + EXPR_WFL_LINECOL ($$) = EXPR_WFL_LINECOL (MODIFIER_WFL (SYNCHRONIZED_TK)); } | synchronized OP_TK expression CP_TK error @@ -1869,7 +1863,7 @@ synchronized: "Illegal modifier `%s'. Only `synchronized' was expected here", $1, ACC_SYNCHRONIZED); if ($1 != ACC_SYNCHRONIZED) - MODIFIER_WFL (SYNCHRONIZED_TK) = + MODIFIER_WFL (SYNCHRONIZED_TK) = build_wfl_node (NULL_TREE); } ; @@ -1880,7 +1874,7 @@ try_statement: | TRY_TK block finally { $$ = build_try_finally_statement ($1.location, $2, $3); } | TRY_TK block catches finally - { $$ = build_try_finally_statement + { $$ = build_try_finally_statement ($1.location, build_try_statement ($1.location, $2, $3), $4); } @@ -1891,7 +1885,7 @@ try_statement: catches: catch_clause | catches catch_clause - { + { TREE_CHAIN ($2) = $1; $$ = $2; } @@ -1899,22 +1893,23 @@ catches: catch_clause: catch_clause_parameter block - { + { java_method_add_stmt (current_function_decl, $2); exit_block (); $$ = $1; } +; catch_clause_parameter: CATCH_TK OP_TK formal_parameter CP_TK - { + { /* We add a block to define a scope for formal_parameter (CCBP). The formal parameter is declared initialized by the appropriate function call */ tree ccpb = enter_block (); tree init = build_assignment - (ASSIGN_TK, $2.location, TREE_PURPOSE ($3), + (ASSIGN_TK, $2.location, TREE_PURPOSE ($3), build (JAVA_EXC_OBJ_EXPR, ptr_type_node)); declare_local_variables (0, TREE_VALUE ($3), build_tree_list (TREE_PURPOSE ($3), @@ -1924,9 +1919,9 @@ catch_clause_parameter: } | CATCH_TK error {yyerror ("'(' expected"); RECOVER; $$ = NULL_TREE;} -| CATCH_TK OP_TK error +| CATCH_TK OP_TK error { - yyerror ("Missing term or ')' expected"); + yyerror ("Missing term or ')' expected"); RECOVER; $$ = NULL_TREE; } | CATCH_TK OP_TK error CP_TK /* That's for () */ @@ -1961,11 +1956,11 @@ primary_no_new_array: refering to a 'ClassName' (class_name) rule that doesn't exist. Used name: instead. */ | name DOT_TK THIS_TK - { + { tree wfl = build_wfl_node (this_identifier_node); $$ = make_qualified_primary ($1, wfl, EXPR_WFL_LINECOL ($1)); } -| OP_TK expression error +| OP_TK expression error {yyerror ("')' expected"); RECOVER;} | name DOT_TK error {yyerror ("'class' or 'this' expected" ); RECOVER;} @@ -1983,7 +1978,7 @@ type_literals: | primitive_type DOT_TK CLASS_TK { $$ = build_incomplete_class_ref ($2.location, $1); } | VOID_TK DOT_TK CLASS_TK - { + { $$ = build_incomplete_class_ref ($2.location, void_type_node); } @@ -1999,20 +1994,20 @@ class_instance_creation_expression: primary instead of primary solely which couldn't work in all situations. */ | something_dot_new identifier OP_TK CP_TK - { + { tree ctor = build_new_invocation ($2, NULL_TREE); - $$ = make_qualified_primary ($1, ctor, + $$ = make_qualified_primary ($1, ctor, EXPR_WFL_LINECOL ($1)); } | something_dot_new identifier OP_TK CP_TK class_body | something_dot_new identifier OP_TK argument_list CP_TK - { + { tree ctor = build_new_invocation ($2, $4); - $$ = make_qualified_primary ($1, ctor, + $$ = make_qualified_primary ($1, ctor, EXPR_WFL_LINECOL ($1)); } | something_dot_new identifier OP_TK argument_list CP_TK class_body -| NEW_TK error SC_TK +| NEW_TK error SC_TK {yyerror ("'(' expected"); DRECOVER(new_1);} | NEW_TK class_type error {yyerror ("'(' expected"); RECOVER;} @@ -2032,10 +2027,10 @@ class_instance_creation_expression: in the documentation but doesn't exist. */ anonymous_class_creation: - NEW_TK class_type OP_TK argument_list CP_TK + NEW_TK class_type OP_TK argument_list CP_TK { create_anonymous_class ($1.location, $2); } class_body - { + { tree id = build_wfl_node (DECL_NAME (GET_CPC ())); EXPR_WFL_LINECOL (id) = EXPR_WFL_LINECOL ($2); @@ -2057,7 +2052,7 @@ anonymous_class_creation: must be generated following the hints provided by the `new' expression. Whether a super constructor of that nature exists or not is to be verified - later on in verify_constructor_super. + later on in verify_constructor_super. It's during the expansion of a `new' statement refering to an anonymous class that a ctor will @@ -2065,10 +2060,10 @@ anonymous_class_creation: right arguments. */ } -| NEW_TK class_type OP_TK CP_TK +| NEW_TK class_type OP_TK CP_TK { create_anonymous_class ($1.location, $2); } - class_body - { + class_body + { tree id = build_wfl_node (DECL_NAME (GET_CPC ())); EXPR_WFL_LINECOL (id) = EXPR_WFL_LINECOL ($2); @@ -2091,9 +2086,9 @@ something_dot_new: /* Added, not part of the specs. */ argument_list: expression - { + { $$ = tree_cons (NULL_TREE, $1, NULL_TREE); - ctxp->formal_parameter_number = 1; + ctxp->formal_parameter_number = 1; } | argument_list C_TK expression { @@ -2127,12 +2122,12 @@ array_creation_expression: $2, get_identifier (sig), $4); } | NEW_TK primitive_type dims array_initializer - { + { int osb = pop_current_osb (ctxp); tree type = $2; while (osb--) type = build_java_array_type (type, -1); - $$ = build (NEW_ANONYMOUS_ARRAY_EXPR, NULL_TREE, + $$ = build (NEW_ANONYMOUS_ARRAY_EXPR, NULL_TREE, build_pointer_type (type), NULL_TREE, $4); } | NEW_TK error CSB_TK @@ -2150,7 +2145,7 @@ dim_exprs: dim_expr: OSB_TK expression CSB_TK - { + { if (JNUMERIC_TYPE_P (TREE_TYPE ($2))) { $2 = build_wfl_node ($2); @@ -2169,9 +2164,9 @@ dim_expr: } ; -dims: +dims: OSB_TK CSB_TK - { + { int allocate = 0; /* If not initialized, allocate memory for the osb numbers stack */ @@ -2183,15 +2178,15 @@ dims: /* If capacity overflown, reallocate a bigger chunk */ else if (ctxp->osb_depth+1 == ctxp->osb_limit) allocate = ctxp->osb_limit << 1; - + if (allocate) { allocate *= sizeof (int); if (ctxp->osb_number) - ctxp->osb_number = (int *)xrealloc (ctxp->osb_number, - allocate); + ctxp->osb_number = xrealloc (ctxp->osb_number, + allocate); else - ctxp->osb_number = (int *)xmalloc (allocate); + ctxp->osb_number = xmalloc (allocate); } ctxp->osb_depth++; CURRENT_OSB (ctxp) = 1; @@ -2205,7 +2200,7 @@ dims: field_access: primary DOT_TK identifier { $$ = make_qualified_primary ($1, $3, $2.location); } - /* FIXME - REWRITE TO: + /* FIXME - REWRITE TO: { $$ = build_binop (COMPONENT_REF, $2.location, $1, $3); } */ | SUPER_TK DOT_TK identifier { @@ -2223,9 +2218,9 @@ method_invocation: | name OP_TK argument_list CP_TK { $$ = build_method_invocation ($1, $3); } | primary DOT_TK identifier OP_TK CP_TK - { + { if (TREE_CODE ($1) == THIS_EXPR) - $$ = build_this_super_qualified_invocation + $$ = build_this_super_qualified_invocation (1, $3, NULL_TREE, 0, $2.location); else { @@ -2234,9 +2229,9 @@ method_invocation: } } | primary DOT_TK identifier OP_TK argument_list CP_TK - { + { if (TREE_CODE ($1) == THIS_EXPR) - $$ = build_this_super_qualified_invocation + $$ = build_this_super_qualified_invocation (1, $3, $5, 0, $2.location); else { @@ -2245,13 +2240,13 @@ method_invocation: } } | SUPER_TK DOT_TK identifier OP_TK CP_TK - { - $$ = build_this_super_qualified_invocation + { + $$ = build_this_super_qualified_invocation (0, $3, NULL_TREE, $1.location, $2.location); } | SUPER_TK DOT_TK identifier OP_TK argument_list CP_TK { - $$ = build_this_super_qualified_invocation + $$ = build_this_super_qualified_invocation (0, $3, $5, $1.location, $2.location); } /* Screws up thing. I let it here until I'm convinced it can @@ -2359,22 +2354,22 @@ unary_expression_not_plus_minus: cast_expression: /* Error handling here is potentially weak */ OP_TK primitive_type dims CP_TK unary_expression - { + { tree type = $2; int osb = pop_current_osb (ctxp); while (osb--) type = build_java_array_type (type, -1); - $$ = build_cast ($1.location, type, $5); + $$ = build_cast ($1.location, type, $5); } | OP_TK primitive_type CP_TK unary_expression { $$ = build_cast ($1.location, $2, $4); } | OP_TK expression CP_TK unary_expression_not_plus_minus { $$ = build_cast ($1.location, $2, $4); } | OP_TK name dims CP_TK unary_expression_not_plus_minus - { + { const char *ptr; - int osb = pop_current_osb (ctxp); - obstack_grow (&temporary_obstack, + int osb = pop_current_osb (ctxp); + obstack_grow (&temporary_obstack, IDENTIFIER_POINTER (EXPR_WFL_NODE ($2)), IDENTIFIER_LENGTH (EXPR_WFL_NODE ($2))); while (osb--) @@ -2402,19 +2397,19 @@ cast_expression: /* Error handling here is potentially weak */ multiplicative_expression: unary_expression | multiplicative_expression MULT_TK unary_expression - { - $$ = build_binop (BINOP_LOOKUP ($2.token), + { + $$ = build_binop (BINOP_LOOKUP ($2.token), $2.location, $1, $3); } | multiplicative_expression DIV_TK unary_expression { $$ = build_binop (BINOP_LOOKUP ($2.token), $2.location, - $1, $3); + $1, $3); } | multiplicative_expression REM_TK unary_expression { $$ = build_binop (BINOP_LOOKUP ($2.token), $2.location, - $1, $3); + $1, $3); } | multiplicative_expression MULT_TK error {yyerror ("Missing term"); RECOVER;} @@ -2429,12 +2424,12 @@ additive_expression: | additive_expression PLUS_TK multiplicative_expression { $$ = build_binop (BINOP_LOOKUP ($2.token), $2.location, - $1, $3); + $1, $3); } | additive_expression MINUS_TK multiplicative_expression { $$ = build_binop (BINOP_LOOKUP ($2.token), $2.location, - $1, $3); + $1, $3); } | additive_expression PLUS_TK error {yyerror ("Missing term"); RECOVER;} @@ -2447,17 +2442,17 @@ shift_expression: | shift_expression LS_TK additive_expression { $$ = build_binop (BINOP_LOOKUP ($2.token), $2.location, - $1, $3); + $1, $3); } | shift_expression SRS_TK additive_expression { $$ = build_binop (BINOP_LOOKUP ($2.token), $2.location, - $1, $3); + $1, $3); } | shift_expression ZRS_TK additive_expression { $$ = build_binop (BINOP_LOOKUP ($2.token), $2.location, - $1, $3); + $1, $3); } | shift_expression LS_TK error {yyerror ("Missing term"); RECOVER;} @@ -2472,22 +2467,22 @@ relational_expression: | relational_expression LT_TK shift_expression { $$ = build_binop (BINOP_LOOKUP ($2.token), $2.location, - $1, $3); + $1, $3); } | relational_expression GT_TK shift_expression { $$ = build_binop (BINOP_LOOKUP ($2.token), $2.location, - $1, $3); + $1, $3); } | relational_expression LTE_TK shift_expression { $$ = build_binop (BINOP_LOOKUP ($2.token), $2.location, - $1, $3); + $1, $3); } | relational_expression GTE_TK shift_expression { $$ = build_binop (BINOP_LOOKUP ($2.token), $2.location, - $1, $3); + $1, $3); } | relational_expression INSTANCEOF_TK reference_type { $$ = build_binop (INSTANCEOF_EXPR, $2.location, $1, $3); } @@ -2508,12 +2503,12 @@ equality_expression: | equality_expression EQ_TK relational_expression { $$ = build_binop (BINOP_LOOKUP ($2.token), $2.location, - $1, $3); + $1, $3); } | equality_expression NEQ_TK relational_expression { $$ = build_binop (BINOP_LOOKUP ($2.token), $2.location, - $1, $3); + $1, $3); } | equality_expression EQ_TK error {yyerror ("Missing term"); RECOVER;} @@ -2526,7 +2521,7 @@ and_expression: | and_expression AND_TK equality_expression { $$ = build_binop (BINOP_LOOKUP ($2.token), $2.location, - $1, $3); + $1, $3); } | and_expression AND_TK error {yyerror ("Missing term"); RECOVER;} @@ -2537,7 +2532,7 @@ exclusive_or_expression: | exclusive_or_expression XOR_TK and_expression { $$ = build_binop (BINOP_LOOKUP ($2.token), $2.location, - $1, $3); + $1, $3); } | exclusive_or_expression XOR_TK error {yyerror ("Missing term"); RECOVER;} @@ -2548,7 +2543,7 @@ inclusive_or_expression: | inclusive_or_expression OR_TK exclusive_or_expression { $$ = build_binop (BINOP_LOOKUP ($2.token), $2.location, - $1, $3); + $1, $3); } | inclusive_or_expression OR_TK error {yyerror ("Missing term"); RECOVER;} @@ -2559,7 +2554,7 @@ conditional_and_expression: | conditional_and_expression BOOL_AND_TK inclusive_or_expression { $$ = build_binop (BINOP_LOOKUP ($2.token), $2.location, - $1, $3); + $1, $3); } | conditional_and_expression BOOL_AND_TK error {yyerror ("Missing term"); RECOVER;} @@ -2570,7 +2565,7 @@ conditional_or_expression: | conditional_or_expression BOOL_OR_TK conditional_and_expression { $$ = build_binop (BINOP_LOOKUP ($2.token), $2.location, - $1, $3); + $1, $3); } | conditional_or_expression BOOL_OR_TK error {yyerror ("Missing term"); RECOVER;} @@ -2635,17 +2630,16 @@ constant_expression: `dims:' rule is being used. */ static int -pop_current_osb (ctxp) - struct parser_ctxt *ctxp; +pop_current_osb (struct parser_ctxt *ctxp) { int to_return; if (ctxp->osb_depth < 0) abort (); - + to_return = CURRENT_OSB (ctxp); ctxp->osb_depth--; - + return to_return; } @@ -2655,25 +2649,24 @@ pop_current_osb (ctxp) Add mode documentation here. FIXME */ /* Helper function. Create a new parser context. With - COPY_FROM_PREVIOUS set to a non zero value, content of the previous + COPY_FROM_PREVIOUS set to a nonzero value, content of the previous context is copied, otherwise, the new context is zeroed. The newly created context becomes the current one. */ static void -create_new_parser_context (copy_from_previous) - int copy_from_previous; +create_new_parser_context (int copy_from_previous) { struct parser_ctxt *new; - new = (struct parser_ctxt *)xmalloc(sizeof (struct parser_ctxt)); + new = ggc_alloc (sizeof (struct parser_ctxt)); if (copy_from_previous) { - memcpy ((PTR)new, (PTR)ctxp, sizeof (struct parser_ctxt)); + memcpy (new, ctxp, sizeof (struct parser_ctxt)); new->saved_data_ctx = 1; } else - memset ((PTR) new, 0, sizeof (struct parser_ctxt)); - + memset (new, 0, sizeof (struct parser_ctxt)); + new->next = ctxp; ctxp = new; } @@ -2681,14 +2674,13 @@ create_new_parser_context (copy_from_previous) /* Create a new parser context and make it the current one. */ void -java_push_parser_context () +java_push_parser_context (void) { create_new_parser_context (0); -} +} -void -java_pop_parser_context (generate) - int generate; +void +java_pop_parser_context (int generate) { tree current; struct parser_ctxt *toFree, *next; @@ -2700,7 +2692,7 @@ java_pop_parser_context (generate) next = ctxp->next; if (next) { - lineno = ctxp->lineno; + input_line = ctxp->lineno; current_class = ctxp->class_type; } @@ -2717,7 +2709,7 @@ java_pop_parser_context (generate) if ((ctxp = next)) /* Assignment is really meant here */ for (current = ctxp->import_list; current; current = TREE_CHAIN (current)) IS_A_SINGLE_IMPORT_CLASSFILE_NAME_P (TREE_VALUE (current)) = 1; - + /* If we pushed a context to parse a class intended to be generated, we keep it so we can remember the class. What we could actually do is to just update a list of class names. */ @@ -2726,15 +2718,13 @@ java_pop_parser_context (generate) toFree->next = ctxp_for_generation; ctxp_for_generation = toFree; } - else - free (toFree); } /* Create a parser context for the use of saving some global variables. */ void -java_parser_context_save_global () +java_parser_context_save_global (void) { if (!ctxp) { @@ -2747,7 +2737,7 @@ java_parser_context_save_global () else if (ctxp->saved_data) create_new_parser_context (1); - ctxp->lineno = lineno; + ctxp->lineno = input_line; ctxp->class_type = current_class; ctxp->filename = input_filename; ctxp->function_decl = current_function_decl; @@ -2758,9 +2748,9 @@ java_parser_context_save_global () previous context the current one. */ void -java_parser_context_restore_global () +java_parser_context_restore_global (void) { - lineno = ctxp->lineno; + input_line = ctxp->lineno; current_class = ctxp->class_type; input_filename = ctxp->filename; if (wfl_operator) @@ -2780,7 +2770,7 @@ java_parser_context_restore_global () classes be parsed. */ static void -java_parser_context_suspend () +java_parser_context_suspend (void) { /* This makes debugging through java_debug_context easier */ static const char *const name = ""; @@ -2806,7 +2796,7 @@ java_parser_context_suspend () can resume as if no context was ever saved. */ static void -java_parser_context_resume () +java_parser_context_resume (void) { struct parser_ctxt *old = ctxp; /* This one is to be discarded */ struct parser_ctxt *saver = old->next; /* This one contain saved info */ @@ -2824,12 +2814,8 @@ java_parser_context_resume () ctxp = restored; /* Re-installed the data for the parsing to carry on */ - memcpy (&ctxp->marker_begining, &old->marker_begining, + memcpy (&ctxp->marker_begining, &old->marker_begining, (size_t)(&ctxp->marker_end - &ctxp->marker_begining)); - - /* Buffer context can now be discarded */ - free (saver); - free (old); } /* Add a new anchor node to which all statement(s) initializing static @@ -2837,7 +2823,7 @@ java_parser_context_resume () linked. */ static void -java_parser_context_push_initialized_field () +java_parser_context_push_initialized_field (void) { tree node; @@ -2859,7 +2845,7 @@ java_parser_context_push_initialized_field () or functions. */ static void -java_parser_context_pop_initialized_field () +java_parser_context_pop_initialized_field (void) { tree stmts; tree class_type = TREE_TYPE (GET_CPC ()); @@ -2875,7 +2861,7 @@ java_parser_context_pop_initialized_field () if (CPC_STATIC_INITIALIZER_LIST (ctxp)) { stmts = CPC_STATIC_INITIALIZER_STMT (ctxp); - CPC_STATIC_INITIALIZER_LIST (ctxp) = + CPC_STATIC_INITIALIZER_LIST (ctxp) = TREE_CHAIN (CPC_STATIC_INITIALIZER_LIST (ctxp)); /* Keep initialization in order to enforce 8.5 */ if (stmts && !java_error_count) @@ -2886,7 +2872,7 @@ java_parser_context_pop_initialized_field () if (CPC_INSTANCE_INITIALIZER_LIST (ctxp)) { stmts = CPC_INSTANCE_INITIALIZER_STMT (ctxp); - CPC_INSTANCE_INITIALIZER_LIST (ctxp) = + CPC_INSTANCE_INITIALIZER_LIST (ctxp) = TREE_CHAIN (CPC_INSTANCE_INITIALIZER_LIST (ctxp)); if (stmts && !java_error_count) TYPE_II_STMT_LIST (class_type) = nreverse (stmts); @@ -2894,18 +2880,17 @@ java_parser_context_pop_initialized_field () } static tree -reorder_static_initialized (list) - tree list; +reorder_static_initialized (tree list) { /* We have to keep things in order. The alias initializer have to come first, then the initialized regular field, in reverse to keep them in lexical order. */ tree marker, previous = NULL_TREE; for (marker = list; marker; previous = marker, marker = TREE_CHAIN (marker)) - if (TREE_CODE (marker) == TREE_LIST + if (TREE_CODE (marker) == TREE_LIST && !TREE_VALUE (marker) && !TREE_PURPOSE (marker)) break; - + /* No static initialized, the list is fine as is */ if (!previous) list = TREE_CHAIN (marker); @@ -2931,8 +2916,7 @@ reorder_static_initialized (list) {int i; for (i = 0; i < (C); i++) fputc (' ', stderr);} static void -java_debug_context_do (tab) - int tab; +java_debug_context_do (int tab) { struct parser_ctxt *copy = ctxp; while (copy) @@ -2945,7 +2929,7 @@ java_debug_context_do (tab) fprintf (stderr, "lineno: %d\n", copy->lineno); TAB_CONTEXT (tab); fprintf (stderr, "package: %s\n", - (copy->package ? + (copy->package ? IDENTIFIER_POINTER (copy->package) : "")); TAB_CONTEXT (tab); fprintf (stderr, "context for saving: %d\n", copy->saved_data_ctx); @@ -2960,7 +2944,7 @@ java_debug_context_do (tab) debugger. */ void -java_debug_context () +java_debug_context (void) { java_debug_context_do (0); } @@ -2975,10 +2959,10 @@ static int force_error = 0; /* Reporting an constructor invocation error. */ static void -parse_ctor_invocation_error () +parse_ctor_invocation_error (void) { if (DECL_CONSTRUCTOR_P (current_function_decl)) - yyerror ("Constructor invocation must be first thing in a constructor"); + yyerror ("Constructor invocation must be first thing in a constructor"); else yyerror ("Only constructors can invoke constructors"); } @@ -2986,8 +2970,7 @@ parse_ctor_invocation_error () /* Reporting JDK1.1 features not implemented. */ static tree -parse_jdk1_1_error (msg) - const char *msg; +parse_jdk1_1_error (const char *msg) { sorry (": `%s' JDK1.1(TM) feature", msg); java_error_count++; @@ -2997,8 +2980,7 @@ parse_jdk1_1_error (msg) static int do_warning = 0; void -yyerror (msg) - const char *msg; +yyerror (const char *msg) { static java_lc elc; static int prev_lineno; @@ -3006,8 +2988,8 @@ yyerror (msg) int save_lineno; char *remainder, *code_from_source; - - if (!force_error && prev_lineno == lineno) + + if (!force_error && prev_lineno == input_line) return; /* Save current error location but report latter, when the context is @@ -3033,19 +3015,19 @@ yyerror (msg) java_warning_count++; else java_error_count++; - + if (elc.col == 0 && msg && msg[1] == ';') { elc.col = ctxp->p_line->char_col-1; elc.line = ctxp->p_line->lineno; } - save_lineno = lineno; - prev_lineno = lineno = elc.line; + save_lineno = input_line; + prev_lineno = input_line = elc.line; prev_msg = msg; code_from_source = java_get_line_col (ctxp->filename, elc.line, elc.col); - obstack_grow0 (&temporary_obstack, + obstack_grow0 (&temporary_obstack, code_from_source, strlen (code_from_source)); remainder = obstack_finish (&temporary_obstack); if (do_warning) @@ -3058,14 +3040,11 @@ yyerror (msg) the same line. This occurs when we report an error but don't have a synchronization point other than ';', which expression_statement is the only one to take care of. */ - ctxp->prevent_ese = lineno = save_lineno; + ctxp->prevent_ese = input_line = save_lineno; } static void -issue_warning_error_from_context (cl, msg, ap) - tree cl; - const char *msg; - va_list ap; +issue_warning_error_from_context (tree cl, const char *msg, va_list ap) { const char *saved, *saved_input_filename; char buffer [4096]; @@ -3073,7 +3052,7 @@ issue_warning_error_from_context (cl, msg, ap) force_error = 1; ctxp->elc.line = EXPR_WFL_LINENO (cl); - ctxp->elc.col = (EXPR_WFL_COLNO (cl) == 0xfff ? -1 : + ctxp->elc.col = (EXPR_WFL_COLNO (cl) == 0xfff ? -1 : (EXPR_WFL_COLNO (cl) == 0xffe ? -2 : EXPR_WFL_COLNO (cl))); /* We have a CL, that's a good reason for using it if it contains data */ @@ -3092,33 +3071,30 @@ issue_warning_error_from_context (cl, msg, ap) /* Issue an error message at a current source line CL */ void -parse_error_context VPARAMS ((tree cl, const char *msg, ...)) +parse_error_context (tree cl, const char *msg, ...) { - VA_OPEN (ap, msg); - VA_FIXEDARG (ap, tree, cl); - VA_FIXEDARG (ap, const char *, msg); + va_list ap; + va_start (ap, msg); issue_warning_error_from_context (cl, msg, ap); - VA_CLOSE (ap); + va_end (ap); } /* Issue a warning at a current source line CL */ static void -parse_warning_context VPARAMS ((tree cl, const char *msg, ...)) +parse_warning_context (tree cl, const char *msg, ...) { - VA_OPEN (ap, msg); - VA_FIXEDARG (ap, tree, cl); - VA_FIXEDARG (ap, const char *, msg); + va_list ap; + va_start (ap, msg); force_error = do_warning = 1; issue_warning_error_from_context (cl, msg, ap); do_warning = force_error = 0; - VA_CLOSE (ap); + va_end (ap); } static tree -find_expr_with_wfl (node) - tree node; +find_expr_with_wfl (tree node) { while (node) { @@ -3141,7 +3117,7 @@ find_expr_with_wfl (node) case LOOP_EXPR: node = TREE_OPERAND (node, 0); continue; - + case LABELED_BLOCK_EXPR: node = TREE_OPERAND (node, 1); continue; @@ -3161,8 +3137,7 @@ find_expr_with_wfl (node) last line of the method the error occurs in. */ static void -missing_return_error (method) - tree method; +missing_return_error (tree method) { EXPR_WFL_SET_LINECOL (wfl_operator, DECL_SOURCE_LINE_LAST (method), -2); parse_error_context (wfl_operator, "Missing return statement"); @@ -3171,8 +3146,7 @@ missing_return_error (method) /* Issue an unreachable statement error. From NODE, find the next statement to report appropriately. */ static void -unreachable_stmt_error (node) - tree node; +unreachable_stmt_error (tree node) { /* Browse node to find the next expression node that has a WFL. Use the location to report the error */ @@ -3191,10 +3165,10 @@ unreachable_stmt_error (node) } int -java_report_errors () +java_report_errors (void) { if (java_error_count) - fprintf (stderr, "%d error%s", + fprintf (stderr, "%d error%s", java_error_count, (java_error_count == 1 ? "" : "s")); if (java_warning_count) fprintf (stderr, "%s%d warning%s", (java_error_count ? ", " : ""), @@ -3205,8 +3179,7 @@ java_report_errors () } static char * -java_accstring_lookup (flags) - int flags; +java_accstring_lookup (int flags) { static char buffer [80]; #define COPY_RETURN(S) {strcpy (buffer, S); return buffer;} @@ -3234,20 +3207,16 @@ java_accstring_lookup (flags) variables. */ static void -classitf_redefinition_error (context, id, decl, cl) - const char *context; - tree id, decl, cl; +classitf_redefinition_error (const char *context, tree id, tree decl, tree cl) { - parse_error_context (cl, "%s `%s' already defined in %s:%d", - context, IDENTIFIER_POINTER (id), + parse_error_context (cl, "%s `%s' already defined in %s:%d", + context, IDENTIFIER_POINTER (id), DECL_SOURCE_FILE (decl), DECL_SOURCE_LINE (decl)); /* Here we should point out where its redefined. It's a unicode. FIXME */ } static void -variable_redefinition_error (context, name, type, line) - tree context, name, type; - int line; +variable_redefinition_error (tree context, tree name, tree type, int line) { const char *type_name; @@ -3258,7 +3227,7 @@ variable_redefinition_error (context, name, type, line) type_name = lang_printable_name (type, 0); parse_error_context (context, - "Variable `%s' is already defined in this method and was declared `%s %s' at line %d", + "Variable `%s' is already defined in this method and was declared `%s %s' at line %d", IDENTIFIER_POINTER (name), type_name, IDENTIFIER_POINTER (name), line); } @@ -3269,9 +3238,7 @@ variable_redefinition_error (context, name, type, line) the node pointed to by TRIMMED unless TRIMMED is null. */ static int -build_type_name_from_array_name (aname, trimmed) - tree aname; - tree *trimmed; +build_type_name_from_array_name (tree aname, tree *trimmed) { const char *name = IDENTIFIER_POINTER (aname); int len = IDENTIFIER_LENGTH (aname); @@ -3286,14 +3253,13 @@ build_type_name_from_array_name (aname, trimmed) } static tree -build_array_from_name (type, type_wfl, name, ret_name) - tree type, type_wfl, name, *ret_name; +build_array_from_name (tree type, tree type_wfl, tree name, tree *ret_name) { int more_dims = 0; /* Eventually get more dims */ more_dims = build_type_name_from_array_name (name, &name); - + /* If we have, then craft a new type for this variable */ if (more_dims) { @@ -3339,8 +3305,7 @@ build_array_from_name (type, type_wfl, name, ret_name) identifier. */ static tree -build_unresolved_array_type (type_or_wfl) - tree type_or_wfl; +build_unresolved_array_type (tree type_or_wfl) { const char *ptr; tree wfl; @@ -3366,8 +3331,7 @@ build_unresolved_array_type (type_or_wfl) } static void -parser_add_interface (class_decl, interface_decl, wfl) - tree class_decl, interface_decl, wfl; +parser_add_interface (tree class_decl, tree interface_decl, tree wfl) { if (maybe_add_interface (TREE_TYPE (class_decl), TREE_TYPE (interface_decl))) parse_error_context (wfl, "Interface `%s' repeated", @@ -3378,9 +3342,8 @@ parser_add_interface (class_decl, interface_decl, wfl) encountered. TAG is 0 for a class, 1 for an interface. */ static int -check_class_interface_creation (is_interface, flags, raw_name, qualified_name, decl, cl) - int is_interface, flags; - tree raw_name, qualified_name, decl, cl; +check_class_interface_creation (int is_interface, int flags, tree raw_name, + tree qualified_name, tree decl, tree cl) { tree node; int sca = 0; /* Static class allowed */ @@ -3388,9 +3351,9 @@ check_class_interface_creation (is_interface, flags, raw_name, qualified_name, d int uaaf = CLASS_MODIFIERS; /* Usually allowed access flags */ if (!quiet_flag) - fprintf (stderr, " %s%s %s", + fprintf (stderr, " %s%s %s", (CPC_INNER_P () ? "inner" : ""), - (is_interface ? "interface" : "class"), + (is_interface ? "interface" : "class"), IDENTIFIER_POINTER (qualified_name)); /* Scope of an interface/class type name: @@ -3400,7 +3363,7 @@ check_class_interface_creation (is_interface, flags, raw_name, qualified_name, d && (node = find_name_in_single_imports (raw_name)) && !CPC_INNER_P ()) { - parse_error_context + parse_error_context (cl, "%s name `%s' clashes with imported type `%s'", (is_interface ? "Interface" : "Class"), IDENTIFIER_POINTER (raw_name), IDENTIFIER_POINTER (node)); @@ -3408,7 +3371,7 @@ check_class_interface_creation (is_interface, flags, raw_name, qualified_name, d } if (decl && CLASS_COMPLETE_P (decl)) { - classitf_redefinition_error ((is_interface ? "Interface" : "Class"), + classitf_redefinition_error ((is_interface ? "Interface" : "Class"), qualified_name, decl, cl); return 1; } @@ -3422,18 +3385,17 @@ check_class_interface_creation (is_interface, flags, raw_name, qualified_name, d { const char *f; - /* Contains OS dependent assumption on path separator. FIXME */ - for (f = &input_filename [strlen (input_filename)]; - f != input_filename && f[0] != '/' && f[0] != DIR_SEPARATOR; + for (f = &input_filename [strlen (input_filename)]; + f != input_filename && ! IS_DIR_SEPARATOR (f[0]); f--) ; - if (f[0] == '/' || f[0] == DIR_SEPARATOR) + if (IS_DIR_SEPARATOR (f[0])) f++; - if (strncmp (IDENTIFIER_POINTER (raw_name), + if (strncmp (IDENTIFIER_POINTER (raw_name), f , IDENTIFIER_LENGTH (raw_name)) || f [IDENTIFIER_LENGTH (raw_name)] != '.') parse_error_context - (cl, "Public %s `%s' must be defined in a file called `%s.java'", + (cl, "Public %s `%s' must be defined in a file called `%s.java'", (is_interface ? "interface" : "class"), IDENTIFIER_POINTER (qualified_name), IDENTIFIER_POINTER (raw_name)); @@ -3448,7 +3410,7 @@ check_class_interface_creation (is_interface, flags, raw_name, qualified_name, d complaining a second time */ if (CPC_INNER_P () && !TOPLEVEL_CLASS_DECL_P (GET_CPC())) { - parse_error_context (cl, "Inner class `%s' can't be static. Static classes can only occur in interfaces and top-level classes", + parse_error_context (cl, "Inner class `%s' can't be static. Static classes can only occur in interfaces and top-level classes", IDENTIFIER_POINTER (qualified_name)); sca = ACC_STATIC; } @@ -3476,14 +3438,14 @@ check_class_interface_creation (is_interface, flags, raw_name, qualified_name, d } } - if (is_interface) + if (is_interface) { if (CPC_INNER_P ()) uaaf = INTERFACE_INNER_MODIFIERS; else uaaf = INTERFACE_MODIFIERS; - - check_modifiers ("Illegal modifier `%s' for interface declaration", + + check_modifiers ("Illegal modifier `%s' for interface declaration", flags, uaaf); } else @@ -3494,39 +3456,41 @@ check_class_interface_creation (is_interface, flags, raw_name, qualified_name, d return 0; } -static void -make_nested_class_name (cpc_list) - tree cpc_list; +/* Construct a nested class name. If the final component starts with + a digit, return true. Otherwise return false. */ +static int +make_nested_class_name (tree cpc_list) { tree name; if (!cpc_list) - return; - else - make_nested_class_name (TREE_CHAIN (cpc_list)); + return 0; + + make_nested_class_name (TREE_CHAIN (cpc_list)); /* Pick the qualified name when dealing with the first upmost enclosing class */ - name = (TREE_CHAIN (cpc_list) ? - TREE_PURPOSE (cpc_list) : DECL_NAME (TREE_VALUE (cpc_list))); + name = (TREE_CHAIN (cpc_list) + ? TREE_PURPOSE (cpc_list) : DECL_NAME (TREE_VALUE (cpc_list))); obstack_grow (&temporary_obstack, IDENTIFIER_POINTER (name), IDENTIFIER_LENGTH (name)); obstack_1grow (&temporary_obstack, '$'); + + return ISDIGIT (IDENTIFIER_POINTER (name)[0]); } /* Can't redefine a class already defined in an earlier scope. */ static int -check_inner_class_redefinition (raw_name, cl) - tree raw_name, cl; +check_inner_class_redefinition (tree raw_name, tree cl) { tree scope_list; - for (scope_list = GET_CPC_LIST (); scope_list; + for (scope_list = GET_CPC_LIST (); scope_list; scope_list = GET_NEXT_ENCLOSING_CPC (scope_list)) if (raw_name == GET_CPC_UN_NODE (scope_list)) { - parse_error_context + parse_error_context (cl, "The class name `%s' is already defined in this scope. An inner class may not have the same simple name as any of its enclosing classes", IDENTIFIER_POINTER (raw_name)); return 1; @@ -3538,9 +3502,8 @@ check_inner_class_redefinition (raw_name, cl) we remember ENCLOSING and SUPER. */ static tree -resolve_inner_class (circularity_hash, cl, enclosing, super, class_type) - struct hash_table *circularity_hash; - tree cl, *enclosing, *super, class_type; +resolve_inner_class (htab_t circularity_hash, tree cl, tree *enclosing, + tree *super, tree class_type) { tree local_enclosing = *enclosing; tree local_super = NULL_TREE; @@ -3549,8 +3512,8 @@ resolve_inner_class (circularity_hash, cl, enclosing, super, class_type) { tree intermediate, decl; - hash_lookup (circularity_hash, - (const hash_table_key) local_enclosing, TRUE, NULL); + *htab_find_slot (circularity_hash, local_enclosing, INSERT) = + local_enclosing; if ((decl = find_as_inner_class (local_enclosing, class_type, cl))) return decl; @@ -3564,9 +3527,16 @@ resolve_inner_class (circularity_hash, cl, enclosing, super, class_type) return decl; } - /* Now go to the upper classes, bail out if necessary. We will + /* Now go to the upper classes, bail out if necessary. We will analyze the returned SUPER and act accordingly (see - do_resolve_class.) */ + do_resolve_class). */ + if (JPRIMITIVE_TYPE_P (TREE_TYPE (local_enclosing)) + || TREE_TYPE (local_enclosing) == void_type_node) + { + parse_error_context (cl, "Qualifier must be a reference"); + local_enclosing = NULL_TREE; + break; + } local_super = CLASSTYPE_SUPER (TREE_TYPE (local_enclosing)); if (!local_super || local_super == object_type_node) break; @@ -3578,12 +3548,11 @@ resolve_inner_class (circularity_hash, cl, enclosing, super, class_type) /* We may not have checked for circular inheritance yet, so do so here to prevent an infinite loop. */ - if (hash_lookup (circularity_hash, - (const hash_table_key) local_super, FALSE, NULL)) + if (htab_find (circularity_hash, local_super) != NULL) { if (!cl) cl = lookup_cl (local_enclosing); - + parse_error_context (cl, "Cyclic inheritance involving %s", IDENTIFIER_POINTER (DECL_NAME (local_enclosing))); @@ -3604,8 +3573,7 @@ resolve_inner_class (circularity_hash, cl, enclosing, super, class_type) qualified. */ static tree -find_as_inner_class (enclosing, name, cl) - tree enclosing, name, cl; +find_as_inner_class (tree enclosing, tree name, tree cl) { tree qual, to_return; if (!enclosing) @@ -3620,7 +3588,7 @@ find_as_inner_class (enclosing, name, cl) qual = build_tree_list (cl, NULL_TREE); else qual = build_tree_list (build_expr_wfl (name, NULL, 0, 0), NULL_TREE); - + if ((to_return = find_as_inner_class_do (qual, enclosing))) return to_return; @@ -3630,10 +3598,10 @@ find_as_inner_class (enclosing, name, cl) { tree acc = NULL_TREE, decl = NULL_TREE, ptr; - for (qual = EXPR_WFL_QUALIFICATION (cl); qual && !decl; + for (qual = EXPR_WFL_QUALIFICATION (cl); qual && !decl; qual = TREE_CHAIN (qual)) { - acc = merge_qualified_name (acc, + acc = merge_qualified_name (acc, EXPR_WFL_NODE (TREE_PURPOSE (qual))); BUILD_PTR_FROM_NAME (ptr, acc); decl = do_resolve_class (NULL_TREE, ptr, NULL_TREE, cl); @@ -3641,7 +3609,7 @@ find_as_inner_class (enclosing, name, cl) /* A NULL qual and a decl means that the search ended successfully?!? We have to do something then. FIXME */ - + if (decl) enclosing = decl; else @@ -3650,7 +3618,7 @@ find_as_inner_class (enclosing, name, cl) /* Otherwise, create a qual for the other part of the resolution. */ else qual = build_tree_list (build_expr_wfl (name, NULL, 0, 0), NULL_TREE); - + return find_as_inner_class_do (qual, enclosing); } @@ -3658,8 +3626,7 @@ find_as_inner_class (enclosing, name, cl) through. */ static tree -find_as_inner_class_do (qual, enclosing) - tree qual, enclosing; +find_as_inner_class_do (tree qual, tree enclosing) { if (!qual) return NULL_TREE; @@ -3689,40 +3656,50 @@ find_as_inner_class_do (qual, enclosing) DECL. */ static void -set_nested_class_simple_name_value (outer, set) - tree outer; - int set; +set_nested_class_simple_name_value (tree outer, int set) { tree l; for (l = DECL_INNER_CLASS_LIST (outer); l; l = TREE_CHAIN (l)) - IDENTIFIER_GLOBAL_VALUE (TREE_VALUE (l)) = (set ? + IDENTIFIER_GLOBAL_VALUE (TREE_VALUE (l)) = (set ? TREE_PURPOSE (l) : NULL_TREE); } static void -link_nested_class_to_enclosing () +link_nested_class_to_enclosing (void) { if (GET_ENCLOSING_CPC ()) { tree enclosing = GET_ENCLOSING_CPC_CONTEXT (); - DECL_INNER_CLASS_LIST (enclosing) = + DECL_INNER_CLASS_LIST (enclosing) = tree_cons (GET_CPC (), GET_CPC_UN (), DECL_INNER_CLASS_LIST (enclosing)); } } static tree -maybe_make_nested_class_name (name) - tree name; +maybe_make_nested_class_name (tree name) { tree id = NULL_TREE; if (CPC_INNER_P ()) { - make_nested_class_name (GET_CPC_LIST ()); + /* If we're in a function, we must append a number to create the + nested class name. However, we don't do this if the class we + are constructing is anonymous, because in that case we'll + already have a number as the class name. */ + if (! make_nested_class_name (GET_CPC_LIST ()) + && current_function_decl != NULL_TREE + && ! ISDIGIT (IDENTIFIER_POINTER (name)[0])) + { + char buf[10]; + sprintf (buf, "%d", anonymous_class_counter); + ++anonymous_class_counter; + obstack_grow (&temporary_obstack, buf, strlen (buf)); + obstack_1grow (&temporary_obstack, '$'); + } obstack_grow0 (&temporary_obstack, - IDENTIFIER_POINTER (name), + IDENTIFIER_POINTER (name), IDENTIFIER_LENGTH (name)); id = get_identifier (obstack_finish (&temporary_obstack)); if (ctxp->package) @@ -3735,8 +3712,8 @@ maybe_make_nested_class_name (name) line CL and do other maintenance things. */ static tree -maybe_create_class_interface_decl (decl, raw_name, qualified_name, cl) - tree decl, raw_name, qualified_name, cl; +maybe_create_class_interface_decl (tree decl, tree raw_name, + tree qualified_name, tree cl) { if (!decl) decl = push_class (make_class (), qualified_name); @@ -3767,14 +3744,13 @@ maybe_create_class_interface_decl (decl, raw_name, qualified_name, cl) /* Install a new dependency list element */ create_jdep_list (ctxp); - SOURCE_FRONTEND_DEBUG (("Defining class/interface %s", + SOURCE_FRONTEND_DEBUG (("Defining class/interface %s", IDENTIFIER_POINTER (qualified_name))); return decl; } static void -add_superinterfaces (decl, interface_list) - tree decl, interface_list; +add_superinterfaces (tree decl, tree interface_list) { tree node; /* Superinterface(s): if present and defined, parser_check_super_interface () @@ -3803,9 +3779,7 @@ add_superinterfaces (decl, interface_list) interface's decl in pass 2. */ static tree -create_interface (flags, id, super) - int flags; - tree id, super; +create_interface (int flags, tree id, tree super) { tree raw_name = EXPR_WFL_NODE (id); tree q_name = parser_qualified_classname (raw_name); @@ -3818,7 +3792,7 @@ create_interface (flags, id, super) EXPR_WFL_NODE (id) = q_name; /* Keep source location, even if refined. */ - /* Basic checks: scope, redefinition, modifiers */ + /* Basic checks: scope, redefinition, modifiers */ if (check_class_interface_creation (1, flags, raw_name, q_name, decl, id)) { PUSH_ERROR (); @@ -3843,7 +3817,7 @@ create_interface (flags, id, super) - abstract is obsolete (comes first, it's a warning, or should be) - Can't use twice the same (checked in the modifier rule) */ if ((flags & ACC_ABSTRACT) && flag_redundant) - parse_warning_context + parse_warning_context (MODIFIER_WFL (ABSTRACT_TK), "Redundant use of `abstract' modifier. Interface `%s' is implicitly abstract", IDENTIFIER_POINTER (raw_name)); @@ -3851,25 +3825,23 @@ create_interface (flags, id, super) decl = maybe_create_class_interface_decl (decl, raw_name, q_name, id); /* Set super info and mark the class a complete */ - set_super_info (ACC_INTERFACE | flags, TREE_TYPE (decl), + set_super_info (ACC_INTERFACE | flags, TREE_TYPE (decl), object_type_node, ctxp->interface_number); ctxp->interface_number = 0; CLASS_COMPLETE_P (decl) = 1; add_superinterfaces (decl, super); + /* Eventually sets the @deprecated tag flag */ + CHECK_DEPRECATED (decl); + return decl; } -/* Anonymous class counter. Will be reset to 1 every time a non - anonymous class gets created. */ -static int anonymous_class_counter = 1; - /* Patch anonymous class CLASS, by either extending or implementing DEP. */ static void -patch_anonymous_class (type_decl, class_decl, wfl) - tree type_decl, class_decl, wfl; +patch_anonymous_class (tree type_decl, tree class_decl, tree wfl) { tree class = TREE_TYPE (class_decl); tree type = TREE_TYPE (type_decl); @@ -3901,9 +3873,7 @@ patch_anonymous_class (type_decl, class_decl, wfl) } static tree -create_anonymous_class (location, type_name) - int location; - tree type_name; +create_anonymous_class (int location, tree type_name) { char buffer [80]; tree super = NULL_TREE, itf = NULL_TREE; @@ -3945,9 +3915,7 @@ create_anonymous_class (location, type_name) interface's decl in pass 2. */ static tree -create_class (flags, id, super, interfaces) - int flags; - tree id, super, interfaces; +create_class (int flags, tree id, tree super, tree interfaces) { tree raw_name = EXPR_WFL_NODE (id); tree class_id, decl; @@ -3968,7 +3936,7 @@ create_class (flags, id, super, interfaces) PUSH_ERROR (); return NULL_TREE; } - + /* Suspend the current parsing context if we're parsing an inner class or an anonymous class. */ if (CPC_INNER_P ()) @@ -3978,13 +3946,13 @@ create_class (flags, id, super, interfaces) if (CLASS_INTERFACE (GET_CPC ())) flags |= ACC_PUBLIC; } - + /* Push a new context for (static) initialized upon declaration fields */ java_parser_context_push_initialized_field (); - /* Class modifier check: + /* Class modifier check: - Allowed modifier (already done at that point) - - abstract AND final forbidden + - abstract AND final forbidden - Public classes defined in the correct file */ if ((flags & ACC_ABSTRACT) && (flags & ACC_FINAL)) parse_error_context @@ -4004,7 +3972,7 @@ create_class (flags, id, super, interfaces) return NULL_TREE; } - super_decl_type = + super_decl_type = register_incomplete_type (JDEP_SUPER, super, decl, NULL_TREE); } else if (TREE_TYPE (decl) != object_type_node) @@ -4021,7 +3989,7 @@ create_class (flags, id, super, interfaces) } /* Set super info and mark the class as complete. */ - set_super_info (flags, TREE_TYPE (decl), super_decl_type, + set_super_info (flags, TREE_TYPE (decl), super_decl_type, ctxp->interface_number); ctxp->interface_number = 0; CLASS_COMPLETE_P (decl) = 1; @@ -4053,13 +4021,15 @@ create_class (flags, id, super, interfaces) parser context if necessary. */ static void -end_class_declaration (resume) - int resume; +end_class_declaration (int resume) { /* If an error occurred, context weren't pushed and won't need to be popped by a resume. */ int no_error_occurred = ctxp->next && GET_CPC () != error_mark_node; + if (GET_CPC () != error_mark_node) + dump_java_tree (TDI_class, GET_CPC ()); + java_parser_context_pop_initialized_field (); POP_CPC (); if (resume && no_error_occurred) @@ -4074,22 +4044,20 @@ end_class_declaration (resume) } static void -add_inner_class_fields (class_decl, fct_decl) - tree class_decl; - tree fct_decl; +add_inner_class_fields (tree class_decl, tree fct_decl) { tree block, marker, f; f = add_field (TREE_TYPE (class_decl), build_current_thisn (TREE_TYPE (class_decl)), - build_pointer_type (TREE_TYPE (DECL_CONTEXT (class_decl))), + build_pointer_type (TREE_TYPE (DECL_CONTEXT (class_decl))), ACC_PRIVATE); FIELD_THISN (f) = 1; if (!fct_decl) return; - - for (block = GET_CURRENT_BLOCK (fct_decl); + + for (block = GET_CURRENT_BLOCK (fct_decl); block && TREE_CODE (block) == BLOCK; block = BLOCK_SUPERCONTEXT (block)) { tree decl; @@ -4097,11 +4065,11 @@ add_inner_class_fields (class_decl, fct_decl) { tree name, pname; tree wfl, init, list; - + /* Avoid non final arguments. */ if (!LOCAL_FINAL_P (decl)) continue; - + MANGLE_OUTER_LOCAL_VARIABLE_NAME (name, DECL_NAME (decl)); MANGLE_ALIAS_INITIALIZER_PARAMETER_NAME_ID (pname, DECL_NAME (decl)); wfl = build_wfl_node (name); @@ -4113,7 +4081,7 @@ add_inner_class_fields (class_decl, fct_decl) invoking it (hence the constructor will also feature a hidden parameter, set to the value of the outer context local at the time the inner class is created.) - + Note: we take into account all possible locals that can be accessed by the inner class. It's actually not trivial to minimize these aliases down to the ones really @@ -4128,14 +4096,14 @@ add_inner_class_fields (class_decl, fct_decl) identify locals really used in the inner class. We leave the flag FIELD_LOCAL_ALIAS_USED around for that future use. - + On the other hand, it only affect local inner classes, whose constructors (and finit$ call) will be featuring unecessary arguments. It's easy for a developper to keep this number of parameter down by using the `final' keyword only when necessary. For the time being, we can issue a warning on unecessary finals. FIXME */ - init = build_assignment (ASSIGN_TK, EXPR_WFL_LINECOL (wfl), + init = build_assignment (ASSIGN_TK, EXPR_WFL_LINECOL (wfl), wfl, init); /* Register the field. The TREE_LIST holding the part @@ -4164,9 +4132,7 @@ add_inner_class_fields (class_decl, fct_decl) can't set the CLASS_LOADED_P flag */ static tree -find_field (class, name) - tree class; - tree name; +find_field (tree class, tree name) { tree decl; for (decl = TYPE_FIELDS (class); decl; decl = TREE_CHAIN (decl)) @@ -4181,8 +4147,7 @@ find_field (class, name) of CLASS */ static tree -lookup_field_wrapper (class, name) - tree class, name; +lookup_field_wrapper (tree class, tree name) { tree type = class; tree decl = NULL_TREE; @@ -4205,6 +4170,13 @@ lookup_field_wrapper (class, name) decl = lookup_field (&type, name); } + /* If the field still hasn't been found, try the next enclosing context. */ + if (!decl && INNER_CLASS_TYPE_P (class)) + { + tree outer_type = TREE_TYPE (DECL_CONTEXT (TYPE_NAME (class))); + decl = lookup_field_wrapper (outer_type, name); + } + java_parser_context_restore_global (); return decl == error_mark_node ? NULL : decl; } @@ -4214,27 +4186,26 @@ lookup_field_wrapper (class, name) otherwise. */ static int -duplicate_declaration_error_p (new_field_name, new_type, cl) - tree new_field_name, new_type, cl; +duplicate_declaration_error_p (tree new_field_name, tree new_type, tree cl) { /* This might be modified to work with method decl as well */ tree decl = find_field (TREE_TYPE (GET_CPC ()), new_field_name); if (decl) { char *t1 = xstrdup (purify_type_name - ((TREE_CODE (new_type) == POINTER_TYPE + ((TREE_CODE (new_type) == POINTER_TYPE && TREE_TYPE (new_type) == NULL_TREE) ? IDENTIFIER_POINTER (TYPE_NAME (new_type)) : lang_printable_name (new_type, 1))); /* The type may not have been completed by the time we report the error */ char *t2 = xstrdup (purify_type_name - ((TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE + ((TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE && TREE_TYPE (TREE_TYPE (decl)) == NULL_TREE) ? IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (decl))) : lang_printable_name (TREE_TYPE (decl), 1))); - parse_error_context - (cl , "Duplicate variable declaration: `%s %s' was `%s %s' (%s:%d)", + parse_error_context + (cl , "Duplicate variable declaration: `%s %s' was `%s %s' (%s:%d)", t1, IDENTIFIER_POINTER (new_field_name), t2, IDENTIFIER_POINTER (DECL_NAME (decl)), DECL_SOURCE_FILE (decl), DECL_SOURCE_LINE (decl)); @@ -4250,13 +4221,11 @@ duplicate_declaration_error_p (new_field_name, new_type, cl) be later resolved in java_complete_class () */ static void -register_fields (flags, type, variable_list) - int flags; - tree type, variable_list; +register_fields (int flags, tree type, tree variable_list) { tree current, saved_type; tree class_type = NULL_TREE; - int saved_lineno = lineno; + int saved_lineno = input_line; int must_chain = 0; tree wfl = NULL_TREE; @@ -4287,7 +4256,7 @@ register_fields (flags, type, variable_list) /* If TYPE is fully resolved and we don't have a reference, make one */ PROMOTE_RECORD_IF_COMPLETE (type, must_chain); - for (current = variable_list, saved_type = type; current; + for (current = variable_list, saved_type = type; current; current = TREE_CHAIN (current), type = saved_type) { tree real_type; @@ -4299,7 +4268,7 @@ register_fields (flags, type, variable_list) /* Can't declare non-final static fields in inner classes */ if ((flags & ACC_STATIC) && !TOPLEVEL_CLASS_TYPE_P (class_type) && !(flags & ACC_FINAL)) - parse_error_context + parse_error_context (cl, "Field `%s' can't be static in inner class `%s' unless it is final", IDENTIFIER_POINTER (EXPR_WFL_NODE (cl)), lang_printable_name (class_type, 0)); @@ -4326,11 +4295,11 @@ register_fields (flags, type, variable_list) /* Set lineno to the line the field was found and create a declaration for it. Eventually sets the @deprecated tag flag. */ if (flag_emit_xref) - lineno = EXPR_WFL_LINECOL (cl); + input_line = EXPR_WFL_LINECOL (cl); else - lineno = EXPR_WFL_LINENO (cl); + input_line = EXPR_WFL_LINENO (cl); field_decl = add_field (class_type, current_name, real_type, flags); - CHECK_DEPRECATED (field_decl); + CHECK_DEPRECATED_NO_RESET (field_decl); /* If the field denotes a final instance variable, then we allocate a LANG_DECL_SPECIFIC part to keep track of its @@ -4353,11 +4322,11 @@ register_fields (flags, type, variable_list) FIELD_LOCAL_ALIAS (field_decl) = 1; FIELD_FINAL (field_decl) = 0; } - + /* Check if we must chain. */ if (must_chain) register_incomplete_type (JDEP_FIELD, wfl, field_decl, type); - + /* If we have an initialization value tied to the field */ if (init) { @@ -4372,7 +4341,7 @@ register_fields (flags, type, variable_list) appropriately. */ TREE_CHAIN (init) = CPC_STATIC_INITIALIZER_STMT (ctxp); SET_CPC_STATIC_INITIALIZER_STMT (ctxp, init); - if (TREE_OPERAND (init, 1) + if (TREE_OPERAND (init, 1) && TREE_CODE (TREE_OPERAND (init, 1)) == NEW_ARRAY_INIT) TREE_STATIC (TREE_OPERAND (init, 1)) = 1; } @@ -4388,7 +4357,9 @@ register_fields (flags, type, variable_list) DECL_INITIAL (field_decl) = TREE_OPERAND (init, 1); } } - lineno = saved_lineno; + + CLEAR_DEPRECATED; + input_line = saved_lineno; } /* Generate finit$, using the list of initialized fields to populate @@ -4397,15 +4368,14 @@ register_fields (flags, type, variable_list) local(s). */ static tree -generate_finit (class_type) - tree class_type; +generate_finit (tree class_type) { int count = 0; tree list = TYPE_FINIT_STMT_LIST (class_type); tree mdecl, current, parms; - parms = build_alias_initializer_parameter_list (AIPL_FUNCTION_CREATION, - class_type, NULL_TREE, + parms = build_alias_initializer_parameter_list (AIPL_FUNCTION_CREATION, + class_type, NULL_TREE, &count); CRAFTED_PARAM_LIST_FIXUP (parms); mdecl = create_artificial_method (class_type, ACC_PRIVATE, void_type_node, @@ -4417,8 +4387,8 @@ generate_finit (class_type) start_artificial_method_body (mdecl); for (current = list; current; current = TREE_CHAIN (current)) - java_method_add_stmt (mdecl, - build_debugable_stmt (EXPR_WFL_LINECOL (current), + java_method_add_stmt (mdecl, + build_debugable_stmt (EXPR_WFL_LINECOL (current), current)); end_artificial_method_body (mdecl); return mdecl; @@ -4432,8 +4402,7 @@ generate_finit (class_type) statements in a try/catch/rethrow sequence. */ static tree -generate_instinit (class_type) - tree class_type; +generate_instinit (tree class_type) { tree current; tree compound = NULL_TREE; @@ -4447,7 +4416,7 @@ generate_instinit (class_type) mdecl, NULL_TREE); /* Gather all the statements in a compound */ - for (current = TYPE_II_STMT_LIST (class_type); + for (current = TYPE_II_STMT_LIST (class_type); current; current = TREE_CHAIN (current)) compound = add_stmt_to_compound (compound, NULL_TREE, current); @@ -4456,10 +4425,10 @@ generate_instinit (class_type) We do that only if all ctors of CLASS_TYPE are set to catch a checked exception. This doesn't apply to anonymous classes (since they don't have declared ctors.) */ - if (!ANONYMOUS_CLASS_P (class_type) && + if (!ANONYMOUS_CLASS_P (class_type) && ctors_unchecked_throws_clause_p (class_type)) { - compound = encapsulate_with_try_catch (0, exception_type_node, compound, + compound = encapsulate_with_try_catch (0, exception_type_node, compound, build1 (THROW_EXPR, NULL_TREE, build_wfl_node (wpv_id))); DECL_FUNCTION_THROWS (mdecl) = build_tree_list (NULL_TREE, @@ -4475,8 +4444,7 @@ generate_instinit (class_type) /* FIXME */ static tree -build_instinit_invocation (class_type) - tree class_type; +build_instinit_invocation (tree class_type) { tree to_return = NULL_TREE; @@ -4506,9 +4474,7 @@ static int patch_stage; with a constructor. */ static tree -method_header (flags, type, mdecl, throws) - int flags; - tree type, mdecl, throws; +method_header (int flags, tree type, tree mdecl, tree throws) { tree type_wfl = NULL_TREE; tree meth_name = NULL_TREE; @@ -4522,7 +4488,7 @@ method_header (flags, type, mdecl, throws) return error_mark_node; meth = TREE_VALUE (mdecl); id = TREE_PURPOSE (mdecl); - + check_modifiers_consistency (flags); if (GET_CPC ()) @@ -4530,7 +4496,7 @@ method_header (flags, type, mdecl, throws) if (!this_class || this_class == error_mark_node) return NULL_TREE; - + /* There are some forbidden modifiers for an abstract method and its class must be abstract as well. */ if (type && (flags & ACC_ABSTRACT)) @@ -4539,15 +4505,28 @@ method_header (flags, type, mdecl, throws) ABSTRACT_CHECK (flags, ACC_STATIC, id, "Static"); ABSTRACT_CHECK (flags, ACC_FINAL, id, "Final"); ABSTRACT_CHECK (flags, ACC_NATIVE, id, "Native"); - ABSTRACT_CHECK (flags, ACC_SYNCHRONIZED,id, "Synchronized"); + ABSTRACT_CHECK (flags, ACC_SYNCHRONIZED, id, "Synchronized"); + ABSTRACT_CHECK (flags, ACC_STRICT, id, "Strictfp"); if (!CLASS_ABSTRACT (TYPE_NAME (this_class)) && !CLASS_INTERFACE (TYPE_NAME (this_class))) - parse_error_context - (id, "Class `%s' must be declared abstract to define abstract method `%s'", + parse_error_context + (id, "Class `%s' must be declared abstract to define abstract method `%s'", IDENTIFIER_POINTER (DECL_NAME (GET_CPC ())), IDENTIFIER_POINTER (EXPR_WFL_NODE (id))); } + /* A native method can't be strictfp. */ + if ((flags & ACC_NATIVE) && (flags & ACC_STRICT)) + parse_error_context (id, "native method `%s' can't be strictfp", + IDENTIFIER_POINTER (EXPR_WFL_NODE (id))); + /* No such thing as a transient or volatile method. */ + if ((flags & ACC_TRANSIENT)) + parse_error_context (id, "method `%s' can't be transient", + IDENTIFIER_POINTER (EXPR_WFL_NODE (id))); + if ((flags & ACC_VOLATILE)) + parse_error_context (id, "method `%s' can't be volatile", + IDENTIFIER_POINTER (EXPR_WFL_NODE (id))); + /* Things to be checked when declaring a constructor */ if (!type) { @@ -4555,7 +4534,7 @@ method_header (flags, type, mdecl, throws) /* 8.6: Constructor declarations: we might be trying to define a method without specifying a return type. */ if (EXPR_WFL_NODE (id) != GET_CPC_UN ()) - parse_error_context + parse_error_context (id, "Invalid method declaration, return type required"); /* 8.6.3: Constructor modifiers */ else @@ -4565,6 +4544,7 @@ method_header (flags, type, mdecl, throws) JCONSTRUCTOR_CHECK (flags, ACC_FINAL, id, "final"); JCONSTRUCTOR_CHECK (flags, ACC_NATIVE, id, "native"); JCONSTRUCTOR_CHECK (flags, ACC_SYNCHRONIZED, id, "synchronized"); + JCONSTRUCTOR_CHECK (flags, ACC_STRICT, id, "strictfp"); } /* If we found error here, we don't consider it's OK to tread the method definition as a constructor, for the rest of this @@ -4593,7 +4573,7 @@ method_header (flags, type, mdecl, throws) /* Inner class can't declare static methods */ if ((flags & ACC_STATIC) && !TOPLEVEL_CLASS_TYPE_P (this_class)) { - parse_error_context + parse_error_context (id, "Method `%s' can't be static in inner class `%s'. Only members of interfaces and top-level classes can be static", IDENTIFIER_POINTER (EXPR_WFL_NODE (id)), lang_printable_name (this_class, 0)); @@ -4631,11 +4611,11 @@ method_header (flags, type, mdecl, throws) else TREE_TYPE (meth) = type; - saved_lineno = lineno; + saved_lineno = input_line; /* When defining an abstract or interface method, the curly bracket at level 1 doesn't exist because there is no function body */ - lineno = (ctxp->first_ccb_indent1 ? ctxp->first_ccb_indent1 : + input_line = (ctxp->first_ccb_indent1 ? ctxp->first_ccb_indent1 : EXPR_WFL_LINENO (id)); /* Remember the original argument list */ @@ -4656,7 +4636,7 @@ method_header (flags, type, mdecl, throws) register_incomplete_type (JDEP_METHOD_END, NULL_TREE, meth, NULL_TREE); } else - meth = add_method (this_class, flags, meth_name, + meth = add_method (this_class, flags, meth_name, build_java_signature (meth)); /* Remember final parameters */ @@ -4669,7 +4649,7 @@ method_header (flags, type, mdecl, throws) /* Register the parameter number and re-install the current line number */ DECL_MAX_LOCALS (meth) = ctxp->formal_parameter_number+1; - lineno = saved_lineno; + input_line = saved_lineno; /* Register exception specified by the `throws' keyword for resolution and set the method decl appropriate field to the list. @@ -4682,7 +4662,7 @@ method_header (flags, type, mdecl, throws) { register_incomplete_type (JDEP_EXCEPTION, TREE_VALUE (current), NULL_TREE, NULL_TREE); - JDEP_GET_PATCH (CLASSD_LAST (ctxp->classd_list)) = + JDEP_GET_PATCH (CLASSD_LAST (ctxp->classd_list)) = &TREE_VALUE (current); } DECL_FUNCTION_THROWS (meth) = throws; @@ -4697,7 +4677,7 @@ method_header (flags, type, mdecl, throws) DECL_CONSTRUCTOR_P (meth) = 1; /* Compute and store the number of artificial parameters declared for this constructor */ - for (count = 0, current = TYPE_FIELDS (this_class); current; + for (count = 0, current = TYPE_FIELDS (this_class); current; current = TREE_CHAIN (current)) if (FIELD_LOCAL_ALIAS (current)) count++; @@ -4716,8 +4696,7 @@ method_header (flags, type, mdecl, throws) } static void -fix_method_argument_names (orig_arg, meth) - tree orig_arg, meth; +fix_method_argument_names (tree orig_arg, tree meth) { tree arg = TYPE_ARG_TYPES (TREE_TYPE (meth)); if (TREE_CODE (TREE_TYPE (meth)) == METHOD_TYPE) @@ -4736,8 +4715,7 @@ fix_method_argument_names (orig_arg, meth) /* Complete the method declaration with METHOD_BODY. */ static void -finish_method_declaration (method_body) - tree method_body; +finish_method_declaration (tree method_body) { int flags; @@ -4750,7 +4728,7 @@ finish_method_declaration (method_body) if ((flags & ACC_ABSTRACT || flags & ACC_NATIVE) && method_body) { tree name = DECL_NAME (current_function_decl); - parse_error_context (DECL_FUNCTION_WFL (current_function_decl), + parse_error_context (DECL_FUNCTION_WFL (current_function_decl), "%s method `%s' can't have a body defined", (METHOD_NATIVE (current_function_decl) ? "Native" : "Abstract"), @@ -4761,15 +4739,15 @@ finish_method_declaration (method_body) { tree name = DECL_NAME (current_function_decl); parse_error_context - (DECL_FUNCTION_WFL (current_function_decl), + (DECL_FUNCTION_WFL (current_function_decl), "Non native and non abstract method `%s' must have a body defined", IDENTIFIER_POINTER (name)); method_body = NULL_TREE; } - if (flag_emit_class_files && method_body - && TREE_CODE (method_body) == NOP_EXPR - && TREE_TYPE (current_function_decl) + if (flag_emit_class_files && method_body + && TREE_CODE (method_body) == NOP_EXPR + && TREE_TYPE (current_function_decl) && TREE_TYPE (TREE_TYPE (current_function_decl)) == void_type_node) method_body = build1 (RETURN_EXPR, void_type_node, NULL); @@ -4786,7 +4764,7 @@ finish_method_declaration (method_body) ARG_FINAL_P parameter that might have been set on some of this function parameters. */ UNMARK_FINAL_PARMS (current_function_decl); - + /* So we don't have an irrelevant function declaration context for the next static block we'll see. */ current_function_decl = NULL_TREE; @@ -4795,8 +4773,7 @@ finish_method_declaration (method_body) /* Build a an error message for constructor circularity errors. */ static char * -constructor_circularity_msg (from, to) - tree from, to; +constructor_circularity_msg (tree from, tree to) { static char string [4096]; char *t = xstrdup (lang_printable_name (from, 0)); @@ -4808,55 +4785,45 @@ constructor_circularity_msg (from, to) /* Verify a circular call to METH. Return 1 if an error is found, 0 otherwise. */ +static GTY(()) tree vcc_list; static int -verify_constructor_circularity (meth, current) - tree meth, current; +verify_constructor_circularity (tree meth, tree current) { - static tree list = NULL_TREE; - static int initialized_p; tree c; - /* If we haven't already registered LIST with the garbage collector, - do so now. */ - if (!initialized_p) - { - ggc_add_tree_root (&list, 1); - initialized_p = 1; - } - for (c = DECL_CONSTRUCTOR_CALLS (current); c; c = TREE_CHAIN (c)) { if (TREE_VALUE (c) == meth) { char *t; - if (list) + if (vcc_list) { tree liste; - list = nreverse (list); - for (liste = list; liste; liste = TREE_CHAIN (liste)) + vcc_list = nreverse (vcc_list); + for (liste = vcc_list; liste; liste = TREE_CHAIN (liste)) { - parse_error_context + parse_error_context (TREE_PURPOSE (TREE_PURPOSE (liste)), "%s", constructor_circularity_msg - (TREE_VALUE (liste), TREE_VALUE (TREE_PURPOSE (liste)))); + (TREE_VALUE (liste), TREE_VALUE (TREE_PURPOSE (liste)))); java_error_count--; } } t = xstrdup (lang_printable_name (meth, 0)); - parse_error_context (TREE_PURPOSE (c), + parse_error_context (TREE_PURPOSE (c), "%s: recursive invocation of constructor `%s'", constructor_circularity_msg (current, meth), t); free (t); - list = NULL_TREE; + vcc_list = NULL_TREE; return 1; } } for (c = DECL_CONSTRUCTOR_CALLS (current); c; c = TREE_CHAIN (c)) { - list = tree_cons (c, current, list); + vcc_list = tree_cons (c, current, vcc_list); if (verify_constructor_circularity (meth, TREE_VALUE (c))) return 1; - list = TREE_CHAIN (list); + vcc_list = TREE_CHAIN (vcc_list); } return 0; } @@ -4864,8 +4831,7 @@ verify_constructor_circularity (meth, current) /* Check modifiers that can be declared but exclusively */ static void -check_modifiers_consistency (flags) - int flags; +check_modifiers_consistency (int flags) { int acc_count = 0; tree cl = NULL_TREE; @@ -4889,15 +4855,14 @@ check_modifiers_consistency (flags) /* Check the methode header METH for abstract specifics features */ static void -check_abstract_method_header (meth) - tree meth; +check_abstract_method_header (tree meth) { int flags = get_access_flags_from_decl (meth); OBSOLETE_MODIFIER_WARNING2 (MODIFIER_WFL (ABSTRACT_TK), flags, ACC_ABSTRACT, "abstract method", IDENTIFIER_POINTER (DECL_NAME (meth))); - OBSOLETE_MODIFIER_WARNING2 (MODIFIER_WFL (PUBLIC_TK), flags, + OBSOLETE_MODIFIER_WARNING2 (MODIFIER_WFL (PUBLIC_TK), flags, ACC_PUBLIC, "abstract method", IDENTIFIER_POINTER (DECL_NAME (meth))); @@ -4911,8 +4876,7 @@ check_abstract_method_header (meth) incomplete types. */ static tree -method_declarator (id, list) - tree id, list; +method_declarator (tree id, tree list) { tree arg_types = NULL_TREE, current, node; tree meth = make_node (FUNCTION_TYPE); @@ -4927,13 +4891,13 @@ method_declarator (id, list) this$ decl in the name field of its parameter declaration. We also might have to hide the outer context local alias initializers. Not done when the class is a toplevel class. */ - if (PURE_INNER_CLASS_DECL_P (GET_CPC ()) + if (PURE_INNER_CLASS_DECL_P (GET_CPC ()) && EXPR_WFL_NODE (id) == GET_CPC_UN ()) { tree aliases_list, type, thisn; /* First the aliases, linked to the regular parameters */ aliases_list = - build_alias_initializer_parameter_list (AIPL_FUNCTION_DECLARATION, + build_alias_initializer_parameter_list (AIPL_FUNCTION_DECLARATION, TREE_TYPE (GET_CPC ()), NULL_TREE, NULL); list = chainon (nreverse (aliases_list), list); @@ -4944,7 +4908,7 @@ method_declarator (id, list) list = tree_cons (build_wfl_node (thisn), build_pointer_type (type), list); } - + for (current = list; current; current = TREE_CHAIN (current)) { int must_chain = 0; @@ -4987,7 +4951,7 @@ method_declarator (id, list) if (must_chain) { patch_stage = JDEP_METHOD; - type = register_incomplete_type (patch_stage, + type = register_incomplete_type (patch_stage, type_wfl, wfl_name, type); jdep = CLASSD_LAST (ctxp->classd_list); JDEP_MISC (jdep) = id; @@ -4997,7 +4961,7 @@ method_declarator (id, list) arg_node = build_tree_list (name, real_type); /* Remeber arguments declared final. */ ARG_FINAL_P (arg_node) = ARG_FINAL_P (current); - + if (jdep) JDEP_GET_PATCH (jdep) = &TREE_VALUE (arg_node); TREE_CHAIN (arg_node) = arg_types; @@ -5009,10 +4973,8 @@ method_declarator (id, list) } static int -unresolved_type_p (wfl, returned) - tree wfl; - tree *returned; - +unresolved_type_p (tree wfl, tree *returned) + { if (TREE_CODE (wfl) == EXPR_WITH_FILE_LOCATION) { @@ -5037,8 +4999,7 @@ unresolved_type_p (wfl, returned) qualification from the current package definition. */ static tree -parser_qualified_classname (name) - tree name; +parser_qualified_classname (tree name) { tree nested_class_name; @@ -5047,7 +5008,7 @@ parser_qualified_classname (name) if (ctxp->package) return merge_qualified_name (ctxp->package, name); - else + else return name; } @@ -5055,25 +5016,24 @@ parser_qualified_classname (name) everything is OK. */ static int -parser_check_super_interface (super_decl, this_decl, this_wfl) - tree super_decl, this_decl, this_wfl; +parser_check_super_interface (tree super_decl, tree this_decl, tree this_wfl) { tree super_type = TREE_TYPE (super_decl); /* Has to be an interface */ if (!CLASS_INTERFACE (super_decl)) { - parse_error_context - (this_wfl, "Can't use %s `%s' to implement/extend %s `%s'", + parse_error_context + (this_wfl, "%s `%s' can't implement/extend %s `%s'", + (CLASS_INTERFACE (TYPE_NAME (TREE_TYPE (this_decl))) ? + "Interface" : "Class"), + IDENTIFIER_POINTER (DECL_NAME (this_decl)), (TYPE_ARRAY_P (super_type) ? "array" : "class"), - IDENTIFIER_POINTER (DECL_NAME (super_decl)), - (CLASS_INTERFACE (TYPE_NAME (TREE_TYPE (this_decl))) ? - "interface" : "class"), - IDENTIFIER_POINTER (DECL_NAME (this_decl))); + IDENTIFIER_POINTER (DECL_NAME (super_decl))); return 1; } - /* Check top-level interface access. Inner classes are subject to member + /* Check top-level interface access. Inner classes are subject to member access rules (6.6.1). */ if (! INNER_CLASS_P (super_type) && check_pkg_class_access (DECL_NAME (super_decl), @@ -5090,15 +5050,14 @@ parser_check_super_interface (super_decl, this_decl, this_wfl) 0 if everthing is OK. */ static int -parser_check_super (super_decl, this_decl, wfl) - tree super_decl, this_decl, wfl; +parser_check_super (tree super_decl, tree this_decl, tree wfl) { tree super_type = TREE_TYPE (super_decl); /* SUPER should be a CLASS (neither an array nor an interface) */ if (TYPE_ARRAY_P (super_type) || CLASS_INTERFACE (TYPE_NAME (super_type))) { - parse_error_context + parse_error_context (wfl, "Class `%s' can't subclass %s `%s'", IDENTIFIER_POINTER (DECL_NAME (this_decl)), (CLASS_INTERFACE (TYPE_NAME (super_type)) ? "interface" : "array"), @@ -5118,7 +5077,7 @@ parser_check_super (super_decl, this_decl, wfl) if (! INNER_CLASS_P (super_type) && (check_pkg_class_access (DECL_NAME (super_decl), wfl, true))) return 1; - + SOURCE_FRONTEND_DEBUG (("Completing class %s with %s", IDENTIFIER_POINTER (DECL_NAME (this_decl)), IDENTIFIER_POINTER (DECL_NAME (super_decl)))); @@ -5129,18 +5088,16 @@ parser_check_super (super_decl, this_decl, wfl) CTXP list of type dependency list. */ static void -create_jdep_list (ctxp) - struct parser_ctxt *ctxp; +create_jdep_list (struct parser_ctxt *ctxp) { - jdeplist *new = (jdeplist *)xmalloc (sizeof (jdeplist)); + jdeplist *new = xmalloc (sizeof (jdeplist)); new->first = new->last = NULL; new->next = ctxp->classd_list; ctxp->classd_list = new; } static jdeplist * -reverse_jdep_list (ctxp) - struct parser_ctxt *ctxp; +reverse_jdep_list (struct parser_ctxt *ctxp) { register jdeplist *prev = NULL, *current, *next; for (current = ctxp->classd_list; current; current = next) @@ -5157,8 +5114,7 @@ reverse_jdep_list (ctxp) registered again. */ static tree -obtain_incomplete_type (type_name) - tree type_name; +obtain_incomplete_type (tree type_name) { tree ptr = NULL_TREE, name; @@ -5169,7 +5125,9 @@ obtain_incomplete_type (type_name) else abort (); + /* Workaround from build_pointer_type for incomplete types. */ BUILD_PTR_FROM_NAME (ptr, name); + TYPE_MODE (ptr) = ptr_mode; layout_type (ptr); return ptr; @@ -5181,11 +5139,9 @@ obtain_incomplete_type (type_name) manner. */ static tree -register_incomplete_type (kind, wfl, decl, ptr) - int kind; - tree wfl, decl, ptr; +register_incomplete_type (int kind, tree wfl, tree decl, tree ptr) { - jdep *new = (jdep *)xmalloc (sizeof (jdep)); + jdep *new = xmalloc (sizeof (jdep)); if (!ptr && kind != JDEP_METHOD_END) /* JDEP_METHOD_END is a mere marker */ ptr = obtain_incomplete_type (wfl); @@ -5202,7 +5158,7 @@ register_incomplete_type (kind, wfl, decl, ptr) && GET_ENCLOSING_CPC ()) JDEP_ENCLOSING (new) = TREE_VALUE (GET_ENCLOSING_CPC ()); else if (kind == JDEP_SUPER) - JDEP_ENCLOSING (new) = (GET_ENCLOSING_CPC () ? + JDEP_ENCLOSING (new) = (GET_ENCLOSING_CPC () ? TREE_VALUE (GET_ENCLOSING_CPC ()) : NULL_TREE); else JDEP_ENCLOSING (new) = GET_CPC (); @@ -5222,9 +5178,7 @@ register_incomplete_type (kind, wfl, decl, ptr) otherwise. */ static tree -check_inner_circular_reference (source, target) - tree source; - tree target; +check_inner_circular_reference (tree source, tree target) { tree basetype_vec = TYPE_BINFO_BASETYPES (source); tree ctx, cl; @@ -5232,14 +5186,23 @@ check_inner_circular_reference (source, target) if (!basetype_vec) return NULL_TREE; - + for (i = 0; i < TREE_VEC_LENGTH (basetype_vec); i++) { - tree su = BINFO_TYPE (TREE_VEC_ELT (basetype_vec, i)); + tree su; + + /* We can end up with a NULL_TREE or an incomplete type here if + we encountered previous type resolution errors. It's safe to + simply ignore these cases. */ + if (TREE_VEC_ELT (basetype_vec, i) == NULL_TREE) + continue; + su = BINFO_TYPE (TREE_VEC_ELT (basetype_vec, i)); + if (INCOMPLETE_TYPE_P (su)) + continue; if (inherits_from_p (su, target)) return lookup_cl (TYPE_NAME (su)); - + for (ctx = DECL_CONTEXT (TYPE_NAME (su)); ctx; ctx = DECL_CONTEXT (ctx)) { /* An enclosing context shouldn't be TARGET */ @@ -5261,8 +5224,7 @@ check_inner_circular_reference (source, target) otherwise. TYPE can be an interface or a class. */ static tree -check_circular_reference (type) - tree type; +check_circular_reference (tree type) { tree basetype_vec = TYPE_BINFO_BASETYPES (type); int i; @@ -5276,7 +5238,7 @@ check_circular_reference (type) return lookup_cl (TYPE_NAME (type)); return NULL_TREE; } - + for (i = 0; i < TREE_VEC_LENGTH (basetype_vec); i++) { tree vec_elt = TREE_VEC_ELT (basetype_vec, i); @@ -5288,7 +5250,7 @@ check_circular_reference (type) } void -java_check_circular_reference () +java_check_circular_reference (void) { tree current; for (current = ctxp->class_list; current; current = TREE_CHAIN (current)) @@ -5314,10 +5276,8 @@ java_check_circular_reference () finit$. */ static tree -build_alias_initializer_parameter_list (mode, class_type, parm, artificial) - int mode; - tree class_type, parm; - int *artificial; +build_alias_initializer_parameter_list (int mode, tree class_type, tree parm, + int *artificial) { tree field; tree additional_parms = NULL_TREE; @@ -5332,7 +5292,7 @@ build_alias_initializer_parameter_list (mode, class_type, parm, artificial) switch (mode) { case AIPL_FUNCTION_DECLARATION: - MANGLE_ALIAS_INITIALIZER_PARAMETER_NAME_STR (mangled_id, + MANGLE_ALIAS_INITIALIZER_PARAMETER_NAME_STR (mangled_id, &buffer [4]); purpose = build_wfl_node (mangled_id); if (TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE) @@ -5348,7 +5308,7 @@ build_alias_initializer_parameter_list (mode, class_type, parm, artificial) break; case AIPL_FUNCTION_FINIT_INVOCATION: - MANGLE_ALIAS_INITIALIZER_PARAMETER_NAME_STR (mangled_id, + MANGLE_ALIAS_INITIALIZER_PARAMETER_NAME_STR (mangled_id, &buffer [4]); /* Now, this is wrong. purpose should always be the NAME of something and value its matching value (decl, type, @@ -5381,7 +5341,7 @@ build_alias_initializer_parameter_list (mode, class_type, parm, artificial) } if (additional_parms) { - if (ANONYMOUS_CLASS_P (class_type) + if (ANONYMOUS_CLASS_P (class_type) && mode == AIPL_FUNCTION_CTOR_INVOCATION) additional_parms = nreverse (additional_parms); parm = chainon (additional_parms, parm); @@ -5394,9 +5354,8 @@ build_alias_initializer_parameter_list (mode, class_type, parm, artificial) where found. ARGS is non NULL when a special signature must be enforced. This is the case for anonymous classes. */ -static void -craft_constructor (class_decl, args) - tree class_decl, args; +static tree +craft_constructor (tree class_decl, tree args) { tree class_type = TREE_TYPE (class_decl); tree parm = NULL_TREE; @@ -5405,7 +5364,7 @@ craft_constructor (class_decl, args) int i = 0, artificial = 0; tree decl, ctor_name; char buffer [80]; - + /* The constructor name is unless we're dealing with an anonymous class, in which case the name will be fixed after having be expanded. */ @@ -5425,7 +5384,7 @@ craft_constructor (class_decl, args) /* Some more arguments to be hidden here. The values of the local variables of the outer context that the inner class needs to see. */ parm = build_alias_initializer_parameter_list (AIPL_FUNCTION_CREATION, - class_type, parm, + class_type, parm, &artificial); } @@ -5437,12 +5396,13 @@ craft_constructor (class_decl, args) } CRAFTED_PARAM_LIST_FIXUP (parm); - decl = create_artificial_method (class_type, flags, void_type_node, + decl = create_artificial_method (class_type, flags, void_type_node, ctor_name, parm); fix_method_argument_names (parm, decl); /* Now, mark the artificial parameters. */ DECL_FUNCTION_NAP (decl) = artificial; DECL_FUNCTION_SYNTHETIC_CTOR (decl) = DECL_CONSTRUCTOR_P (decl) = 1; + return decl; } @@ -5453,7 +5413,7 @@ craft_constructor (class_decl, args) compilation triggered this one to be simply loaded. */ void -java_fix_constructors () +java_fix_constructors (void) { tree current; @@ -5487,23 +5447,21 @@ java_fix_constructors () about the class processed currently. */ void -safe_layout_class (class) - tree class; +safe_layout_class (tree class) { tree save_current_class = current_class; const char *save_input_filename = input_filename; - int save_lineno = lineno; + int save_lineno = input_line; layout_class (class); current_class = save_current_class; input_filename = save_input_filename; - lineno = save_lineno; + input_line = save_lineno; } static tree -jdep_resolve_class (dep) - jdep *dep; +jdep_resolve_class (jdep *dep) { tree decl; @@ -5514,8 +5472,12 @@ jdep_resolve_class (dep) decl = resolve_class (JDEP_ENCLOSING (dep), JDEP_TO_RESOLVE (dep), JDEP_DECL (dep), JDEP_WFL (dep)); JDEP_RESOLVED (dep, decl); + /* If there is no WFL, that's ok. We generate this warning + elsewhere. */ + if (decl && JDEP_WFL (dep) != NULL_TREE) + check_deprecation (JDEP_WFL (dep), decl); } - + if (!decl) complete_class_report_errors (dep); else if (PURE_INNER_CLASS_DECL_P (decl)) @@ -5535,7 +5497,7 @@ jdep_resolve_class (dep) /* Complete unsatisfied class declaration and their dependencies */ void -java_complete_class () +java_complete_class (void) { tree cclass; jdeplist *cclassd; @@ -5545,12 +5507,12 @@ java_complete_class () /* Process imports */ process_imports (); - /* Rever things so we have the right order */ + /* Reverse things so we have the right order */ ctxp->class_list = nreverse (ctxp->class_list); ctxp->classd_list = reverse_jdep_list (ctxp); - for (cclassd = ctxp->classd_list, cclass = ctxp->class_list; - cclass && cclassd; + for (cclassd = ctxp->classd_list, cclass = ctxp->class_list; + cclass && cclassd; cclass = TREE_CHAIN (cclass), cclassd = CLASSD_CHAIN (cclassd)) { jdep *dep; @@ -5574,7 +5536,7 @@ java_complete_class () /* Simply patch super */ if (parser_check_super (decl, JDEP_DECL (dep), JDEP_WFL (dep))) continue; - BINFO_TYPE (TREE_VEC_ELT (BINFO_BASETYPES (TYPE_BINFO + BINFO_TYPE (TREE_VEC_ELT (BINFO_BASETYPES (TYPE_BINFO (TREE_TYPE (JDEP_DECL (dep)))), 0)) = TREE_TYPE (decl); break; @@ -5589,7 +5551,7 @@ java_complete_class () DECL_ALIGN (field_decl) = 0; DECL_USER_ALIGN (field_decl) = 0; layout_decl (field_decl, 0); - SOURCE_FRONTEND_DEBUG + SOURCE_FRONTEND_DEBUG (("Completed field/var decl `%s' with `%s'", IDENTIFIER_POINTER (DECL_NAME (field_decl)), IDENTIFIER_POINTER (DECL_NAME (decl)))); @@ -5606,11 +5568,11 @@ java_complete_class () if (TREE_CODE (type) == RECORD_TYPE) type = promote_type (type); JDEP_APPLY_PATCH (dep, type); - SOURCE_FRONTEND_DEBUG + SOURCE_FRONTEND_DEBUG (((JDEP_KIND (dep) == JDEP_METHOD_RETURN ? "Completing fct `%s' with ret type `%s'": "Completing arg `%s' with type `%s'"), - IDENTIFIER_POINTER (EXPR_WFL_NODE + IDENTIFIER_POINTER (EXPR_WFL_NODE (JDEP_DECL_WFL (dep))), IDENTIFIER_POINTER (DECL_NAME (decl)))); } @@ -5655,14 +5617,14 @@ java_complete_class () case JDEP_TYPE: JDEP_APPLY_PATCH (dep, TREE_TYPE (decl)); - SOURCE_FRONTEND_DEBUG + SOURCE_FRONTEND_DEBUG (("Completing a random type dependency on a '%s' node", tree_code_name [TREE_CODE (JDEP_DECL (dep))])); break; case JDEP_EXCEPTION: JDEP_APPLY_PATCH (dep, TREE_TYPE (decl)); - SOURCE_FRONTEND_DEBUG + SOURCE_FRONTEND_DEBUG (("Completing `%s' `throws' argument node", IDENTIFIER_POINTER (EXPR_WFL_NODE (JDEP_WFL (dep))))); break; @@ -5683,14 +5645,13 @@ java_complete_class () array. */ static tree -resolve_class (enclosing, class_type, decl, cl) - tree enclosing, class_type, decl, cl; +resolve_class (tree enclosing, tree class_type, tree decl, tree cl) { tree tname = TYPE_NAME (class_type); tree resolved_type = TREE_TYPE (class_type); int array_dims = 0; tree resolved_type_decl; - + if (resolved_type != NULL_TREE) { tree resolved_type_decl = TYPE_NAME (resolved_type); @@ -5711,12 +5672,12 @@ resolve_class (enclosing, class_type, decl, cl) WFL_STRIP_BRACKET (cl, cl); /* 2- Resolve the bare type */ - if (!(resolved_type_decl = do_resolve_class (enclosing, class_type, + if (!(resolved_type_decl = do_resolve_class (enclosing, class_type, decl, cl))) return NULL_TREE; resolved_type = TREE_TYPE (resolved_type_decl); - /* 3- If we have and array, reconstruct the array down to its nesting */ + /* 3- If we have an array, reconstruct the array down to its nesting */ if (array_dims) { for (; array_dims; array_dims--) @@ -5727,51 +5688,72 @@ resolve_class (enclosing, class_type, decl, cl) return resolved_type_decl; } -/* Effectively perform the resolution of class CLASS_TYPE. DECL or CL - are used to report error messages. Do not try to replace TYPE_NAME - (class_type) by a variable, since it is changed by - find_in_imports{_on_demand} and (but it doesn't really matter) - qualify_and_find. */ +/* Effectively perform the resolution of class CLASS_TYPE. DECL or CL + are used to report error messages; CL must either be NULL_TREE or a + WFL wrapping a class. Do not try to replace TYPE_NAME (class_type) + by a variable, since it is changed by find_in_imports{_on_demand} + and (but it doesn't really matter) qualify_and_find. */ tree -do_resolve_class (enclosing, class_type, decl, cl) - tree enclosing, class_type, decl, cl; +do_resolve_class (tree enclosing, tree class_type, tree decl, tree cl) { tree new_class_decl = NULL_TREE, super = NULL_TREE; tree saved_enclosing_type = enclosing ? TREE_TYPE (enclosing) : NULL_TREE; - struct hash_table _ht, *circularity_hash = &_ht; - - /* This hash table is used to register the classes we're going - through when searching the current class as an inner class, in - order to detect circular references. Remember to free it before - returning the section 0- of this function. */ - hash_table_init (circularity_hash, hash_newfunc, - java_hash_hash_tree_node, java_hash_compare_tree_node); - - /* 0- Search in the current class as an inner class. - Maybe some code here should be added to load the class or - something, at least if the class isn't an inner class and ended - being loaded from class file. FIXME. */ - while (enclosing) - { - new_class_decl = resolve_inner_class (circularity_hash, cl, &enclosing, - &super, class_type); - if (new_class_decl) - break; + tree decl_result; + htab_t circularity_hash; - /* If we haven't found anything because SUPER reached Object and - ENCLOSING happens to be an innerclass, try the enclosing context. */ - if ((!super || super == object_type_node) && - enclosing && INNER_CLASS_DECL_P (enclosing)) - enclosing = DECL_CONTEXT (enclosing); - else - enclosing = NULL_TREE; + if (QUALIFIED_P (TYPE_NAME (class_type))) + { + /* If the type name is of the form `Q . Id', then Q is either a + package name or a class name. First we try to find Q as a + class and then treat Id as a member type. If we can't find Q + as a class then we fall through. */ + tree q, left, left_type, right; + breakdown_qualified (&left, &right, TYPE_NAME (class_type)); + BUILD_PTR_FROM_NAME (left_type, left); + q = do_resolve_class (enclosing, left_type, decl, cl); + if (q) + { + enclosing = q; + saved_enclosing_type = TREE_TYPE (q); + BUILD_PTR_FROM_NAME (class_type, right); + } } - hash_table_free (circularity_hash); + if (enclosing) + { + /* This hash table is used to register the classes we're going + through when searching the current class as an inner class, in + order to detect circular references. Remember to free it before + returning the section 0- of this function. */ + circularity_hash = htab_create (20, htab_hash_pointer, htab_eq_pointer, + NULL); - if (new_class_decl) - return new_class_decl; + /* 0- Search in the current class as an inner class. + Maybe some code here should be added to load the class or + something, at least if the class isn't an inner class and ended + being loaded from class file. FIXME. */ + while (enclosing) + { + new_class_decl = resolve_inner_class (circularity_hash, cl, &enclosing, + &super, class_type); + if (new_class_decl) + break; + + /* If we haven't found anything because SUPER reached Object and + ENCLOSING happens to be an innerclass, try the enclosing context. */ + if ((!super || super == object_type_node) && + enclosing && INNER_CLASS_DECL_P (enclosing)) + enclosing = DECL_CONTEXT (enclosing); + else + enclosing = NULL_TREE; + } + + htab_delete (circularity_hash); + + if (new_class_decl) + return new_class_decl; + } /* 1- Check for the type in single imports. This will change TYPE_NAME() if something relevant is found */ @@ -5800,7 +5782,7 @@ do_resolve_class (enclosing, class_type, decl, cl) if (find_in_imports_on_demand (saved_enclosing_type, class_type)) return NULL_TREE; - /* If found in find_in_imports_on_demant, the type has already been + /* If found in find_in_imports_on_demand, the type has already been loaded. */ if ((new_class_decl = IDENTIFIER_CLASS_VALUE (TYPE_NAME (class_type)))) return new_class_decl; @@ -5812,22 +5794,22 @@ do_resolve_class (enclosing, class_type, decl, cl) /* If there is a current package (ctxp->package), it's the first element of package_list and we can skip it. */ - for (package = (ctxp->package ? + for (package = (ctxp->package ? TREE_CHAIN (package_list) : package_list); package; package = TREE_CHAIN (package)) if ((new_class_decl = qualify_and_find (class_type, - TREE_PURPOSE (package), + TREE_PURPOSE (package), TYPE_NAME (class_type)))) return new_class_decl; } - /* 5- Check an other compilation unit that bears the name of type */ + /* 5- Check another compilation unit that bears the name of type */ load_class (TYPE_NAME (class_type), 0); - + if (!cl) cl = lookup_cl (decl); - - /* If we don't have a value for CL, then we're being called recursively. + + /* If we don't have a value for CL, then we're being called recursively. We can't check package access just yet, but it will be taken care of by the caller. */ if (cl) @@ -5835,14 +5817,38 @@ do_resolve_class (enclosing, class_type, decl, cl) if (check_pkg_class_access (TYPE_NAME (class_type), cl, true)) return NULL_TREE; } - + /* 6- Last call for a resolution */ - return IDENTIFIER_CLASS_VALUE (TYPE_NAME (class_type)); + decl_result = IDENTIFIER_CLASS_VALUE (TYPE_NAME (class_type)); + + /* The final lookup might have registered a.b.c into a.b$c If we + failed at the first lookup, progressively change the name if + applicable and use the matching DECL instead. */ + if (!decl_result && QUALIFIED_P (TYPE_NAME (class_type))) + { + char *separator; + tree name = TYPE_NAME (class_type); + char *namebuffer = alloca (IDENTIFIER_LENGTH (name) + 1); + + strcpy (namebuffer, IDENTIFIER_POINTER (name)); + + do { + + /* Reach the last '.', and if applicable, replace it by a `$' and + see if this exists as a type. */ + if ((separator = strrchr (namebuffer, '.'))) + { + *separator = '$'; + name = get_identifier (namebuffer); + decl_result = IDENTIFIER_CLASS_VALUE (name); + } + } while (!decl_result && separator); + } + return decl_result; } static tree -qualify_and_find (class_type, package, name) - tree class_type, package, name; +qualify_and_find (tree class_type, tree package, tree name) { tree new_qualified = merge_qualified_name (package, name); tree new_class_decl; @@ -5865,9 +5871,7 @@ qualify_and_find (class_type, package, name) called when type resolution is necessary during the walk pass. */ static tree -resolve_and_layout (something, cl) - tree something; - tree cl; +resolve_and_layout (tree something, tree cl) { tree decl, decl_type; @@ -5917,7 +5921,7 @@ resolve_and_layout (something, cl) /* Check methods */ if (CLASS_FROM_SOURCE_P (decl_type)) java_check_methods (decl); - /* Layout the type if necessary */ + /* Layout the type if necessary */ if (decl_type != current_class && !CLASS_LOADED_P (decl_type)) safe_layout_class (decl_type); @@ -5928,15 +5932,14 @@ resolve_and_layout (something, cl) layout. The current parsing context is saved and restored */ static tree -resolve_no_layout (name, cl) - tree name, cl; +resolve_no_layout (tree name, tree cl) { tree ptr, decl; BUILD_PTR_FROM_NAME (ptr, name); java_parser_context_save_global (); decl = resolve_class (TYPE_NAME (current_class), ptr, NULL_TREE, cl); java_parser_context_restore_global (); - + return decl; } @@ -5945,8 +5948,7 @@ resolve_no_layout (name, cl) use an identifier tree. */ static const char * -purify_type_name (name) - const char *name; +purify_type_name (const char *name) { int len = strlen (name); int bracket_found; @@ -5964,8 +5966,7 @@ purify_type_name (name) /* The type CURRENT refers to can't be found. We print error messages. */ static void -complete_class_report_errors (dep) - jdep *dep; +complete_class_report_errors (jdep *dep) { const char *name; @@ -5976,7 +5977,7 @@ complete_class_report_errors (dep) switch (JDEP_KIND (dep)) { case JDEP_SUPER: - parse_error_context + parse_error_context (JDEP_WFL (dep), "Superclass `%s' of class `%s' not found", purify_type_name (name), IDENTIFIER_POINTER (DECL_NAME (JDEP_DECL (dep)))); @@ -5996,7 +5997,7 @@ complete_class_report_errors (dep) break; case JDEP_METHOD_RETURN: /* Covers return type */ parse_error_context - (JDEP_WFL (dep), "Type `%s' not found in the declaration of the return type of method `%s'", + (JDEP_WFL (dep), "Type `%s' not found in the declaration of the return type of method `%s'", purify_type_name (name), IDENTIFIER_POINTER (EXPR_WFL_NODE (JDEP_DECL_WFL (dep)))); break; @@ -6009,13 +6010,13 @@ complete_class_report_errors (dep) break; case JDEP_VARIABLE: parse_error_context - (JDEP_WFL (dep), "Type `%s' not found in the declaration of the local variable `%s'", - purify_type_name (IDENTIFIER_POINTER + (JDEP_WFL (dep), "Type `%s' not found in the declaration of the local variable `%s'", + purify_type_name (IDENTIFIER_POINTER (EXPR_WFL_NODE (JDEP_WFL (dep)))), IDENTIFIER_POINTER (DECL_NAME (JDEP_DECL (dep)))); break; case JDEP_EXCEPTION: /* As specified by `throws' */ - parse_error_context + parse_error_context (JDEP_WFL (dep), "Class `%s' not found in `throws'", IDENTIFIER_POINTER (EXPR_WFL_NODE (JDEP_WFL (dep)))); break; @@ -6031,8 +6032,7 @@ complete_class_report_errors (dep) */ static const char * -get_printable_method_name (decl) - tree decl; +get_printable_method_name (tree decl) { const char *to_return; tree name = NULL_TREE; @@ -6042,11 +6042,11 @@ get_printable_method_name (decl) name = DECL_NAME (decl); DECL_NAME (decl) = DECL_NAME (TYPE_NAME (DECL_CONTEXT (decl))); } - + to_return = lang_printable_name (decl, 0); if (DECL_CONSTRUCTOR_P (decl)) DECL_NAME (decl) = name; - + return to_return; } @@ -6055,8 +6055,7 @@ get_printable_method_name (decl) function it's a FWL, so we can track errors more accurately.) */ static int -check_method_redefinition (class, method) - tree class, method; +check_method_redefinition (tree class, tree method) { tree redef, sig; @@ -6074,7 +6073,7 @@ check_method_redefinition (class, method) && sig == TYPE_ARGUMENT_SIGNATURE (TREE_TYPE (redef)) && !DECL_ARTIFICIAL (method)) { - parse_error_context + parse_error_context (DECL_FUNCTION_WFL (method), "Duplicate %s declaration `%s'", (DECL_CONSTRUCTOR_P (redef) ? "constructor" : "method"), get_printable_method_name (redef)); @@ -6086,9 +6085,8 @@ check_method_redefinition (class, method) /* Return 1 if check went ok, 0 otherwise. */ static int -check_abstract_method_definitions (do_interface, class_decl, type) - int do_interface; - tree class_decl, type; +check_abstract_method_definitions (int do_interface, tree class_decl, + tree type) { tree class = TREE_TYPE (class_decl); tree method, end_type; @@ -6100,14 +6098,14 @@ check_abstract_method_definitions (do_interface, class_decl, type) tree other_super, other_method, method_sig, method_name; int found = 0; int end_type_reached = 0; - + if (!METHOD_ABSTRACT (method) || METHOD_FINAL (method)) continue; - + /* Now verify that somewhere in between TYPE and CLASS, abstract method METHOD gets a non abstract definition that is inherited by CLASS. */ - + method_sig = build_java_signature (TREE_TYPE (method)); method_name = DECL_NAME (method); if (TREE_CODE (method_name) == EXPR_WITH_FILE_LOCATION) @@ -6117,14 +6115,14 @@ check_abstract_method_definitions (do_interface, class_decl, type) do { if (other_super == end_type) end_type_reached = 1; - + /* Method search */ for (other_method = TYPE_METHODS (other_super); other_method; other_method = TREE_CHAIN (other_method)) { tree s = build_java_signature (TREE_TYPE (other_method)); tree other_name = DECL_NAME (other_method); - + if (TREE_CODE (other_name) == EXPR_WITH_FILE_LOCATION) other_name = EXPR_WFL_NODE (other_name); if (!DECL_CLINIT_P (other_method) @@ -6139,21 +6137,21 @@ check_abstract_method_definitions (do_interface, class_decl, type) } other_super = CLASSTYPE_SUPER (other_super); } while (!end_type_reached); - + /* Report that abstract METHOD didn't find an implementation that CLASS can use. */ if (!found) { - char *t = xstrdup (lang_printable_name + char *t = xstrdup (lang_printable_name (TREE_TYPE (TREE_TYPE (method)), 0)); tree ccn = DECL_NAME (TYPE_NAME (DECL_CONTEXT (method))); - - parse_error_context + + parse_error_context (lookup_cl (class_decl), "Class `%s' doesn't define the abstract method `%s %s' from %s `%s'. This method must be defined or %s `%s' must be declared abstract", IDENTIFIER_POINTER (DECL_NAME (class_decl)), - t, lang_printable_name (method, 0), - (CLASS_INTERFACE (TYPE_NAME (DECL_CONTEXT (method))) ? + t, lang_printable_name (method, 0), + (CLASS_INTERFACE (TYPE_NAME (DECL_CONTEXT (method))) ? "interface" : "class"), IDENTIFIER_POINTER (ccn), (CLASS_INTERFACE (class_decl) ? "interface" : "class"), @@ -6182,8 +6180,7 @@ check_abstract_method_definitions (do_interface, class_decl, type) methods. */ static void -java_check_abstract_method_definitions (class_decl) - tree class_decl; +java_check_abstract_method_definitions (tree class_decl) { tree class = TREE_TYPE (class_decl); tree super, vector; @@ -6213,15 +6210,14 @@ java_check_abstract_method_definitions (class_decl) safe to build a method signature or not. */ static int -check_method_types_complete (decl) - tree decl; +check_method_types_complete (tree decl) { tree type = TREE_TYPE (decl); tree args; if (!INCOMPLETE_TYPE_P (TREE_TYPE (type))) return 0; - + args = TYPE_ARG_TYPES (type); if (TREE_CODE (type) == METHOD_TYPE) args = TREE_CHAIN (args); @@ -6235,8 +6231,7 @@ check_method_types_complete (decl) /* Visible interface to check methods contained in CLASS_DECL */ void -java_check_methods (class_decl) - tree class_decl; +java_check_methods (tree class_decl) { if (CLASS_METHOD_CHECKED_P (TREE_TYPE (class_decl))) return; @@ -6245,7 +6240,7 @@ java_check_methods (class_decl) java_check_abstract_methods (class_decl); else java_check_regular_methods (class_decl); - + CLASS_METHOD_CHECKED_P (TREE_TYPE (class_decl)) = 1; } @@ -6255,12 +6250,11 @@ java_check_methods (class_decl) declaration. */ static void -java_check_regular_methods (class_decl) - tree class_decl; +java_check_regular_methods (tree class_decl) { int saw_constructor = ANONYMOUS_CLASS_P (TREE_TYPE (class_decl)); tree method; - tree class = CLASS_TO_HANDLE_TYPE (TREE_TYPE (class_decl)); + tree class = TREE_TYPE (class_decl); tree found = NULL_TREE; tree mthrows; @@ -6282,27 +6276,27 @@ java_check_regular_methods (class_decl) if (check_method_redefinition (class, method)) continue; - /* If we see one constructor a mark so we don't generate the - default one. Also skip other verifications: constructors - can't be inherited hence hiden or overriden */ - if (DECL_CONSTRUCTOR_P (method)) - { - saw_constructor = 1; - continue; - } - - /* We verify things thrown by the method. They must inherits from - java.lang.Throwable */ + /* We verify things thrown by the method. They must inherit from + java.lang.Throwable. */ for (mthrows = DECL_FUNCTION_THROWS (method); mthrows; mthrows = TREE_CHAIN (mthrows)) { if (!inherits_from_p (TREE_VALUE (mthrows), throwable_type_node)) - parse_error_context + parse_error_context (TREE_PURPOSE (mthrows), "Class `%s' in `throws' clause must be a subclass of class `java.lang.Throwable'", - IDENTIFIER_POINTER + IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (TREE_VALUE (mthrows))))); } + /* If we see one constructor a mark so we don't generate the + default one. Also skip other verifications: constructors + can't be inherited hence hidden or overridden. */ + if (DECL_CONSTRUCTOR_P (method)) + { + saw_constructor = 1; + continue; + } + sig = build_java_argument_signature (TREE_TYPE (method)); found = lookup_argument_method2 (class, DECL_NAME (method), sig); @@ -6310,7 +6304,7 @@ java_check_regular_methods (class_decl) if (METHOD_STATIC (method) && !TOPLEVEL_CLASS_DECL_P (class_decl)) { char *t = xstrdup (lang_printable_name (class, 0)); - parse_error_context + parse_error_context (method_wfl, "Method `%s' can't be static in inner class `%s'. Only members of interfaces and top-level classes can be static", lang_printable_name (method, 0), t); free (t); @@ -6327,7 +6321,7 @@ java_check_regular_methods (class_decl) /* If `found' is declared in an interface, make sure the modifier matches. */ - if (CLASS_INTERFACE (TYPE_NAME (DECL_CONTEXT (found))) + if (CLASS_INTERFACE (TYPE_NAME (DECL_CONTEXT (found))) && clinit_identifier_node != DECL_NAME (found) && !METHOD_PUBLIC (method)) { @@ -6342,13 +6336,13 @@ java_check_regular_methods (class_decl) types. */ if (TREE_TYPE (TREE_TYPE (found)) != TREE_TYPE (TREE_TYPE (method))) { - char *t = xstrdup + char *t = xstrdup (lang_printable_name (TREE_TYPE (TREE_TYPE (found)), 0)); - parse_error_context + parse_error_context (method_wfl, - "Method `%s' was defined with return type `%s' in class `%s'", + "Method `%s' was defined with return type `%s' in class `%s'", lang_printable_name (found, 0), t, - IDENTIFIER_POINTER + IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (DECL_CONTEXT (found))))); free (t); } @@ -6361,7 +6355,7 @@ java_check_regular_methods (class_decl) /* Static *can* override static */ if (METHOD_STATIC (found) && METHOD_STATIC (method)) continue; - parse_error_context + parse_error_context (method_wfl, "%s methods can't be overriden. Method `%s' is %s in class `%s'", (METHOD_FINAL (found) ? "Final" : "Static"), @@ -6375,7 +6369,7 @@ java_check_regular_methods (class_decl) /* Static method can't override instance method. */ if (METHOD_STATIC (method)) { - parse_error_context + parse_error_context (method_wfl, "Instance methods can't be overriden by a static method. Method `%s' is an instance method in class `%s'", lang_printable_name (found, 0), @@ -6393,17 +6387,17 @@ java_check_regular_methods (class_decl) taken care of. */ if (!CLASS_INTERFACE (TYPE_NAME (DECL_CONTEXT (found))) && ((METHOD_PUBLIC (found) && !METHOD_PUBLIC (method)) - || (METHOD_PROTECTED (found) + || (METHOD_PROTECTED (found) && !(METHOD_PUBLIC (method) || METHOD_PROTECTED (method))) || (!(aflags & (ACC_PUBLIC | ACC_PRIVATE | ACC_STATIC)) && METHOD_PRIVATE (method)))) { - parse_error_context + parse_error_context (method_wfl, "Methods can't be overridden to be more private. Method `%s' is not %s in class `%s'", lang_printable_name (method, 0), - (METHOD_PUBLIC (method) ? "public" : + (METHOD_PUBLIC (method) ? "public" : (METHOD_PRIVATE (method) ? "private" : "protected")), - IDENTIFIER_POINTER (DECL_NAME + IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (DECL_CONTEXT (found))))); continue; } @@ -6414,7 +6408,7 @@ java_check_regular_methods (class_decl) /* Inheriting multiple methods with the same signature. FIXME */ } - + if (!TYPE_NVIRTUALS (class)) TYPE_METHODS (class) = nreverse (TYPE_METHODS (class)); @@ -6426,12 +6420,11 @@ java_check_regular_methods (class_decl) abort (); } -/* Return a non zero value if the `throws' clause of METHOD (if any) +/* Return a nonzero value if the `throws' clause of METHOD (if any) is incompatible with the `throws' clause of FOUND (if any). */ static void -check_throws_clauses (method, method_wfl, found) - tree method, method_wfl, found; +check_throws_clauses (tree method, tree method_wfl, tree found) { tree mthrows, fthrows; @@ -6446,17 +6439,17 @@ check_throws_clauses (method, method_wfl, found) if (IS_UNCHECKED_EXCEPTION_P (TREE_VALUE (mthrows))) continue; /* Checked expression must be compatible */ - for (fthrows = DECL_FUNCTION_THROWS (found); + for (fthrows = DECL_FUNCTION_THROWS (found); fthrows; fthrows = TREE_CHAIN (fthrows)) if (inherits_from_p (TREE_VALUE (mthrows), TREE_VALUE (fthrows))) break; if (!fthrows) { - parse_error_context + parse_error_context (method_wfl, "Invalid checked exception class `%s' in `throws' clause. The exception must be a subclass of an exception thrown by `%s' from class `%s'", IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (TREE_VALUE (mthrows)))), lang_printable_name (found, 0), - IDENTIFIER_POINTER + IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (DECL_CONTEXT (found))))); } } @@ -6465,8 +6458,7 @@ check_throws_clauses (method, method_wfl, found) /* Check abstract method of interface INTERFACE */ static void -java_check_abstract_methods (interface_decl) - tree interface_decl; +java_check_abstract_methods (tree interface_decl) { int i, n; tree method, basetype_vec, found; @@ -6485,11 +6477,11 @@ java_check_abstract_methods (interface_decl) { char *t; t = xstrdup (lang_printable_name (TREE_TYPE (TREE_TYPE (found)), 0)); - parse_error_context + parse_error_context (DECL_FUNCTION_WFL (found), "Method `%s' was defined with return type `%s' in class `%s'", lang_printable_name (found, 0), t, - IDENTIFIER_POINTER + IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (DECL_CONTEXT (found))))); free (t); continue; @@ -6507,23 +6499,23 @@ java_check_abstract_methods (interface_decl) if (!vec_elt) continue; sub_interface = BINFO_TYPE (vec_elt); - for (sub_interface_method = TYPE_METHODS (sub_interface); + for (sub_interface_method = TYPE_METHODS (sub_interface); sub_interface_method; sub_interface_method = TREE_CHAIN (sub_interface_method)) { - found = lookup_java_interface_method2 (interface, + found = lookup_java_interface_method2 (interface, sub_interface_method); if (found && (found != sub_interface_method)) { - parse_error_context + parse_error_context (lookup_cl (sub_interface_method), "Interface `%s' inherits method `%s' from interface `%s'. This method is redefined with a different return type in interface `%s'", IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (interface))), lang_printable_name (found, 0), - IDENTIFIER_POINTER - (DECL_NAME (TYPE_NAME + IDENTIFIER_POINTER + (DECL_NAME (TYPE_NAME (DECL_CONTEXT (sub_interface_method)))), - IDENTIFIER_POINTER + IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (DECL_CONTEXT (found))))); } } @@ -6534,8 +6526,7 @@ java_check_abstract_methods (interface_decl) signature. Return a matching method only if their types differ. */ static tree -lookup_java_interface_method2 (class, method_decl) - tree class, method_decl; +lookup_java_interface_method2 (tree class, tree method_decl) { int i, n; tree basetype_vec = TYPE_BINFO_BASETYPES (class), to_return; @@ -6548,13 +6539,13 @@ lookup_java_interface_method2 (class, method_decl) { tree vec_elt = TREE_VEC_ELT (basetype_vec, i), to_return; if ((BINFO_TYPE (vec_elt) != object_type_node) - && (to_return = + && (to_return = lookup_java_method2 (BINFO_TYPE (vec_elt), method_decl, 1))) return to_return; } for (i = 0; i < n; i++) { - to_return = lookup_java_interface_method2 + to_return = lookup_java_interface_method2 (BINFO_TYPE (TREE_VEC_ELT (basetype_vec, i)), method_decl); if (to_return) return to_return; @@ -6567,15 +6558,13 @@ lookup_java_interface_method2 (class, method_decl) matching method only if their types differ. */ static tree -lookup_java_method2 (clas, method_decl, do_interface) - tree clas, method_decl; - int do_interface; +lookup_java_method2 (tree clas, tree method_decl, int do_interface) { tree method, method_signature, method_name, method_type, name; method_signature = build_java_argument_signature (TREE_TYPE (method_decl)); name = DECL_NAME (method_decl); - method_name = (TREE_CODE (name) == EXPR_WITH_FILE_LOCATION ? + method_name = (TREE_CODE (name) == EXPR_WITH_FILE_LOCATION ? EXPR_WFL_NODE (name) : name); method_type = TREE_TYPE (TREE_TYPE (method_decl)); @@ -6588,7 +6577,7 @@ lookup_java_method2 (clas, method_decl, do_interface) tree name = DECL_NAME (method); if ((TREE_CODE (name) == EXPR_WITH_FILE_LOCATION ? EXPR_WFL_NODE (name) : name) == method_name - && method_sig == method_signature + && method_sig == method_signature && TREE_TYPE (TREE_TYPE (method)) != method_type) return method; } @@ -6600,41 +6589,38 @@ lookup_java_method2 (clas, method_decl, do_interface) /* Return the line that matches DECL line number, and try its best to position the column number. Used during error reports. */ +static GTY(()) tree cl_v; static tree -lookup_cl (decl) - tree decl; +lookup_cl (tree decl) { - static tree cl = NULL_TREE; char *line, *found; - + if (!decl) return NULL_TREE; - if (cl == NULL_TREE) + if (cl_v == NULL_TREE) { - cl = build_expr_wfl (NULL_TREE, NULL, 0, 0); - ggc_add_tree_root (&cl, 1); + cl_v = build_expr_wfl (NULL_TREE, NULL, 0, 0); } - EXPR_WFL_FILENAME_NODE (cl) = get_identifier (DECL_SOURCE_FILE (decl)); - EXPR_WFL_SET_LINECOL (cl, DECL_SOURCE_LINE_FIRST (decl), -1); + EXPR_WFL_FILENAME_NODE (cl_v) = get_identifier (DECL_SOURCE_FILE (decl)); + EXPR_WFL_SET_LINECOL (cl_v, DECL_SOURCE_LINE_FIRST (decl), -1); - line = java_get_line_col (EXPR_WFL_FILENAME (cl), - EXPR_WFL_LINENO (cl), EXPR_WFL_COLNO (cl)); + line = java_get_line_col (EXPR_WFL_FILENAME (cl_v), + EXPR_WFL_LINENO (cl_v), EXPR_WFL_COLNO (cl_v)); - found = strstr ((const char *)line, + found = strstr ((const char *)line, (const char *)IDENTIFIER_POINTER (DECL_NAME (decl))); if (found) - EXPR_WFL_SET_LINECOL (cl, EXPR_WFL_LINENO (cl), found - line); + EXPR_WFL_SET_LINECOL (cl_v, EXPR_WFL_LINENO (cl_v), found - line); - return cl; + return cl_v; } /* Look for a simple name in the single-type import list */ static tree -find_name_in_single_imports (name) - tree name; +find_name_in_single_imports (tree name) { tree node; @@ -6648,7 +6634,7 @@ find_name_in_single_imports (name) /* Process all single-type import. */ static int -process_imports () +process_imports (void) { tree import; int error_found; @@ -6658,15 +6644,14 @@ process_imports () tree to_be_found = EXPR_WFL_NODE (TREE_PURPOSE (import)); char *original_name; - obstack_grow0 (&temporary_obstack, - IDENTIFIER_POINTER (to_be_found), - IDENTIFIER_LENGTH (to_be_found)); - original_name = obstack_finish (&temporary_obstack); + original_name = xmemdup (IDENTIFIER_POINTER (to_be_found), + IDENTIFIER_LENGTH (to_be_found), + IDENTIFIER_LENGTH (to_be_found) + 1); /* Don't load twice something already defined. */ if (IDENTIFIER_CLASS_VALUE (to_be_found)) continue; - + while (1) { tree left; @@ -6675,10 +6660,14 @@ process_imports () load_class (to_be_found, 0); error_found = check_pkg_class_access (to_be_found, TREE_PURPOSE (import), true); - + /* We found it, we can bail out */ if (IDENTIFIER_CLASS_VALUE (to_be_found)) - break; + { + check_deprecation (TREE_PURPOSE (import), + IDENTIFIER_CLASS_VALUE (to_be_found)); + break; + } /* We haven't found it. Maybe we're trying to access an inner class. The only way for us to know is to try again @@ -6697,7 +6686,7 @@ process_imports () error_found = 1; } - obstack_free (&temporary_obstack, original_name); + free (original_name); if (error_found) return 1; } @@ -6708,11 +6697,9 @@ process_imports () statement. */ static void -find_in_imports (enclosing_type, class_type) - tree enclosing_type; - tree class_type; +find_in_imports (tree enclosing_type, tree class_type) { - tree import = (enclosing_type ? TYPE_IMPORT_LIST (enclosing_type) : + tree import = (enclosing_type ? TYPE_IMPORT_LIST (enclosing_type) : ctxp->import_list); while (import) { @@ -6727,9 +6714,7 @@ find_in_imports (enclosing_type, class_type) } static int -note_possible_classname (name, len) - const char *name; - int len; +note_possible_classname (const char *name, int len) { tree node; if (len > 5 && strncmp (&name [len-5], ".java", 5) == 0) @@ -6749,8 +6734,7 @@ note_possible_classname (name, len) directory. */ static void -read_import_dir (wfl) - tree wfl; +read_import_dir (tree wfl) { tree package_id = EXPR_WFL_NODE (wfl); const char *package_name = IDENTIFIER_POINTER (package_id); @@ -6800,7 +6784,7 @@ read_import_dir (wfl) int current_entry_len = zipd->filename_length; if (current_entry_len >= BUFFER_LENGTH (filename) - && strncmp (filename->data, current_entry, + && strncmp (filename->data, current_entry, BUFFER_LENGTH (filename)) != 0) continue; found |= note_possible_classname (current_entry, @@ -6827,7 +6811,7 @@ read_import_dir (wfl) *filename->ptr++ = '/'; for (;;) { - int len; + int len; const char *d_name; struct dirent *direntp = readdir (dirp); if (!direntp) @@ -6869,11 +6853,9 @@ read_import_dir (wfl) /* Possibly find a type in the import on demands specified types. Returns 1 if an error occurred, 0 otherwise. Run through the entire list, to detected potential double definitions. */ - + static int -find_in_imports_on_demand (enclosing_type, class_type) - tree enclosing_type; - tree class_type; +find_in_imports_on_demand (tree enclosing_type, tree class_type) { tree class_type_name = TYPE_NAME (class_type); tree import = (enclosing_type ? TYPE_IMPORT_DEMAND_LIST (enclosing_type) : @@ -6885,26 +6867,26 @@ find_in_imports_on_demand (enclosing_type, class_type) for (; import; import = TREE_CHAIN (import)) { - int saved_lineno = lineno; + int saved_lineno = input_line; int access_check; const char *id_name; tree decl, type_name_copy; - obstack_grow (&temporary_obstack, + obstack_grow (&temporary_obstack, IDENTIFIER_POINTER (EXPR_WFL_NODE (TREE_PURPOSE (import))), IDENTIFIER_LENGTH (EXPR_WFL_NODE (TREE_PURPOSE (import)))); obstack_1grow (&temporary_obstack, '.'); - obstack_grow0 (&temporary_obstack, + obstack_grow0 (&temporary_obstack, IDENTIFIER_POINTER (class_type_name), IDENTIFIER_LENGTH (class_type_name)); id_name = obstack_finish (&temporary_obstack); - + if (! (node = maybe_get_identifier (id_name))) continue; /* Setup lineno so that it refers to the line of the import (in case we parse a class file and encounter errors */ - lineno = EXPR_WFL_LINENO (TREE_PURPOSE (import)); + input_line = EXPR_WFL_LINENO (TREE_PURPOSE (import)); type_name_copy = TYPE_NAME (class_type); TYPE_NAME (class_type) = node; @@ -6926,7 +6908,7 @@ find_in_imports_on_demand (enclosing_type, class_type) /* 6.6.1: Inner classes are subject to member access rules. */ access_check = 0; - lineno = saved_lineno; + input_line = saved_lineno; /* If the loaded class is not accessible or couldn't be loaded, we restore the original TYPE_NAME and process the next @@ -6936,7 +6918,7 @@ find_in_imports_on_demand (enclosing_type, class_type) TYPE_NAME (class_type) = type_name_copy; continue; } - + /* If the loaded class is accessible, we keep a tab on it to detect and report multiple inclusions. */ if (IS_A_CLASSFILE_NAME (node)) @@ -6949,13 +6931,13 @@ find_in_imports_on_demand (enclosing_type, class_type) else if (seen_once >= 0) { tree location = (cl ? cl : TREE_PURPOSE (import)); - tree package = (cl ? EXPR_WFL_NODE (cl) : + tree package = (cl ? EXPR_WFL_NODE (cl) : EXPR_WFL_NODE (TREE_PURPOSE (import))); seen_once++; - parse_error_context + parse_error_context (location, "Type `%s' also potentially defined in package `%s'", - IDENTIFIER_POINTER (TYPE_NAME (class_type)), + IDENTIFIER_POINTER (TYPE_NAME (class_type)), IDENTIFIER_POINTER (package)); } } @@ -6968,74 +6950,53 @@ find_in_imports_on_demand (enclosing_type, class_type) return (seen_once < 0 ? 0 : seen_once); /* It's ok not to have found */ } -/* Add package NAME to the list of package encountered so far. To +/* Add package NAME to the list of packages encountered so far. To speed up class lookup in do_resolve_class, we make sure a particular package is added only once. */ static void -register_package (name) - tree name; +register_package (tree name) { - static struct hash_table _pht, *pht = NULL; + static htab_t pht; + void **e; - if (!pht) - { - hash_table_init (&_pht, hash_newfunc, - java_hash_hash_tree_node, java_hash_compare_tree_node); - pht = &_pht; - } - - if (!hash_lookup (pht, (const hash_table_key) name, FALSE, NULL)) + if (pht == NULL) + pht = htab_create (50, htab_hash_pointer, htab_eq_pointer, NULL); + + e = htab_find_slot (pht, name, INSERT); + if (*e == NULL) { package_list = chainon (package_list, build_tree_list (name, NULL)); - hash_lookup (pht, (const hash_table_key) name, TRUE, NULL); + *e = name; } } static tree -resolve_package (pkg, next) - tree pkg, *next; +resolve_package (tree pkg, tree *next, tree *type_name) { - tree current, acc; - tree type_name = NULL_TREE; - const char *name = IDENTIFIER_POINTER (EXPR_WFL_NODE (pkg)); + tree current; + tree decl = NULL_TREE; + *type_name = NULL_TREE; /* The trick is to determine when the package name stops and were the name of something contained in the package starts. Then we return a fully qualified name of what we want to get. */ - /* Do a quick search on well known package names */ - if (!strncmp (name, "java.lang.reflect", 17)) - { - *next = - TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (EXPR_WFL_QUALIFICATION (pkg)))); - type_name = lookup_package_type (name, 17); - } - else if (!strncmp (name, "java.lang", 9)) - { - *next = TREE_CHAIN (TREE_CHAIN (EXPR_WFL_QUALIFICATION (pkg))); - type_name = lookup_package_type (name, 9); - } - - /* If we found something here, return */ - if (type_name) - return type_name; - *next = EXPR_WFL_QUALIFICATION (pkg); /* Try to progressively construct a type name */ if (TREE_CODE (pkg) == EXPR_WITH_FILE_LOCATION) - for (acc = NULL_TREE, current = EXPR_WFL_QUALIFICATION (pkg); + for (current = EXPR_WFL_QUALIFICATION (pkg); current; current = TREE_CHAIN (current)) { /* If we don't have what we're expecting, exit now. TYPE_NAME will be null and the error caught later. */ if (TREE_CODE (QUAL_WFL (current)) != EXPR_WITH_FILE_LOCATION) break; - acc = merge_qualified_name (acc, EXPR_WFL_NODE (QUAL_WFL (current))); - if ((type_name = resolve_no_layout (acc, NULL_TREE))) + *type_name = + merge_qualified_name (*type_name, EXPR_WFL_NODE (QUAL_WFL (current))); + if ((decl = resolve_no_layout (*type_name, NULL_TREE))) { - type_name = acc; /* resolve_package should be used in a loop, hence we point at this one to naturally process the next one at the next iteration. */ @@ -7043,30 +7004,16 @@ resolve_package (pkg, next) break; } } - return type_name; + return decl; } -static tree -lookup_package_type (name, from) - const char *name; - int from; -{ - char subname [128]; - const char *sub = &name[from+1]; - while (*sub != '.' && *sub) - sub++; - strncpy (subname, name, sub-name); - subname [sub-name] = '\0'; - return get_identifier (subname); -} -/* Check accessibility of inner classes according to member access rules. +/* Check accessibility of inner classes according to member access rules. DECL is the inner class, ENCLOSING_DECL is the class from which the access is being attempted. */ static void -check_inner_class_access (decl, enclosing_decl, cl) - tree decl, enclosing_decl, cl; +check_inner_class_access (tree decl, tree enclosing_decl, tree cl) { const char *access; tree enclosing_decl_type; @@ -7087,11 +7034,11 @@ check_inner_class_access (decl, enclosing_decl, cl) class in which DECL is declared. */ tree top_level = decl; while (DECL_CONTEXT (top_level)) - top_level = DECL_CONTEXT (top_level); + top_level = DECL_CONTEXT (top_level); while (DECL_CONTEXT (enclosing_decl)) enclosing_decl = DECL_CONTEXT (enclosing_decl); if (top_level == enclosing_decl) - return; + return; access = "private"; } else if (CLASS_PROTECTED (decl)) @@ -7100,7 +7047,7 @@ check_inner_class_access (decl, enclosing_decl, cl) /* Access is permitted from within the same package... */ if (in_same_package (decl, enclosing_decl)) return; - + /* ... or from within the body of a subtype of the context in which DECL is declared. */ decl_context = DECL_CONTEXT (decl); @@ -7108,19 +7055,19 @@ check_inner_class_access (decl, enclosing_decl, cl) { if (CLASS_INTERFACE (decl)) { - if (interface_of_p (TREE_TYPE (decl_context), + if (interface_of_p (TREE_TYPE (decl_context), enclosing_decl_type)) return; } else { /* Eww. The order of the arguments is different!! */ - if (inherits_from_p (enclosing_decl_type, + if (inherits_from_p (enclosing_decl_type, TREE_TYPE (decl_context))) return; } enclosing_decl = DECL_CONTEXT (enclosing_decl); - } + } access = "protected"; } else if (! CLASS_PUBLIC (decl)) @@ -7145,10 +7092,7 @@ check_inner_class_access (decl, enclosing_decl, cl) was found, it is reported and accounted for. */ static int -check_pkg_class_access (class_name, cl, verbose) - tree class_name; - tree cl; - bool verbose; +check_pkg_class_access (tree class_name, tree cl, bool verbose) { tree type; @@ -7172,7 +7116,7 @@ check_pkg_class_access (class_name, cl, verbose) return 0; if (verbose) - parse_error_context + parse_error_context (cl, "Can't access %s `%s'. Only public classes and interfaces in other packages can be accessed", (CLASS_INTERFACE (TYPE_NAME (type)) ? "interface" : "class"), IDENTIFIER_POINTER (class_name)); @@ -7184,10 +7128,7 @@ check_pkg_class_access (class_name, cl, verbose) /* Local variable declaration. */ static void -declare_local_variables (modifier, type, vlist) - int modifier; - tree type; - tree vlist; +declare_local_variables (int modifier, tree type, tree vlist) { tree decl, current, saved_type; tree type_wfl = NULL_TREE; @@ -7204,14 +7145,16 @@ declare_local_variables (modifier, type, vlist) if (modifier) { - int i; - for (i = 0; i <= 10; i++) if (1 << i & modifier) break; + size_t i; + for (i = 0; i < ARRAY_SIZE (ctxp->modifier_ctx); i++) + if (1 << i & modifier) + break; if (modifier == ACC_FINAL) final_p = 1; - else + else { - parse_error_context - (ctxp->modifier_ctx [i], + parse_error_context + (ctxp->modifier_ctx [i], "Only `final' is allowed as a local variables modifier"); return; } @@ -7257,16 +7200,16 @@ declare_local_variables (modifier, type, vlist) MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (decl); DECL_FINAL (decl) = final_p; BLOCK_CHAIN_DECL (decl); - + /* If doing xreferencing, replace the line number with the WFL compound value */ if (flag_emit_xref) DECL_SOURCE_LINE (decl) = EXPR_WFL_LINECOL (wfl); - + /* Don't try to use an INIT statement when an error was found */ if (init && java_error_count) init = NULL_TREE; - + /* Add the initialization function to the current function's code */ if (init) { @@ -7277,7 +7220,7 @@ declare_local_variables (modifier, type, vlist) build_debugable_stmt (EXPR_WFL_LINECOL (init), init)); } - + /* Setup dependency the type of the decl */ if (must_chain) { @@ -7293,8 +7236,7 @@ declare_local_variables (modifier, type, vlist) /* Called during parsing. Build decls from argument list. */ static void -source_start_java_method (fndecl) - tree fndecl; +source_start_java_method (tree fndecl) { tree tem; tree parm_decl; @@ -7312,7 +7254,7 @@ source_start_java_method (fndecl) { tree type = TREE_VALUE (tem); tree name = TREE_PURPOSE (tem); - + /* If type is incomplete. Create an incomplete decl and ask for the decl to be patched later */ if (INCOMPLETE_TYPE_P (type)) @@ -7349,29 +7291,26 @@ source_start_java_method (fndecl) /* Called during parsing. Creates an artificial method declaration. */ static tree -create_artificial_method (class, flags, type, name, args) - tree class; - int flags; - tree type, name, args; +create_artificial_method (tree class, int flags, tree type, + tree name, tree args) { tree mdecl; java_parser_context_save_global (); - lineno = 0; - mdecl = make_node (FUNCTION_TYPE); + input_line = 0; + mdecl = make_node (FUNCTION_TYPE); TREE_TYPE (mdecl) = type; TYPE_ARG_TYPES (mdecl) = args; - mdecl = add_method (class, flags, name, build_java_signature (mdecl)); + mdecl = add_method (class, flags, name, build_java_signature (mdecl)); java_parser_context_restore_global (); - DECL_ARTIFICIAL (mdecl) = 1; + DECL_ARTIFICIAL (mdecl) = 1; return mdecl; } /* Starts the body if an artificial method. */ static void -start_artificial_method_body (mdecl) - tree mdecl; +start_artificial_method_body (tree mdecl) { DECL_SOURCE_LINE (mdecl) = 1; DECL_SOURCE_LINE_MERGE (mdecl, 1); @@ -7380,8 +7319,7 @@ start_artificial_method_body (mdecl) } static void -end_artificial_method_body (mdecl) - tree mdecl; +end_artificial_method_body (tree mdecl) { /* exit_block modifies DECL_FUNCTION_BODY (current_function_decl). It has to be evaluated first. (if mdecl is current_function_decl, @@ -7391,10 +7329,27 @@ end_artificial_method_body (mdecl) exit_block (); } +/* Dump a tree of some kind. This is a convenience wrapper for the + dump_* functions in tree-dump.c. */ +static void +dump_java_tree (enum tree_dump_index phase, tree t) +{ + FILE *stream; + int flags; + + stream = dump_begin (phase, &flags); + flags |= TDF_SLIM; + if (stream) + { + dump_node (t, flags, stream); + dump_end (phase, stream); + } +} + /* Terminate a function and expand its body. */ static void -source_end_java_method () +source_end_java_method (void) { tree fndecl = current_function_decl; @@ -7402,7 +7357,7 @@ source_end_java_method () return; java_parser_context_save_global (); - lineno = ctxp->last_ccb_indent1; + input_line = ctxp->last_ccb_indent1; /* Turn function bodies with only a NOP expr null, so they don't get generated at all and we won't get warnings when using the -W @@ -7410,6 +7365,12 @@ source_end_java_method () if (BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (fndecl)) == empty_stmt_node) BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (fndecl)) = NULL_TREE; + /* We've generated all the trees for this function, and it has been + patched. Dump it to a file if the user requested it. */ + dump_java_tree (TDI_original, fndecl); + + java_optimize_inline (fndecl); + /* Generate function's code */ if (BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (fndecl)) && ! flag_emit_class_files @@ -7424,8 +7385,10 @@ source_end_java_method () /* Generate rtl for function exit. */ if (! flag_emit_class_files && ! flag_emit_xref) { - lineno = DECL_SOURCE_LINE_LAST (fndecl); - expand_function_end (input_filename, lineno, 0); + input_line = DECL_SOURCE_LINE_LAST (fndecl); + expand_function_end (input_filename, input_line, 0); + + DECL_SOURCE_LINE (fndecl) = DECL_SOURCE_LINE_FIRST (fndecl); /* Run the optimizers and output assembler code for this function. */ rest_of_compilation (fndecl); @@ -7439,8 +7402,7 @@ source_end_java_method () expression second operand if necessary. */ tree -java_method_add_stmt (fndecl, expr) - tree fndecl, expr; +java_method_add_stmt (tree fndecl, tree expr) { if (!GET_CURRENT_BLOCK (fndecl)) return NULL_TREE; @@ -7448,14 +7410,13 @@ java_method_add_stmt (fndecl, expr) } static tree -add_stmt_to_block (b, type, stmt) - tree b, type, stmt; +add_stmt_to_block (tree b, tree type, tree stmt) { tree body = BLOCK_EXPR_BODY (b), c; - + if (java_error_count) return body; - + if ((c = add_stmt_to_compound (body, type, stmt)) == body) return body; @@ -7468,16 +7429,19 @@ add_stmt_to_block (b, type, stmt) COMPOUND_EXPR and add STMT to it. */ static tree -add_stmt_to_compound (existing, type, stmt) - tree existing, type, stmt; +add_stmt_to_compound (tree existing, tree type, tree stmt) { + /* Keep track of this for inlining. */ + if (current_function_decl) + ++DECL_NUM_STMTS (current_function_decl); + if (existing) return build (COMPOUND_EXPR, type, existing, stmt); else return stmt; } -void java_layout_seen_class_methods () +void java_layout_seen_class_methods (void) { tree previous_list = all_class_list; tree end = NULL_TREE; @@ -7485,10 +7449,10 @@ void java_layout_seen_class_methods () while (1) { - for (current = previous_list; + for (current = previous_list; current != end; current = TREE_CHAIN (current)) layout_class_methods (TREE_TYPE (TREE_VALUE (current))); - + if (previous_list != all_class_list) { end = previous_list; @@ -7499,20 +7463,12 @@ void java_layout_seen_class_methods () } } +static GTY(()) tree stop_reordering; void -java_reorder_fields () +java_reorder_fields (void) { - static tree stop_reordering = NULL_TREE; - static int initialized_p; tree current; - /* Register STOP_REORDERING with the garbage collector. */ - if (!initialized_p) - { - ggc_add_tree_root (&stop_reordering, 1); - initialized_p = 1; - } - for (current = gclass_list; current; current = TREE_CHAIN (current)) { current_class = TREE_TYPE (TREE_VALUE (current)); @@ -7537,7 +7493,7 @@ java_reorder_fields () after having reversed the fields */ else { - TYPE_FIELDS (current_class) = + TYPE_FIELDS (current_class) = nreverse (TYPE_FIELDS (current_class)); TYPE_SIZE (current_class) = NULL_TREE; } @@ -7554,7 +7510,7 @@ java_reorder_fields () classes */ void -java_layout_classes () +java_layout_classes (void) { tree current; int save_error_count = java_error_count; @@ -7591,7 +7547,7 @@ java_layout_classes () generation. */ static void -java_complete_expand_classes () +java_complete_expand_classes (void) { tree current; @@ -7606,8 +7562,7 @@ java_complete_expand_classes () classes, if any. */ static void -java_complete_expand_class (outer) - tree outer; +java_complete_expand_class (tree outer) { tree inner_list; @@ -7633,8 +7588,7 @@ java_complete_expand_class (outer) constructors and then . */ static void -java_complete_expand_methods (class_decl) - tree class_decl; +java_complete_expand_methods (tree class_decl) { tree clinit, decl, first_decl; @@ -7667,7 +7621,7 @@ java_complete_expand_methods (class_decl) if (!DECL_CONSTRUCTOR_P (decl)) continue; - + no_body = !DECL_FUNCTION_BODY (decl); /* Don't generate debug info on line zero when expanding a generated constructor. */ @@ -7686,7 +7640,7 @@ java_complete_expand_methods (class_decl) /* Ctors aren't part of this batch. */ if (DECL_CONSTRUCTOR_P (decl) || DECL_CLINIT_P (decl)) continue; - + /* Skip abstract or native methods -- but do handle native methods when generating JNI stubs. */ if (METHOD_ABSTRACT (decl) || (! flag_jni && METHOD_NATIVE (decl))) @@ -7697,7 +7651,9 @@ java_complete_expand_methods (class_decl) if (METHOD_NATIVE (decl)) { - tree body = build_jni_stub (decl); + tree body; + current_function_decl = decl; + body = build_jni_stub (decl); BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (decl)) = body; } @@ -7712,7 +7668,7 @@ java_complete_expand_methods (class_decl) java_complete_expand_method (clinit); ctxp->explicit_constructor_p = 0; } - + /* We might have generated a class$ that we now want to expand */ if (TYPE_DOT_CLASS (current_class)) java_complete_expand_method (TYPE_DOT_CLASS (current_class)); @@ -7721,7 +7677,7 @@ java_complete_expand_methods (class_decl) prove wrong.) */ if (!CLASS_INTERFACE (class_decl)) for (decl = TYPE_METHODS (current_class); decl; decl = TREE_CHAIN (decl)) - if (DECL_CONSTRUCTOR_P (decl) + if (DECL_CONSTRUCTOR_P (decl) && verify_constructor_circularity (decl, decl)) break; @@ -7733,8 +7689,7 @@ java_complete_expand_methods (class_decl) safely used in some other methods/constructors. */ static tree -maybe_generate_pre_expand_clinit (class_type) - tree class_type; +maybe_generate_pre_expand_clinit (tree class_type) { tree current, mdecl; @@ -7742,7 +7697,7 @@ maybe_generate_pre_expand_clinit (class_type) return NULL_TREE; /* Go through all static fields and pre expand them */ - for (current = TYPE_FIELDS (class_type); current; + for (current = TYPE_FIELDS (class_type); current; current = TREE_CHAIN (current)) if (FIELD_STATIC (current)) build_field_ref (NULL_TREE, class_type, DECL_NAME (current)); @@ -7793,8 +7748,7 @@ maybe_generate_pre_expand_clinit (class_type) MODIFY_EXPR with a constant value. */ static int -analyze_clinit_body (this_class, bbody) - tree this_class, bbody; +analyze_clinit_body (tree this_class, tree bbody) { while (bbody) switch (TREE_CODE (bbody)) @@ -7802,17 +7756,17 @@ analyze_clinit_body (this_class, bbody) case BLOCK: bbody = BLOCK_EXPR_BODY (bbody); break; - + case EXPR_WITH_FILE_LOCATION: bbody = EXPR_WFL_NODE (bbody); break; - + case COMPOUND_EXPR: if (analyze_clinit_body (this_class, TREE_OPERAND (bbody, 0))) return 1; bbody = TREE_OPERAND (bbody, 1); break; - + case MODIFY_EXPR: /* If we're generating to class file and we're dealing with an array initialization, we return 1 to keep */ @@ -7842,12 +7796,11 @@ analyze_clinit_body (this_class, bbody) is empty. Return 1 if was discarded, 0 otherwise. */ static int -maybe_yank_clinit (mdecl) - tree mdecl; +maybe_yank_clinit (tree mdecl) { tree type, current; tree fbody, bbody; - + if (!DECL_CLINIT_P (mdecl)) return 0; @@ -7866,7 +7819,7 @@ maybe_yank_clinit (mdecl) type = DECL_CONTEXT (mdecl); current = TYPE_FIELDS (type); - for (current = (current ? TREE_CHAIN (current) : current); + for (current = (current ? TREE_CHAIN (current) : current); current; current = TREE_CHAIN (current)) { tree f_init; @@ -7901,7 +7854,7 @@ maybe_yank_clinit (mdecl) if (TYPE_METHODS (type) == mdecl) TYPE_METHODS (type) = TREE_CHAIN (mdecl); else - for (current = TYPE_METHODS (type); current; + for (current = TYPE_METHODS (type); current; current = TREE_CHAIN (current)) if (TREE_CHAIN (current) == mdecl) { @@ -7916,8 +7869,7 @@ maybe_yank_clinit (mdecl) expansion of mdecl's body. */ static void -start_complete_expand_method (mdecl) - tree mdecl; +start_complete_expand_method (tree mdecl) { tree tem; @@ -7927,7 +7879,7 @@ start_complete_expand_method (mdecl) for (; tem; tem = TREE_CHAIN (tem)) { - /* TREE_CHAIN (tem) will change after pushdecl. */ + /* TREE_CHAIN (tem) will change after pushdecl. */ tree next = TREE_CHAIN (tem); tree type = TREE_TYPE (tem); if (PROMOTE_PROTOTYPES @@ -7942,7 +7894,7 @@ start_complete_expand_method (mdecl) TREE_CHAIN (tem) = next; } pushdecl_force_head (DECL_ARGUMENTS (mdecl)); - lineno = DECL_SOURCE_LINE_FIRST (mdecl); + input_line = DECL_SOURCE_LINE_FIRST (mdecl); build_result_decl (mdecl); } @@ -7950,8 +7902,7 @@ start_complete_expand_method (mdecl) /* Complete and expand a method. */ static void -java_complete_expand_method (mdecl) - tree mdecl; +java_complete_expand_method (tree mdecl) { tree fbody, block_body, exception_copy; @@ -7959,7 +7910,7 @@ java_complete_expand_method (mdecl) /* Fix constructors before expanding them */ if (DECL_CONSTRUCTOR_P (mdecl)) fix_constructors (mdecl); - + /* Expand functions that have a body */ if (!DECL_FUNCTION_BODY (mdecl)) return; @@ -7976,35 +7927,35 @@ java_complete_expand_method (mdecl) announce_function (mdecl); if (! quiet_flag) fprintf (stderr, "]"); - + /* Prepare the function for tree completion */ start_complete_expand_method (mdecl); /* Install the current this */ - current_this = (!METHOD_STATIC (mdecl) ? + current_this = (!METHOD_STATIC (mdecl) ? BLOCK_EXPR_DECLS (DECL_FUNCTION_BODY (mdecl)) : NULL_TREE); /* Purge the `throws' list of unchecked exceptions (we save a copy of the list and re-install it later.) */ exception_copy = copy_list (DECL_FUNCTION_THROWS (mdecl)); purge_unchecked_exceptions (mdecl); - + /* Install exceptions thrown with `throws' */ PUSH_EXCEPTIONS (DECL_FUNCTION_THROWS (mdecl)); - + if (block_body != NULL_TREE) { block_body = java_complete_tree (block_body); - + /* Before we check initialization, attached all class initialization variable to the block_body */ - hash_traverse (&DECL_FUNCTION_INIT_TEST_TABLE (mdecl), + htab_traverse (DECL_FUNCTION_INIT_TEST_TABLE (mdecl), attach_init_test_initialization_flags, block_body); - + if (! flag_emit_xref && ! METHOD_NATIVE (mdecl)) { check_for_initialization (block_body, mdecl); - + /* Go through all the flags marking the initialization of static variables and see whether they're definitively assigned, in which case the type is remembered as @@ -8015,16 +7966,18 @@ java_complete_expand_method (mdecl) MDECL. This used with caution helps removing extra initialization of self. */ if (METHOD_STATIC (mdecl)) - hash_lookup (&DECL_FUNCTION_INITIALIZED_CLASS_TABLE (mdecl), - (hash_table_key) DECL_CONTEXT (mdecl), - TRUE, NULL); + { + *(htab_find_slot + (DECL_FUNCTION_INITIALIZED_CLASS_TABLE (mdecl), + DECL_CONTEXT (mdecl), INSERT)) = DECL_CONTEXT (mdecl); + } } } ctxp->explicit_constructor_p = 0; } - + BLOCK_EXPR_BODY (fbody) = block_body; - + /* If we saw a return but couldn't evaluate it properly, we'll have an error_mark_node here. */ if (block_body != error_mark_node @@ -8053,8 +8006,7 @@ java_complete_expand_method (mdecl) /* For with each class for which there's code to generate. */ static void -java_expand_method_bodies (class) - tree class; +java_expand_method_bodies (tree class) { tree decl; for (decl = TYPE_METHODS (class); decl; decl = TREE_CHAIN (decl)) @@ -8064,6 +8016,11 @@ java_expand_method_bodies (class) current_function_decl = decl; + /* Save the function for inlining. */ + if (flag_inline_trees) + DECL_SAVED_TREE (decl) = + BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (decl)); + /* It's time to assign the variable flagging static class initialization based on which classes invoked static methods are definitely initializing. This should be flagged. */ @@ -8085,7 +8042,7 @@ java_expand_method_bodies (class) /* For each class definitely initialized in CALLED_METHOD, fill ASSIGNMENT_COMPOUND with assignment to the class initialization flag. */ - hash_traverse (&DECL_FUNCTION_INITIALIZED_CLASS_TABLE (called_method), + htab_traverse (DECL_FUNCTION_INITIALIZED_CLASS_TABLE (called_method), emit_test_initialization, assignment_compound_list); @@ -8095,7 +8052,7 @@ java_expand_method_bodies (class) } } - /* Prepare the function for RTL expansion */ + /* Prepare the function for RTL expansion */ start_complete_expand_method (decl); /* Expand function start, generate initialization flag @@ -8121,8 +8078,7 @@ java_expand_method_bodies (class) be later turned into a write by calling outer_field_access_fix. */ static tree -build_outer_field_access (id, decl) - tree id, decl; +build_outer_field_access (tree id, tree decl) { tree access = NULL_TREE; tree ctx = TREE_TYPE (DECL_CONTEXT (TYPE_NAME (current_class))); @@ -8136,7 +8092,7 @@ build_outer_field_access (id, decl) && (!FIELD_PRIVATE (decl) || !flag_emit_class_files )) { tree thisn = build_current_thisn (current_class); - access = make_qualified_primary (build_wfl_node (thisn), + access = make_qualified_primary (build_wfl_node (thisn), id, EXPR_WFL_LINECOL (id)); } /* Otherwise, generate access methods to outer this and access the @@ -8167,18 +8123,17 @@ build_outer_field_access (id, decl) return resolve_expression_name (access, NULL); } -/* Return a non zero value if NODE describes an outer field inner +/* Return a nonzero value if NODE describes an outer field inner access. */ static int -outer_field_access_p (type, decl) - tree type, decl; +outer_field_access_p (tree type, tree decl) { - if (!INNER_CLASS_TYPE_P (type) + if (!INNER_CLASS_TYPE_P (type) || TREE_CODE (decl) != FIELD_DECL || DECL_CONTEXT (decl) == type) return 0; - + /* If the inner class extends the declaration context of the field we're try to acces, then this isn't an outer field access */ if (inherits_from_p (type, DECL_CONTEXT (decl))) @@ -8203,15 +8158,15 @@ outer_field_access_p (type, decl) return 0; } -/* Return a non zero value if NODE represents an outer field inner +/* Return a nonzero value if NODE represents an outer field inner access that was been already expanded. As a side effect, it returns the name of the field being accessed and the argument passed to the access function, suitable for a regeneration of the access method call if necessary. */ static int -outer_field_expanded_access_p (node, name, arg_type, arg) - tree node, *name, *arg_type, *arg; +outer_field_expanded_access_p (tree node, tree *name, tree *arg_type, + tree *arg) { int identified = 0; @@ -8221,21 +8176,21 @@ outer_field_expanded_access_p (node, name, arg_type, arg) /* Well, gcj generates slightly different tree nodes when compiling to native or bytecodes. It's the case for function calls. */ - if (flag_emit_class_files + if (flag_emit_class_files && TREE_CODE (node) == CALL_EXPR && OUTER_FIELD_ACCESS_IDENTIFIER_P (DECL_NAME (TREE_OPERAND (node, 0)))) identified = 1; else if (!flag_emit_class_files) { node = TREE_OPERAND (node, 0); - + if (node && TREE_OPERAND (node, 0) && TREE_CODE (TREE_OPERAND (node, 0)) == ADDR_EXPR) { node = TREE_OPERAND (node, 0); if (TREE_OPERAND (node, 0) && TREE_CODE (TREE_OPERAND (node, 0)) == FUNCTION_DECL - && (OUTER_FIELD_ACCESS_IDENTIFIER_P + && (OUTER_FIELD_ACCESS_IDENTIFIER_P (DECL_NAME (TREE_OPERAND (node, 0))))) identified = 1; } @@ -8257,14 +8212,13 @@ outer_field_expanded_access_p (node, name, arg_type, arg) be identified. */ static tree -outer_field_access_fix (wfl, node, rhs) - tree wfl, node, rhs; +outer_field_access_fix (tree wfl, tree node, tree rhs) { tree name, arg_type, arg; - + if (outer_field_expanded_access_p (node, &name, &arg_type, &arg)) { - node = build_outer_field_access_expr (EXPR_WFL_LINECOL (wfl), + node = build_outer_field_access_expr (EXPR_WFL_LINECOL (wfl), arg_type, name, arg, rhs); return java_complete_tree (node); } @@ -8272,19 +8226,18 @@ outer_field_access_fix (wfl, node, rhs) } /* Construct the expression that calls an access method: - .access$( [, ]); + .access$( [, ]); ARG2 can be NULL and will be omitted in that case. It will denote a read access. */ static tree -build_outer_field_access_expr (lc, type, access_method_name, arg1, arg2) - int lc; - tree type, access_method_name, arg1, arg2; +build_outer_field_access_expr (int lc, tree type, tree access_method_name, + tree arg1, tree arg2) { tree args, cn, access; - args = arg1 ? arg1 : + args = arg1 ? arg1 : build_wfl_node (build_current_thisn (current_class)); args = build_tree_list (NULL_TREE, args); @@ -8297,7 +8250,7 @@ build_outer_field_access_expr (lc, type, access_method_name, arg1, arg2) } static tree -build_new_access_id () +build_new_access_id (void) { static int access_n_counter = 1; char buffer [128]; @@ -8321,16 +8274,15 @@ build_new_access_id () */ static tree -build_outer_field_access_methods (decl) - tree decl; +build_outer_field_access_methods (tree decl) { tree id, args, stmt, mdecl; - + 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 (); @@ -8344,14 +8296,14 @@ build_outer_field_access_methods (decl) stmt = make_qualified_primary (build_wfl_node (inst_id), build_wfl_node (DECL_NAME (decl)), 0); stmt = build_return (0, stmt); - mdecl = build_outer_field_access_method (DECL_CONTEXT (decl), + mdecl = build_outer_field_access_method (DECL_CONTEXT (decl), TREE_TYPE (decl), id, args, stmt); DECL_FUNCTION_ACCESS_DECL (mdecl) = decl; /* Create the write access method. No write access for final variable */ if (!FIELD_FINAL (decl)) { - args = build_tree_list (inst_id, + 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; @@ -8359,8 +8311,8 @@ build_outer_field_access_methods (decl) 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, + mdecl = build_outer_field_access_method (DECL_CONTEXT (decl), + TREE_TYPE (decl), id, args, stmt); } DECL_FUNCTION_ACCESS_DECL (mdecl) = decl; @@ -8371,9 +8323,9 @@ build_outer_field_access_methods (decl) /* Build an field access method NAME. */ -static tree -build_outer_field_access_method (class, type, name, args, body) - tree class, type, name, args, body; +static tree +build_outer_field_access_method (tree class, tree type, tree name, + tree args, tree body) { tree saved_current_function_decl, mdecl; @@ -8397,8 +8349,7 @@ build_outer_field_access_method (class, type, name, args, body) certain kinds of method invocation from inner classes. */ static tree -build_outer_method_access_method (decl) - tree decl; +build_outer_method_access_method (tree decl) { tree saved_current_function_decl, mdecl; tree args = NULL_TREE, call_args = NULL_TREE; @@ -8422,17 +8373,17 @@ build_outer_method_access_method (decl) carg = TYPE_ARG_TYPES (TREE_TYPE (decl)); /* Create the arguments, as much as the original */ - for (; carg && carg != end_params_node; + for (; carg && carg != end_params_node; carg = TREE_CHAIN (carg)) { sprintf (buffer, "write_parm_value$%d", parm_id_count++); - args = chainon (args, build_tree_list (get_identifier (buffer), + args = chainon (args, build_tree_list (get_identifier (buffer), TREE_VALUE (carg))); } args = chainon (args, end_params_node); /* Create the method */ - mdecl = create_artificial_method (class, ACC_STATIC, + mdecl = create_artificial_method (class, ACC_STATIC, TREE_TYPE (TREE_TYPE (decl)), id, args); layout_class_method (class, NULL_TREE, mdecl, NULL_TREE); /* There is a potential bug here. We should be able to use @@ -8456,10 +8407,10 @@ build_outer_method_access_method (decl) call_args = tree_cons (NULL_TREE, build_wfl_node (TREE_PURPOSE (carg)), call_args); - body = build_method_invocation (build_wfl_node (DECL_NAME (decl)), + body = build_method_invocation (build_wfl_node (DECL_NAME (decl)), call_args); if (!METHOD_STATIC (decl)) - body = make_qualified_primary (build_wfl_node (TREE_PURPOSE (args)), + body = make_qualified_primary (build_wfl_node (TREE_PURPOSE (args)), body, 0); if (TREE_TYPE (TREE_TYPE (decl)) != void_type_node) body = build_return (0, body); @@ -8479,7 +8430,7 @@ build_outer_method_access_method (decl) the enclosing instance of an inner class. The enclosing instance is kept in a generated field called this$, with being the inner class nesting level (starting from 0.) */ - + /* Build an access to a given this$, always chaining access call to others. Access methods to this$ are build on the fly if necessary. This CAN'T be used to solely access this$ from @@ -8487,13 +8438,11 @@ build_outer_method_access_method (decl) for example build_outer_field_access). */ static tree -build_access_to_thisn (from, to, lc) - tree from, to; - int lc; +build_access_to_thisn (tree from, tree to, int lc) { tree access = NULL_TREE; - while (from != to) + while (from != to && PURE_INNER_CLASS_TYPE_P (from)) { if (!access) { @@ -8513,8 +8462,8 @@ build_access_to_thisn (from, to, lc) access = make_qualified_primary (cn, access, lc); } - /* if FROM isn't an inter class, that's fine, we've done - enough. What we're looking for can be accessed from there. */ + /* If FROM isn't an inner class, that's fine, we've done enough. + What we're looking for can be accessed from there. */ from = DECL_CONTEXT (TYPE_NAME (from)); if (!from) break; @@ -8525,14 +8474,13 @@ build_access_to_thisn (from, to, lc) /* Build an access function to the this$ local to TYPE. NULL_TREE is returned if nothing needs to be generated. Otherwise, the method - generated and a method decl is returned. + generated and a method decl is returned. NOTE: These generated methods should be declared in a class file attribute so that they can't be referred to directly. */ static tree -maybe_build_thisn_access_method (type) - tree type; +maybe_build_thisn_access_method (tree type) { tree mdecl, args, stmt, rtype; tree saved_current_function_decl; @@ -8553,7 +8501,7 @@ maybe_build_thisn_access_method (type) fix_method_argument_names (args, mdecl); layout_class_method (type, NULL_TREE, mdecl, NULL_TREE); stmt = build_current_thisn (type); - stmt = make_qualified_primary (build_wfl_node (inst_id), + stmt = make_qualified_primary (build_wfl_node (inst_id), build_wfl_node (stmt), 0); stmt = build_return (0, stmt); @@ -8573,37 +8521,28 @@ maybe_build_thisn_access_method (type) This function can be invoked with TYPE to NULL, available and then has to count the parser context. */ +static GTY(()) tree saved_thisn; +static GTY(()) tree saved_type; + static tree -build_current_thisn (type) - tree type; +build_current_thisn (tree type) { static int saved_i = -1; - static tree saved_thisn = NULL_TREE; - static tree saved_type = NULL_TREE; static int saved_type_i = 0; - static int initialized_p; tree decl; char buffer [24]; int i = 0; - /* Register SAVED_THISN and SAVED_TYPE with the garbage collector. */ - if (!initialized_p) - { - ggc_add_tree_root (&saved_thisn, 1); - ggc_add_tree_root (&saved_type, 1); - initialized_p = 1; - } - if (type) { if (type == saved_type) i = saved_type_i; else { - for (i = -1, decl = DECL_CONTEXT (TYPE_NAME (type)); + for (i = -1, decl = DECL_CONTEXT (TYPE_NAME (type)); decl; decl = DECL_CONTEXT (decl), i++) ; - + saved_type = type; saved_type_i = i; } @@ -8613,7 +8552,7 @@ build_current_thisn (type) if (i == saved_i) return saved_thisn; - + sprintf (buffer, "this$%d", i); saved_i = i; saved_thisn = get_identifier (buffer); @@ -8625,7 +8564,7 @@ build_current_thisn (type) form used is `this.this$ = this$;'. */ static tree -build_thisn_assign () +build_thisn_assign (void) { if (current_class && PURE_INNER_CLASS_TYPE_P (current_class)) { @@ -8633,7 +8572,7 @@ build_thisn_assign () tree lhs = make_qualified_primary (build_wfl_node (this_identifier_node), build_wfl_node (thisn), 0); tree rhs = build_wfl_node (thisn); - EXPR_WFL_SET_LINECOL (lhs, lineno, 0); + EXPR_WFL_SET_LINECOL (lhs, input_line, 0); return build_assignment (ASSIGN_TK, EXPR_WFL_LINECOL (lhs), lhs, rhs); } return NULL_TREE; @@ -8650,23 +8589,21 @@ build_thisn_assign () throw new NoClassDefFoundError(e.getMessage());} } */ +static GTY(()) tree get_message_wfl; +static GTY(()) tree type_parm_wfl; + static tree -build_dot_class_method (class) - tree class; +build_dot_class_method (tree class) { #define BWF(S) build_wfl_node (get_identifier ((S))) #define MQN(X,Y) make_qualified_name ((X), (Y), 0) tree args, tmp, saved_current_function_decl, mdecl; tree stmt, throw_stmt; - static tree get_message_wfl, type_parm_wfl; - if (!get_message_wfl) { get_message_wfl = build_wfl_node (get_identifier ("getMessage")); type_parm_wfl = build_wfl_node (get_identifier ("type$")); - ggc_add_tree_root (&get_message_wfl, 1); - ggc_add_tree_root (&type_parm_wfl, 1); } /* Build the arguments */ @@ -8675,32 +8612,32 @@ build_dot_class_method (class) TREE_CHAIN (args) = end_params_node; /* Build the qualified name java.lang.Class.forName */ - tmp = MQN (MQN (MQN (BWF ("java"), + tmp = MQN (MQN (MQN (BWF ("java"), BWF ("lang")), BWF ("Class")), BWF ("forName")); load_class (class_not_found_type_node, 1); load_class (no_class_def_found_type_node, 1); - + /* Create the "class$" function */ - mdecl = create_artificial_method (class, ACC_STATIC, + mdecl = create_artificial_method (class, ACC_STATIC, build_pointer_type (class_type_node), classdollar_identifier_node, args); - DECL_FUNCTION_THROWS (mdecl) = + DECL_FUNCTION_THROWS (mdecl) = build_tree_list (NULL_TREE, no_class_def_found_type_node); /* We start by building the try block. We need to build: return (java.lang.Class.forName (type)); */ - stmt = build_method_invocation (tmp, + stmt = build_method_invocation (tmp, build_tree_list (NULL_TREE, type_parm_wfl)); stmt = build_return (0, stmt); /* Now onto the catch block. We start by building the expression throwing a new exception: throw new NoClassDefFoundError (_.getMessage) */ - throw_stmt = make_qualified_name (build_wfl_node (wpv_id), + throw_stmt = make_qualified_name (build_wfl_node (wpv_id), get_message_wfl, 0); throw_stmt = build_method_invocation (throw_stmt, NULL_TREE); - + /* Build new NoClassDefFoundError (_.getMessage) */ - throw_stmt = build_new_invocation + throw_stmt = build_new_invocation (build_wfl_node (get_identifier ("NoClassDefFoundError")), build_tree_list (build_pointer_type (string_type_node), throw_stmt)); @@ -8724,8 +8661,7 @@ build_dot_class_method (class) } static tree -build_dot_class_method_invocation (type) - tree type; +build_dot_class_method_invocation (tree type) { tree sig_id, s; @@ -8738,7 +8674,7 @@ build_dot_class_method_invocation (type) sig_id = unmangle_classname (IDENTIFIER_POINTER (sig_id), IDENTIFIER_LENGTH (sig_id)); - s = build_string (IDENTIFIER_LENGTH (sig_id), + s = build_string (IDENTIFIER_LENGTH (sig_id), IDENTIFIER_POINTER (sig_id)); return build_method_invocation (build_wfl_node (classdollar_identifier_node), build_tree_list (NULL_TREE, s)); @@ -8751,8 +8687,7 @@ build_dot_class_method_invocation (type) necessary. */ static void -fix_constructors (mdecl) - tree mdecl; +fix_constructors (tree mdecl) { tree iii; /* Instance Initializer Invocation */ tree body = DECL_FUNCTION_BODY (mdecl); @@ -8775,17 +8710,17 @@ fix_constructors (mdecl) const char *n = IDENTIFIER_POINTER (DECL_NAME (sclass_decl)); DECL_NAME (mdecl) = DECL_NAME (sclass_decl); parse_error_context - (lookup_cl (TYPE_NAME (class_type)), + (lookup_cl (TYPE_NAME (class_type)), "No constructor matching `%s' found in class `%s'", lang_printable_name (mdecl, 0), n); DECL_NAME (mdecl) = save; } - + /* The constructor body must be crafted by hand. It's the constructor we defined when we realize we didn't have the CLASSNAME() constructor */ start_artificial_method_body (mdecl); - + /* Insert an assignment to the this$ hidden field, if necessary */ if ((thisn_assign = build_thisn_assign ())) @@ -8803,13 +8738,13 @@ fix_constructors (mdecl) end_artificial_method_body (mdecl); } /* Search for an explicit constructor invocation */ - else + else { int found = 0; int invokes_this = 0; tree found_call = NULL_TREE; tree main_block = BLOCK_EXPR_BODY (body); - + while (body) switch (TREE_CODE (body)) { @@ -8849,7 +8784,7 @@ fix_constructors (mdecl) TREE_OPERAND (found_call, 0)); TREE_OPERAND (found_call, 0) = empty_stmt_node; } - + DECL_INIT_CALLS_THIS (mdecl) = invokes_this; /* Insert the instance initializer block right after. */ @@ -8872,8 +8807,7 @@ fix_constructors (mdecl) for something that has the same signature. */ static int -verify_constructor_super (mdecl) - tree mdecl; +verify_constructor_super (tree mdecl) { tree class = CLASSTYPE_SUPER (current_class); int super_inner = PURE_INNER_CLASS_TYPE_P (class); @@ -8893,12 +8827,12 @@ verify_constructor_super (mdecl) tree arg_type = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (sdecl))); if (super_inner) arg_type = TREE_CHAIN (arg_type); - for (m_arg_type = mdecl_arg_type; - (arg_type != end_params_node + for (m_arg_type = mdecl_arg_type; + (arg_type != end_params_node && m_arg_type != end_params_node); - arg_type = TREE_CHAIN (arg_type), + arg_type = TREE_CHAIN (arg_type), m_arg_type = TREE_CHAIN (m_arg_type)) - if (!valid_method_invocation_conversion_p + if (!valid_method_invocation_conversion_p (TREE_VALUE (arg_type), TREE_VALUE (m_arg_type))) break; @@ -8923,8 +8857,9 @@ verify_constructor_super (mdecl) /* Generate code for all context remembered for code generation. */ +static GTY(()) tree reversed_class_list; void -java_expand_classes () +java_expand_classes (void) { int save_error_count = 0; static struct parser_ctxt *cur_ctxp = NULL; @@ -8935,8 +8870,7 @@ java_expand_classes () java_layout_classes (); java_parse_abort_on_error (); - cur_ctxp = ctxp_for_generation; - for (; cur_ctxp; cur_ctxp = cur_ctxp->next) + for (cur_ctxp = ctxp_for_generation; cur_ctxp; cur_ctxp = cur_ctxp->next) { ctxp = cur_ctxp; input_filename = ctxp->filename; @@ -8946,9 +8880,11 @@ java_expand_classes () } input_filename = main_input_filename; - /* Find anonymous classes and expand their constructor, now they - have been fixed. */ - for (cur_ctxp = ctxp_for_generation; cur_ctxp; cur_ctxp = cur_ctxp->next) + + /* Find anonymous classes and expand their constructor. This extra pass is + neccessary because the constructor itself is only generated when the + method in which it is defined is expanded. */ + for (cur_ctxp = ctxp_for_generation; cur_ctxp; cur_ctxp = cur_ctxp->next) { tree current; ctxp = cur_ctxp; @@ -8965,29 +8901,120 @@ java_expand_classes () restore_line_number_status (1); java_complete_expand_method (d); restore_line_number_status (0); - break; /* We now there are no other ones */ + break; /* There is only one constructor. */ + } + } + } + } + } + + /* Expanding the constructors of anonymous classes generates access + methods. Scan all the methods looking for null DECL_RESULTs -- + this will be the case if a method hasn't been expanded. */ + for (cur_ctxp = ctxp_for_generation; cur_ctxp; cur_ctxp = cur_ctxp->next) + { + tree current; + ctxp = cur_ctxp; + for (current = ctxp->class_list; current; current = TREE_CHAIN (current)) + { + tree d; + current_class = TREE_TYPE (current); + for (d = TYPE_METHODS (current_class); d; d = TREE_CHAIN (d)) + { + if (DECL_RESULT (d) == NULL_TREE) + { + restore_line_number_status (1); + java_complete_expand_method (d); + restore_line_number_status (0); + } + } + } + } + + /* ??? Instead of all this we could iterate around the list of + classes until there were no more un-expanded methods. It would + take a little longer -- one pass over the whole list of methods + -- but it would be simpler. Like this: */ +#if 0 + { + int something_changed; + + do + { + something_changed = 0; + for (cur_ctxp = ctxp_for_generation; cur_ctxp; cur_ctxp = cur_ctxp->next) + { + tree current; + ctxp = cur_ctxp; + for (current = ctxp->class_list; current; current = TREE_CHAIN (current)) + { + tree d; + current_class = TREE_TYPE (current); + for (d = TYPE_METHODS (current_class); d; d = TREE_CHAIN (d)) + { + if (DECL_RESULT (d) == NULL_TREE) + { + something_changed = 1; + restore_line_number_status (1); + java_complete_expand_method (d); + restore_line_number_status (0); + } } } } } + while (something_changed); } +#endif /* If we've found error at that stage, don't try to generate anything, unless we're emitting xrefs or checking the syntax only (but not using -fsyntax-only for the purpose of generating bytecode. */ - if (java_error_count && !flag_emit_xref + if (java_error_count && !flag_emit_xref && (!flag_syntax_only && !flag_emit_class_files)) return; /* Now things are stable, go for generation of the class data. */ - for (cur_ctxp = ctxp_for_generation; cur_ctxp; cur_ctxp = cur_ctxp->next) + + /* We pessimistically marked all methods and fields external until + we knew what set of classes we were planning to compile. Now mark + those that will be generated locally as not external. */ + for (cur_ctxp = ctxp_for_generation; cur_ctxp; cur_ctxp = cur_ctxp->next) { tree current; ctxp = cur_ctxp; for (current = ctxp->class_list; current; current = TREE_CHAIN (current)) + java_mark_class_local (TREE_TYPE (current)); + } + + /* Compile the classes. */ + for (cur_ctxp = ctxp_for_generation; cur_ctxp; cur_ctxp = cur_ctxp->next) + { + tree current; + reversed_class_list = NULL; + + ctxp = cur_ctxp; + + /* We write out the classes in reverse order. This ensures that + inner classes are written before their containing classes, + which is important for parallel builds. Otherwise, the + class file for the outer class may be found, but the class + file for the inner class may not be present. In that + situation, the compiler cannot fall back to the original + source, having already read the outer class, so we must + prevent that situation. */ + for (current = ctxp->class_list; + current; + current = TREE_CHAIN (current)) + reversed_class_list + = tree_cons (NULL_TREE, current, reversed_class_list); + + for (current = reversed_class_list; + current; + current = TREE_CHAIN (current)) { - current_class = TREE_TYPE (current); + current_class = TREE_TYPE (TREE_VALUE (current)); outgoing_cpool = TYPE_CPOOL (current_class); if (flag_emit_class_files) write_classfile (current_class); @@ -9008,9 +9035,7 @@ java_expand_classes () separating `.' operator. */ static tree -make_qualified_primary (primary, right, location) - tree primary, right; - int location; +make_qualified_primary (tree primary, tree right, int location) { tree wfl; @@ -9034,8 +9059,7 @@ make_qualified_primary (primary, right, location) /* Simple merge of two name separated by a `.' */ static tree -merge_qualified_name (left, right) - tree left, right; +merge_qualified_name (tree left, tree right) { tree node; if (!left && !right) @@ -9063,9 +9087,7 @@ merge_qualified_name (left, right) inherited from the location information of the `.' operator. */ static tree -make_qualified_name (left, right, location) - tree left, right; - int location; +make_qualified_name (tree left, tree right, int location) { #ifdef USE_COMPONENT_REF tree node = build (COMPONENT_REF, NULL_TREE, left, right); @@ -9085,7 +9107,7 @@ make_qualified_name (left, right, location) EXPR_WFL_LINECOL (wfl) = EXPR_WFL_LINECOL (left); EXPR_WFL_QUALIFICATION (left) = build_tree_list (wfl, NULL_TREE); } - + wfl = build_expr_wfl (right_id, ctxp->filename, 0, 0); EXPR_WFL_LINECOL (wfl) = location; chainon (EXPR_WFL_QUALIFICATION (left), build_tree_list (wfl, NULL_TREE)); @@ -9099,8 +9121,7 @@ make_qualified_name (left, right, location) last identifier is removed from the linked list */ static tree -cut_identifier_in_qualified (wfl) - tree wfl; +cut_identifier_in_qualified (tree wfl) { tree q; tree previous = NULL_TREE; @@ -9119,9 +9140,7 @@ cut_identifier_in_qualified (wfl) /* Resolve the expression name NAME. Return its decl. */ static tree -resolve_expression_name (id, orig) - tree id; - tree *orig; +resolve_expression_name (tree id, tree *orig) { tree name = EXPR_WFL_NODE (id); tree decl; @@ -9135,7 +9154,7 @@ resolve_expression_name (id, orig) return decl; /* 15.13.1: NAME can appear within a class declaration */ - else + else { decl = lookup_field_wrapper (current_class, name); if (decl) @@ -9149,6 +9168,8 @@ resolve_expression_name (id, orig) if (FIELD_LOCAL_ALIAS_USED (decl)) name = DECL_NAME (decl); + check_deprecation (id, decl); + /* Instance variable (8.3.1.1) can't appear within static method, static initializer or initializer for a static variable. */ @@ -9210,26 +9231,25 @@ resolve_expression_name (id, orig) /* We've got an error here */ if (INNER_CLASS_TYPE_P (current_class)) - parse_error_context (id, + parse_error_context (id, "Local variable `%s' can't be accessed from within the inner class `%s' unless it is declared final", IDENTIFIER_POINTER (name), IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (current_class)))); else - parse_error_context (id, "Undefined variable `%s'", + parse_error_context (id, "Undefined variable `%s'", IDENTIFIER_POINTER (name)); return error_mark_node; } static void -static_ref_err (wfl, field_id, class_type) - tree wfl, field_id, class_type; +static_ref_err (tree wfl, tree field_id, tree class_type) { - parse_error_context - (wfl, + parse_error_context + (wfl, "Can't make a static reference to nonstatic variable `%s' in class `%s'", - IDENTIFIER_POINTER (field_id), + IDENTIFIER_POINTER (field_id), IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (class_type)))); } @@ -9239,9 +9259,7 @@ static_ref_err (wfl, field_id, class_type) recipient's address can be null. */ static tree -resolve_field_access (qual_wfl, field_decl, field_type) - tree qual_wfl; - tree *field_decl, *field_type; +resolve_field_access (tree qual_wfl, tree *field_decl, tree *field_type) { int is_static = 0; tree field_ref; @@ -9252,8 +9270,8 @@ resolve_field_access (qual_wfl, field_decl, field_type) return error_mark_node; /* Resolve the LENGTH field of an array here */ - if (DECL_P (decl) && DECL_NAME (decl) == length_identifier_node - && type_found && TYPE_ARRAY_P (type_found) + if (DECL_P (decl) && DECL_NAME (decl) == length_identifier_node + && type_found && TYPE_ARRAY_P (type_found) && ! flag_emit_class_files && ! flag_emit_xref) { tree length = build_java_array_length_access (where_found); @@ -9280,13 +9298,26 @@ resolve_field_access (qual_wfl, field_decl, field_type) if (!type_found) type_found = DECL_CONTEXT (decl); is_static = FIELD_STATIC (decl); - field_ref = build_field_ref ((is_static && !flag_emit_xref? - NULL_TREE : where_found), + field_ref = build_field_ref ((is_static && !flag_emit_xref? + NULL_TREE : where_found), type_found, DECL_NAME (decl)); if (field_ref == error_mark_node) return error_mark_node; if (is_static) field_ref = maybe_build_class_init_for_field (decl, field_ref); + + /* If we're looking at a static field, we may need to generate a + class initialization for it. This can happen when the access + looks like `field.ref', where `field' is a static field in an + interface we implement. */ + if (!flag_emit_class_files + && !flag_emit_xref + && TREE_CODE (where_found) == VAR_DECL + && FIELD_STATIC (where_found)) + { + build_static_field_ref (where_found); + field_ref = build_class_init (DECL_CONTEXT (where_found), field_ref); + } } else field_ref = decl; @@ -9294,7 +9325,7 @@ resolve_field_access (qual_wfl, field_decl, field_type) if (field_decl) *field_decl = decl; if (field_type) - *field_type = (QUAL_DECL_TYPE (decl) ? + *field_type = (QUAL_DECL_TYPE (decl) ? QUAL_DECL_TYPE (decl) : TREE_TYPE (decl)); return field_ref; } @@ -9304,8 +9335,7 @@ resolve_field_access (qual_wfl, field_decl, field_type) NODE. */ static tree -strip_out_static_field_access_decl (node) - tree node; +strip_out_static_field_access_decl (tree node) { if (TREE_CODE (node) == COMPOUND_EXPR) { @@ -9328,9 +9358,8 @@ strip_out_static_field_access_decl (node) /* 6.5.5.2: Qualified Expression Names */ static int -resolve_qualified_expression_name (wfl, found_decl, where_found, type_found) - tree wfl; - tree *found_decl, *type_found, *where_found; +resolve_qualified_expression_name (tree wfl, tree *found_decl, + tree *where_found, tree *type_found) { int from_type = 0; /* Field search initiated from a type */ int from_super = 0, from_cast = 0, from_qualified_this = 0; @@ -9338,7 +9367,7 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found) int is_static; tree decl = NULL_TREE, type = NULL_TREE, q; /* For certain for of inner class instantiation */ - tree saved_current, saved_this; + tree saved_current, saved_this; #define RESTORE_THIS_AND_CURRENT_CLASS \ { current_class = saved_current; current_this = saved_this;} @@ -9359,7 +9388,7 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found) build the code to access it. */ if (JDECL_P (decl) && !FIELD_STATIC (decl)) { - decl = maybe_access_field (decl, *where_found, + decl = maybe_access_field (decl, *where_found, DECL_CONTEXT (decl)); if (decl == error_mark_node) return 1; @@ -9375,7 +9404,7 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found) saved and restored shortly after */ saved_current = current_class; saved_this = current_this; - if (decl + if (decl && (TREE_CODE (qual_wfl) == NEW_CLASS_EXPR || from_qualified_this)) { @@ -9399,6 +9428,7 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found) *where_found = patch_method_invocation (qual_wfl, decl, type, from_super, &is_static, &ret_decl); + from_super = 0; if (*where_found == error_mark_node) { RESTORE_THIS_AND_CURRENT_CLASS; @@ -9406,12 +9436,14 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found) } *type_found = type = QUAL_DECL_TYPE (*where_found); + *where_found = force_evaluation_order (*where_found); + /* If we're creating an inner class instance, check for that an enclosing instance is in scope */ if (TREE_CODE (qual_wfl) == NEW_CLASS_EXPR && INNER_ENCLOSING_SCOPE_CHECK (type)) { - parse_error_context + parse_error_context (qual_wfl, "No enclosing instance for inner class `%s' is in scope%s", lang_printable_name (type, 0), (!current_this ? "" : @@ -9425,8 +9457,8 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found) RESTORE_THIS_AND_CURRENT_CLASS; /* EH check. No check on access$ functions */ - if (location - && !OUTER_FIELD_ACCESS_IDENTIFIER_P + if (location + && !OUTER_FIELD_ACCESS_IDENTIFIER_P (DECL_NAME (current_function_decl))) check_thrown_exceptions (location, ret_decl); @@ -9520,7 +9552,7 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found) { if (!current_this) { - parse_error_context + parse_error_context (wfl, "Keyword `this' used outside allowed context"); return 1; } @@ -9543,8 +9575,8 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found) if (!enclosing_context_p (type, current_class)) { char *p = xstrdup (lang_printable_name (type, 0)); - parse_error_context (qual_wfl, "Can't use variable `%s.this': type `%s' isn't an outer type of type `%s'", - p, p, + parse_error_context (qual_wfl, "Can't use variable `%s.this': type `%s' isn't an outer type of type `%s'", + p, p, lang_printable_name (current_class, 0)); free (p); return 1; @@ -9575,12 +9607,12 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found) if (METHOD_STATIC (current_function_decl) || current_class == object_type_node) { - parse_error_context + parse_error_context (wfl, "Keyword `super' used outside allowed context"); return 1; } /* Otherwise, treat SUPER as (SUPER_CLASS)THIS */ - node = build_cast (EXPR_WFL_LINECOL (qual_wfl), + node = build_cast (EXPR_WFL_LINECOL (qual_wfl), CLASSTYPE_SUPER (current_class), build_this (EXPR_WFL_LINECOL (qual_wfl))); *where_found = decl = java_complete_tree (node); @@ -9595,11 +9627,12 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found) assume a variable/class name was meant. */ if (RESOLVE_PACKAGE_NAME_P (qual_wfl)) { - tree name = resolve_package (wfl, &q); - if (name) + tree name; + if ((decl = resolve_package (wfl, &q, &name))) { tree list; - *where_found = decl = resolve_no_layout (name, qual_wfl); + *where_found = decl; + /* We want to be absolutely sure that the class is laid out. We're going to search something inside it. */ *type_found = type = TREE_TYPE (decl); @@ -9621,7 +9654,7 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found) else { if (from_super || from_cast) - parse_error_context + parse_error_context ((from_cast ? qual_wfl : wfl), "No variable `%s' defined in class `%s'", IDENTIFIER_POINTER (EXPR_WFL_NODE (qual_wfl)), @@ -9629,7 +9662,7 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found) else parse_error_context (qual_wfl, "Undefined variable or class name: `%s'", - IDENTIFIER_POINTER (EXPR_WFL_NODE (qual_wfl))); + IDENTIFIER_POINTER (name)); return 1; } } @@ -9643,7 +9676,7 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found) /* Sneak preview. If next we see a `new', we're facing a qualification with resulted in a type being selected instead of a field. Report the error */ - if(TREE_CHAIN (q) + if(TREE_CHAIN (q) && TREE_CODE (TREE_PURPOSE (TREE_CHAIN (q))) == NEW_CLASS_EXPR) { parse_error_context (qual_wfl, "Undefined variable `%s'", @@ -9653,7 +9686,7 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found) if (not_accessible_p (TREE_TYPE (decl), decl, type, 0)) { - parse_error_context + parse_error_context (qual_wfl, "Can't access %s field `%s.%s' from `%s'", java_accstring_lookup (get_access_flags_from_decl (decl)), GET_TYPE_NAME (type), @@ -9667,7 +9700,7 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found) from_type = 1; } /* We resolve an expression name */ - else + else { tree field_decl = NULL_TREE; @@ -9725,14 +9758,14 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found) if (!from_type && !JREFERENCE_TYPE_P (type)) { - parse_error_context + parse_error_context (qual_wfl, "Attempt to reference field `%s' in `%s %s'", IDENTIFIER_POINTER (EXPR_WFL_NODE (qual_wfl)), lang_printable_name (type, 0), - IDENTIFIER_POINTER (DECL_NAME (field_decl))); + IDENTIFIER_POINTER (DECL_NAME (decl))); return 1; } - + field_decl = lookup_field_wrapper (type, EXPR_WFL_NODE (qual_wfl)); @@ -9746,7 +9779,7 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found) inner_decl = resolve_class (decl, ptr, NULL_TREE, qual_wfl); if (inner_decl) { - check_inner_class_access (inner_decl, decl, qual_wfl); + check_inner_class_access (inner_decl, decl, qual_wfl); type = TREE_TYPE (inner_decl); decl = inner_decl; from_type = 1; @@ -9756,9 +9789,9 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found) if (field_decl == NULL_TREE) { - parse_error_context + parse_error_context (qual_wfl, "No variable `%s' defined in type `%s'", - IDENTIFIER_POINTER (EXPR_WFL_NODE (qual_wfl)), + IDENTIFIER_POINTER (EXPR_WFL_NODE (qual_wfl)), GET_TYPE_NAME (type)); return 1; } @@ -9773,37 +9806,37 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found) field_decl_type = TREE_TYPE (TREE_TYPE (field_decl)); else field_decl_type = TREE_TYPE (field_decl); - if (!JPRIMITIVE_TYPE_P (field_decl_type) + if (!JPRIMITIVE_TYPE_P (field_decl_type) && !CLASS_LOADED_P (field_decl_type) && !TYPE_ARRAY_P (field_decl_type)) resolve_and_layout (field_decl_type, NULL_TREE); - + /* Check on accessibility here */ if (not_accessible_p (current_class, field_decl, DECL_CONTEXT (field_decl), from_super)) { - parse_error_context + parse_error_context (qual_wfl, "Can't access %s field `%s.%s' from `%s'", - java_accstring_lookup + java_accstring_lookup (get_access_flags_from_decl (field_decl)), GET_TYPE_NAME (type), IDENTIFIER_POINTER (DECL_NAME (field_decl)), - IDENTIFIER_POINTER + IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (current_class)))); return 1; } check_deprecation (qual_wfl, field_decl); - + /* There are things to check when fields are accessed from type. There are no restrictions on a static declaration of the field when it is accessed from an interface */ is_static = FIELD_STATIC (field_decl); - if (!from_super && from_type - && !TYPE_INTERFACE_P (type) - && !is_static - && (current_function_decl + if (!from_super && from_type + && !TYPE_INTERFACE_P (type) + && !is_static + && (current_function_decl && METHOD_STATIC (current_function_decl))) { static_ref_err (qual_wfl, EXPR_WFL_NODE (qual_wfl), type); @@ -9848,11 +9881,11 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found) /* Sneak preview. If decl is qualified by a `new', report the error here to be accurate on the peculiar construct */ - if (TREE_CHAIN (q) + if (TREE_CHAIN (q) && TREE_CODE (TREE_PURPOSE (TREE_CHAIN (q))) == NEW_CLASS_EXPR && !JREFERENCE_TYPE_P (type)) { - parse_error_context (qual_wfl, "Attempt to reference field `new' in a `%s'", + parse_error_context (qual_wfl, "Attempt to reference field `new' in a `%s'", lang_printable_name (type, 0)); return 1; } @@ -9874,10 +9907,7 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found) method. */ static int -not_accessible_p (reference, member, where, from_super) - tree reference, member; - tree where; - int from_super; +not_accessible_p (tree reference, tree member, tree where, int from_super) { int access_flag = get_access_flags_from_decl (member); @@ -9888,7 +9918,7 @@ not_accessible_p (reference, member, where, from_super) /* Access always granted for members declared public */ if (access_flag & ACC_PUBLIC) return 0; - + /* Check access on protected members */ if (access_flag & ACC_PROTECTED) { @@ -9949,25 +9979,42 @@ not_accessible_p (reference, member, where, from_super) /* Test deprecated decl access. */ static void -check_deprecation (wfl, decl) - tree wfl, decl; +check_deprecation (tree wfl, tree decl) { - const char *file = DECL_SOURCE_FILE (decl); + const char *file; + tree elt; + + if (! flag_deprecated) + return; + + /* We want to look at the element type of arrays here, so we strip + all surrounding array types. */ + if (TYPE_ARRAY_P (TREE_TYPE (decl))) + { + elt = TREE_TYPE (decl); + while (TYPE_ARRAY_P (elt)) + elt = TYPE_ARRAY_ELEMENT (elt); + /* We'll end up with a pointer type, so we use TREE_TYPE to go + to the record. */ + decl = TYPE_NAME (TREE_TYPE (elt)); + } + file = DECL_SOURCE_FILE (decl); + /* Complain if the field is deprecated and the file it was defined in isn't compiled at the same time the file which contains its use is */ - if (DECL_DEPRECATED (decl) + if (DECL_DEPRECATED (decl) && !IS_A_COMMAND_LINE_FILENAME_P (get_identifier (file))) { - char the [20]; + const char *the; switch (TREE_CODE (decl)) { case FUNCTION_DECL: - strcpy (the, "method"); + the = "method"; break; case FIELD_DECL: case VAR_DECL: - strcpy (the, "field"); + the = "field"; break; case TYPE_DECL: parse_warning_context (wfl, "The class `%s' has been deprecated", @@ -9979,8 +10026,8 @@ check_deprecation (wfl, decl) /* Don't issue a message if the context as been deprecated as a whole. */ if (! CLASS_DEPRECATED (TYPE_NAME (DECL_CONTEXT (decl)))) - parse_warning_context - (wfl, "The %s `%s' in class `%s' has been deprecated", + parse_warning_context + (wfl, "The %s `%s' in class `%s' has been deprecated", the, lang_printable_name (decl, 0), IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (DECL_CONTEXT (decl))))); } @@ -9988,15 +10035,14 @@ check_deprecation (wfl, decl) /* Returns 1 if class was declared in the current package, 0 otherwise */ +static GTY(()) tree cicp_cache; static int -class_in_current_package (class) - tree class; +class_in_current_package (tree class) { - static tree cache = NULL_TREE; int qualified_flag; tree left; - if (cache == class) + if (cicp_cache == class) return 1; qualified_flag = QUALIFIED_P (DECL_NAME (TYPE_NAME (class))); @@ -10017,15 +10063,7 @@ class_in_current_package (class) breakdown_qualified (&left, NULL, DECL_NAME (TYPE_NAME (class))); if (ctxp->package == left) { - static int initialized_p; - /* Register CACHE with the garbage collector. */ - if (!initialized_p) - { - ggc_add_tree_root (&cache, 1); - initialized_p = 1; - } - - cache = class; + cicp_cache = class; return 1; } return 0; @@ -10035,12 +10073,11 @@ class_in_current_package (class) done only if certain conditions meet. */ static tree -maybe_access_field (decl, where, type) - tree decl, where, type; +maybe_access_field (tree decl, tree where, tree type) { if (TREE_CODE (decl) == FIELD_DECL && decl != current_this && !FIELD_STATIC (decl)) - decl = build_field_ref (where ? where : current_this, + decl = build_field_ref (where ? where : current_this, (type ? type : DECL_CONTEXT (decl)), DECL_NAME (decl)); return decl; @@ -10051,12 +10088,8 @@ maybe_access_field (decl, where, type) used. IS_STATIC is set to 1 if the invoked function is static. */ static tree -patch_method_invocation (patch, primary, where, from_super, - is_static, ret_decl) - tree patch, primary, where; - int from_super; - int *is_static; - tree *ret_decl; +patch_method_invocation (tree patch, tree primary, tree where, int from_super, + int *is_static, tree *ret_decl) { tree wfl = TREE_OPERAND (patch, 0); tree args = TREE_OPERAND (patch, 1); @@ -10066,7 +10099,7 @@ patch_method_invocation (patch, primary, where, from_super, int is_super_init = 0; tree this_arg = NULL_TREE; int is_array_clone_call = 0; - + /* Should be overriden if everything goes well. Otherwise, if something fails, it should keep this value. It stop the evaluation of a bogus assignment. See java_complete_tree, @@ -10089,14 +10122,14 @@ patch_method_invocation (patch, primary, where, from_super, data during error report. */ identifier_wfl = cut_identifier_in_qualified (wfl); identifier = EXPR_WFL_NODE (identifier_wfl); - + /* Given the context, IDENTIFIER is syntactically qualified as a MethodName. We need to qualify what's before */ qualify_ambiguous_name (wfl); resolved = resolve_field_access (wfl, NULL, NULL); if (TREE_CODE (resolved) == VAR_DECL && FIELD_STATIC (resolved) - && FIELD_FINAL (resolved) + && FIELD_FINAL (resolved) && !inherits_from_p (DECL_CONTEXT (resolved), current_class) && !flag_emit_class_files && !flag_emit_xref) resolved = build_class_init (DECL_CONTEXT (resolved), resolved); @@ -10106,14 +10139,14 @@ patch_method_invocation (patch, primary, where, from_super, type = GET_SKIP_TYPE (resolved); resolve_and_layout (type, NULL_TREE); - + if (JPRIMITIVE_TYPE_P (type)) { parse_error_context (identifier_wfl, "Can't invoke a method on primitive type `%s'", IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)))); - PATCH_METHOD_RETURN_ERROR (); + PATCH_METHOD_RETURN_ERROR (); } list = lookup_method_invoke (0, identifier_wfl, type, identifier, args); @@ -10127,17 +10160,17 @@ patch_method_invocation (patch, primary, where, from_super, parse_error_context (identifier_wfl, "Can't make static reference to method `%s' in interface `%s'", - IDENTIFIER_POINTER (identifier), + IDENTIFIER_POINTER (identifier), IDENTIFIER_POINTER (name)); PATCH_METHOD_RETURN_ERROR (); } if (list && !METHOD_STATIC (list)) { char *fct_name = xstrdup (lang_printable_name (list, 0)); - parse_error_context + parse_error_context (identifier_wfl, "Can't make static reference to method `%s %s' in class `%s'", - lang_printable_name (TREE_TYPE (TREE_TYPE (list)), 0), + lang_printable_name (TREE_TYPE (TREE_TYPE (list)), 0), fct_name, IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)))); free (fct_name); PATCH_METHOD_RETURN_ERROR (); @@ -10145,10 +10178,10 @@ patch_method_invocation (patch, primary, where, from_super, } else this_arg = primary = resolved; - + if (TYPE_ARRAY_P (type) && identifier == get_identifier ("clone")) is_array_clone_call = 1; - + /* IDENTIFIER_WFL will be used to report any problem further */ wfl = identifier_wfl; } @@ -10158,13 +10191,13 @@ patch_method_invocation (patch, primary, where, from_super, { tree class_to_search = NULL_TREE; int lc; /* Looking for Constructor */ - + /* We search constructor in their target class */ if (CALL_CONSTRUCTOR_P (patch)) { if (TREE_CODE (patch) == NEW_CLASS_EXPR) class_to_search = EXPR_WFL_NODE (wfl); - else if (EXPR_WFL_NODE (TREE_OPERAND (patch, 0)) == + else if (EXPR_WFL_NODE (TREE_OPERAND (patch, 0)) == this_identifier_node) class_to_search = NULL_TREE; else if (EXPR_WFL_NODE (TREE_OPERAND (patch, 0)) == @@ -10172,7 +10205,7 @@ patch_method_invocation (patch, primary, where, from_super, { is_super_init = 1; if (CLASSTYPE_SUPER (current_class)) - class_to_search = + class_to_search = DECL_NAME (TYPE_NAME (CLASSTYPE_SUPER (current_class))); else { @@ -10188,19 +10221,19 @@ patch_method_invocation (patch, primary, where, from_super, if (!class_to_search) { - parse_error_context + parse_error_context (wfl, "Class `%s' not found in type declaration", IDENTIFIER_POINTER (EXPR_WFL_NODE (wfl))); PATCH_METHOD_RETURN_ERROR (); } - + /* Can't instantiate an abstract class, but we can invoke it's constructor. It's use within the `new' context is denied here. */ - if (CLASS_ABSTRACT (class_to_search) + if (CLASS_ABSTRACT (class_to_search) && TREE_CODE (patch) == NEW_CLASS_EXPR) { - parse_error_context + parse_error_context (wfl, "Class `%s' is an abstract class. It can't be instantiated", IDENTIFIER_POINTER (EXPR_WFL_NODE (wfl))); PATCH_METHOD_RETURN_ERROR (); @@ -10252,13 +10285,13 @@ patch_method_invocation (patch, primary, where, from_super, can't be executed then. */ if (!list) PATCH_METHOD_RETURN_ERROR (); - + if (TYPE_ARRAY_P (class_to_search) && DECL_NAME (list) == get_identifier ("clone")) is_array_clone_call = 1; /* Check for static reference if non static methods */ - if (check_for_static_method_reference (wfl, patch, list, + if (check_for_static_method_reference (wfl, patch, list, class_to_search, primary)) PATCH_METHOD_RETURN_ERROR (); @@ -10268,7 +10301,7 @@ patch_method_invocation (patch, primary, where, from_super, && INNER_ENCLOSING_SCOPE_CHECK (class_to_search) && !DECL_INIT_P (current_function_decl)) { - parse_error_context + parse_error_context (wfl, "No enclosing instance for inner class `%s' is in scope%s", lang_printable_name (class_to_search, 0), (!current_this ? "" : @@ -10296,17 +10329,17 @@ patch_method_invocation (patch, primary, where, from_super, x(a1,...,an) into TYPE_OF(this$).x(a1,....an) 2) We're generating bytecodes: - + - LIST is non static. It's invocation is transformed from x(a1,....,an) into access$(this$,a1,...,an). - LIST is static. It's invocation is transformed from x(a1,....,an) into TYPE_OF(this$).x(a1,....an). Of course, this$ can be abitrary complex, ranging from - this$0 (the immediate outer context) to - access$0(access$0(...(this$0))). - - maybe_use_access_method returns a non zero value if the + this$0 (the immediate outer context) to + access$0(access$0(...(this$0))). + + maybe_use_access_method returns a nonzero value if the this_arg has to be moved into the (then generated) stub argument list. In the meantime, the selected function might have be replaced by a generated stub. */ @@ -10321,13 +10354,13 @@ patch_method_invocation (patch, primary, where, from_super, /* Merge point of all resolution schemes. If we have nothing, this is an error, already signaled */ - if (!list) + if (!list) PATCH_METHOD_RETURN_ERROR (); /* Check accessibility, position the is_static flag, build and return the call */ if (not_accessible_p (DECL_CONTEXT (current_function_decl), list, - (primary ? TREE_TYPE (TREE_TYPE (primary)) : + (primary ? TREE_TYPE (TREE_TYPE (primary)) : NULL_TREE), from_super) /* Calls to clone() on array types are permitted as a special-case. */ && !is_array_clone_call) @@ -10350,15 +10383,14 @@ patch_method_invocation (patch, primary, where, from_super, } /* Deprecation check: check whether the method being invoked or the - instance-being-created's type are deprecated. */ + instance-being-created's type are deprecated. */ if (TREE_CODE (patch) == NEW_CLASS_EXPR) check_deprecation (wfl, TYPE_NAME (DECL_CONTEXT (list))); - else - check_deprecation (wfl, list); + check_deprecation (wfl, list); /* If invoking a innerclass constructor, there are hidden parameters to pass */ - if (TREE_CODE (patch) == NEW_CLASS_EXPR + if (TREE_CODE (patch) == NEW_CLASS_EXPR && PURE_INNER_CLASS_TYPE_P (DECL_CONTEXT (list))) { /* And make sure we add the accessed local variables to be saved @@ -10401,27 +10433,15 @@ patch_method_invocation (patch, primary, where, from_super, /* This handles the situation where a constructor invocation needs to have an enclosing context passed as a second parameter (the - constructor is one of an inner class. We extract it from the - current function. */ - if ((is_super_init || + constructor is one of an inner class). */ + if ((is_super_init || (TREE_CODE (patch) == CALL_EXPR && name == this_identifier_node)) && PURE_INNER_CLASS_TYPE_P (DECL_CONTEXT (list))) { - tree enclosing_decl = DECL_CONTEXT (TYPE_NAME (current_class)); - tree extra_arg; - - if (ANONYMOUS_CLASS_P (current_class) || !DECL_CONTEXT (enclosing_decl)) - { - extra_arg = DECL_FUNCTION_BODY (current_function_decl); - extra_arg = TREE_CHAIN (BLOCK_EXPR_DECLS (extra_arg)); - } - else - { - tree dest = TREE_TYPE (DECL_CONTEXT (enclosing_decl)); - extra_arg = - build_access_to_thisn (TREE_TYPE (enclosing_decl), dest, 0); - extra_arg = java_complete_tree (extra_arg); - } + tree dest = TYPE_NAME (DECL_CONTEXT (list)); + tree extra_arg = + build_access_to_thisn (current_class, DECL_CONTEXT (dest), 0); + extra_arg = java_complete_tree (extra_arg); args = tree_cons (NULL_TREE, extra_arg, args); } @@ -10433,8 +10453,8 @@ patch_method_invocation (patch, primary, where, from_super, invoke any method relying on `this'. Exceptions are: we're invoking a static function, primary exists and is not the current this, we're creating a new object. */ - if (ctxp->explicit_constructor_p - && !is_static_flag + if (ctxp->explicit_constructor_p + && !is_static_flag && (!primary || primary == current_this) && (TREE_CODE (patch) != NEW_CLASS_EXPR)) { @@ -10442,7 +10462,7 @@ patch_method_invocation (patch, primary, where, from_super, PATCH_METHOD_RETURN_ERROR (); } java_parser_context_restore_global (); - if (is_static) + if (is_static) *is_static = is_static_flag; /* Sometimes, we want the decl of the selected method. Such as for EH checking */ @@ -10454,21 +10474,21 @@ patch_method_invocation (patch, primary, where, from_super, if (is_super_init && CLASS_HAS_FINIT_P (current_class)) { tree finit_parms, finit_call; - + /* Prepare to pass hidden parameters to finit$, if any. */ - finit_parms = build_alias_initializer_parameter_list + finit_parms = build_alias_initializer_parameter_list (AIPL_FUNCTION_FINIT_INVOCATION, current_class, NULL_TREE, NULL); - - finit_call = + + finit_call = build_method_invocation (build_wfl_node (finit_identifier_node), finit_parms); /* Generate the code used to initialize fields declared with an initialization statement and build a compound statement along with the super constructor invocation. */ + CAN_COMPLETE_NORMALLY (patch) = 1; patch = build (COMPOUND_EXPR, void_type_node, patch, java_complete_tree (finit_call)); - CAN_COMPLETE_NORMALLY (patch) = 1; } return patch; } @@ -10477,15 +10497,15 @@ patch_method_invocation (patch, primary, where, from_super, non static method. Return 1 if it's the case, 0 otherwise. */ static int -check_for_static_method_reference (wfl, node, method, where, primary) - tree wfl, node, method, where, primary; +check_for_static_method_reference (tree wfl, tree node, tree method, + tree where, tree primary) { - if (METHOD_STATIC (current_function_decl) + if (METHOD_STATIC (current_function_decl) && !METHOD_STATIC (method) && !primary && !CALL_CONSTRUCTOR_P (node)) { char *fct_name = xstrdup (lang_printable_name (method, 0)); - parse_error_context - (wfl, "Can't make static reference to method `%s %s' in class `%s'", + parse_error_context + (wfl, "Can't make static reference to method `%s %s' in class `%s'", lang_printable_name (TREE_TYPE (TREE_TYPE (method)), 0), fct_name, IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (where)))); free (fct_name); @@ -10500,22 +10520,20 @@ check_for_static_method_reference (wfl, node, method, where, primary) returned. */ static int -maybe_use_access_method (is_super_init, mdecl, this_arg) - int is_super_init; - tree *mdecl, *this_arg; +maybe_use_access_method (int is_super_init, tree *mdecl, tree *this_arg) { tree ctx; tree md = *mdecl, ta = *this_arg; int to_return = 0; int non_static_context = !METHOD_STATIC (md); - if (is_super_init + if (is_super_init || DECL_CONTEXT (md) == current_class - || !PURE_INNER_CLASS_TYPE_P (current_class) + || !PURE_INNER_CLASS_TYPE_P (current_class) || DECL_FINIT_P (md) || DECL_INSTINIT_P (md)) return 0; - + /* If we're calling a method found in an enclosing class, generate what it takes to retrieve the right this. Don't do that if we're invoking a static method. Note that if MD's type is unrelated to @@ -10540,7 +10558,7 @@ maybe_use_access_method (is_super_init, mdecl, this_arg) ta = build_access_to_thisn (ctx, type, 0); break; } - type = (DECL_CONTEXT (TYPE_NAME (type)) ? + type = (DECL_CONTEXT (TYPE_NAME (type)) ? TREE_TYPE (DECL_CONTEXT (TYPE_NAME (type))) : NULL_TREE); } } @@ -10559,7 +10577,7 @@ maybe_use_access_method (is_super_init, mdecl, this_arg) *mdecl = md; *this_arg = ta; - /* Returnin a non zero value indicates we were doing a non static + /* Returnin a nonzero value indicates we were doing a non static method invokation that is now a static invocation. It will have callee displace `this' to insert it in the regular argument list. */ @@ -10570,8 +10588,7 @@ maybe_use_access_method (is_super_init, mdecl, this_arg) mode. */ static tree -patch_invoke (patch, method, args) - tree patch, method, args; +patch_invoke (tree patch, tree method, tree args) { tree dtable, func; tree original_call, t, ta; @@ -10584,7 +10601,7 @@ patch_invoke (patch, method, args) t = TYPE_ARG_TYPES (TREE_TYPE (method)); if (TREE_CODE (patch) == NEW_CLASS_EXPR) t = TREE_CHAIN (t); - for (ta = args; t != end_params_node && ta; + for (ta = args; t != end_params_node && ta; t = TREE_CHAIN (t), ta = TREE_CHAIN (ta)) if (JPRIMITIVE_TYPE_P (TREE_TYPE (TREE_VALUE (ta))) && TREE_TYPE (TREE_VALUE (ta)) != TREE_VALUE (t)) @@ -10599,7 +10616,6 @@ patch_invoke (patch, method, args) func = method; else { - tree signature = build_java_signature (TREE_TYPE (method)); switch (invocation_mode (method, CALL_USING_SUPER (patch))) { case INVOKE_VIRTUAL: @@ -10624,9 +10640,12 @@ patch_invoke (patch, method, args) case INVOKE_SUPER: case INVOKE_STATIC: - func = build_known_method_ref (method, TREE_TYPE (method), - DECL_CONTEXT (method), - signature, args); + { + tree signature = build_java_signature (TREE_TYPE (method)); + func = build_known_method_ref (method, TREE_TYPE (method), + DECL_CONTEXT (method), + signature, args); + } break; case INVOKE_INTERFACE: @@ -10645,6 +10664,7 @@ patch_invoke (patch, method, args) TREE_TYPE (patch) = TREE_TYPE (TREE_TYPE (method)); TREE_OPERAND (patch, 0) = func; TREE_OPERAND (patch, 1) = args; + patch = check_for_builtin (method, patch); original_call = patch; /* We're processing a `new TYPE ()' form. New is called and its @@ -10672,7 +10692,7 @@ patch_invoke (patch, method, args) new = build (CALL_EXPR, promote_type (class), build_address_of (alloc_node), tree_cons (NULL_TREE, build_class_ref (class), - build_tree_list (NULL_TREE, + build_tree_list (NULL_TREE, size_in_bytes (class))), NULL_TREE); saved_new = save_expr (new); @@ -10687,7 +10707,11 @@ patch_invoke (patch, method, args) is NULL. */ if (check != NULL_TREE) { - patch = build (COMPOUND_EXPR, TREE_TYPE (patch), check, patch); + /* We have to call force_evaluation_order now because creating a + COMPOUND_EXPR wraps the arg list in a way that makes it + unrecognizable by force_evaluation_order later. Yuk. */ + patch = build (COMPOUND_EXPR, TREE_TYPE (patch), check, + force_evaluation_order (patch)); TREE_SIDE_EFFECTS (patch) = 1; } @@ -10703,7 +10727,10 @@ patch_invoke (patch, method, args) { tree list; tree fndecl = current_function_decl; - tree save = save_expr (patch); + /* We have to call force_evaluation_order now because creating a + COMPOUND_EXPR wraps the arg list in a way that makes it + unrecognizable by force_evaluation_order later. Yuk. */ + tree save = save_expr (force_evaluation_order (patch)); tree type = TREE_TYPE (patch); patch = build (COMPOUND_EXPR, type, save, empty_stmt_node); @@ -10719,9 +10746,7 @@ patch_invoke (patch, method, args) } static int -invocation_mode (method, super) - tree method; - int super; +invocation_mode (tree method, int super) { int access = get_access_flags_from_decl (method); @@ -10752,10 +10777,7 @@ invocation_mode (method, super) 15.11.2 (Compile-Time Step 2) */ static tree -lookup_method_invoke (lc, cl, class, name, arg_list) - int lc; - tree cl; - tree class, name, arg_list; +lookup_method_invoke (int lc, tree cl, tree class, tree name, tree arg_list) { tree atl = end_params_node; /* Arg Type List */ tree method, signature, list, node; @@ -10780,7 +10802,14 @@ lookup_method_invoke (lc, cl, class, name, arg_list) know the arguments' types. */ if (lc && ANONYMOUS_CLASS_P (class)) - craft_constructor (TYPE_NAME (class), atl); + { + tree saved_current_class; + tree mdecl = craft_constructor (TYPE_NAME (class), atl); + saved_current_class = current_class; + current_class = class; + fix_constructors (mdecl); + current_class = saved_current_class; + } /* Find all candidates and then refine the list, searching for the most specific method. */ @@ -10803,7 +10832,7 @@ lookup_method_invoke (lc, cl, class, name, arg_list) char string [4096]; if (!cm || not_accessible_p (class, cm, NULL_TREE, 0)) continue; - sprintf + sprintf (string, " `%s' in `%s'%s", get_printable_method_name (cm), IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (DECL_CONTEXT (cm)))), @@ -10831,32 +10860,28 @@ lookup_method_invoke (lc, cl, class, name, arg_list) when we're looking for a constructor. */ static tree -find_applicable_accessible_methods_list (lc, class, name, arglist) - int lc; - tree class, name, arglist; +find_applicable_accessible_methods_list (int lc, tree class, tree name, + tree arglist) { - static struct hash_table t, *searched_classes = NULL; + static htab_t searched_classes; static int search_not_done = 0; tree list = NULL_TREE, all_list = NULL_TREE; - /* Check the hash table to determine if this class has been searched + /* Check the hash table to determine if this class has been searched already. */ if (searched_classes) { - if (hash_lookup (searched_classes, - (const hash_table_key) class, FALSE, NULL)) - return NULL; + if (htab_find (searched_classes, class) != NULL) + return NULL; } else { - hash_table_init (&t, hash_newfunc, java_hash_hash_tree_node, - java_hash_compare_tree_node); - searched_classes = &t; + searched_classes = htab_create (10, htab_hash_pointer, + htab_eq_pointer, NULL); } - + search_not_done++; - hash_lookup (searched_classes, - (const hash_table_key) class, TRUE, NULL); + *htab_find_slot (searched_classes, class, INSERT) = class; if (!CLASS_LOADED_P (class) && !CLASS_FROM_SOURCE_P (class)) { @@ -10865,12 +10890,12 @@ find_applicable_accessible_methods_list (lc, class, name, arglist) } /* Search interfaces */ - if (TREE_CODE (TYPE_NAME (class)) == TYPE_DECL + if (TREE_CODE (TYPE_NAME (class)) == TYPE_DECL && CLASS_INTERFACE (TYPE_NAME (class))) { int i, n; tree basetype_vec = TYPE_BINFO_BASETYPES (class); - search_applicable_methods_list (lc, TYPE_METHODS (class), + search_applicable_methods_list (lc, TYPE_METHODS (class), name, arglist, &list, &all_list); n = TREE_VEC_LENGTH (basetype_vec); for (i = 1; i < n; i++) @@ -10878,7 +10903,7 @@ find_applicable_accessible_methods_list (lc, class, name, arglist) tree t = BINFO_TYPE (TREE_VEC_ELT (basetype_vec, i)); tree rlist; - rlist = find_applicable_accessible_methods_list (lc, t, name, + rlist = find_applicable_accessible_methods_list (lc, t, name, arglist); list = chainon (rlist, list); } @@ -10886,7 +10911,7 @@ find_applicable_accessible_methods_list (lc, class, name, arglist) /* Search classes */ else { - search_applicable_methods_list (lc, TYPE_METHODS (class), + search_applicable_methods_list (lc, TYPE_METHODS (class), name, arglist, &list, &all_list); /* When looking finit$, class$ or instinit$, we turn LC to 1 so @@ -10922,7 +10947,7 @@ find_applicable_accessible_methods_list (lc, class, name, arglist) { tree rlist; class = CLASSTYPE_SUPER (class); - rlist = find_applicable_accessible_methods_list (lc, class, + rlist = find_applicable_accessible_methods_list (lc, class, name, arglist); list = chainon (rlist, list); } @@ -10936,15 +10961,13 @@ find_applicable_accessible_methods_list (lc, class, name, arglist) { if (!lc && TYPE_METHODS (object_type_node) - && !hash_lookup (searched_classes, - (const hash_table_key) object_type_node, - FALSE, NULL)) + && htab_find (searched_classes, object_type_node) == NULL) { - search_applicable_methods_list (lc, + search_applicable_methods_list (lc, TYPE_METHODS (object_type_node), name, arglist, &list, &all_list); } - hash_table_free (searched_classes); + htab_delete (searched_classes); searched_classes = NULL; } @@ -10955,11 +10978,9 @@ find_applicable_accessible_methods_list (lc, class, name, arglist) /* Effectively search for the appropriate method in method */ -static void -search_applicable_methods_list (lc, method, name, arglist, list, all_list) - int lc; - tree method, name, arglist; - tree *list, *all_list; +static void +search_applicable_methods_list (int lc, tree method, tree name, tree arglist, + tree *list, tree *all_list) { for (; method; method = TREE_CHAIN (method)) { @@ -10967,14 +10988,14 @@ search_applicable_methods_list (lc, method, name, arglist, list, all_list) other classes */ if (lc && !DECL_CONSTRUCTOR_P (method)) continue; - else if (!lc && (DECL_CONSTRUCTOR_P (method) + else if (!lc && (DECL_CONSTRUCTOR_P (method) || (DECL_NAME (method) != name))) continue; if (argument_types_convertible (method, arglist)) { /* Retain accessible methods only */ - if (!not_accessible_p (DECL_CONTEXT (current_function_decl), + if (!not_accessible_p (DECL_CONTEXT (current_function_decl), method, NULL_TREE, 0)) *list = tree_cons (NULL_TREE, method, *list); else @@ -10987,8 +11008,7 @@ search_applicable_methods_list (lc, method, name, arglist, list, all_list) /* 15.11.2.2 Choose the Most Specific Method */ static tree -find_most_specific_methods_list (list) - tree list; +find_most_specific_methods_list (tree list) { int max = 0; int abstract, candidates; @@ -11011,13 +11031,13 @@ find_most_specific_methods_list (list) /* Compare arguments and location where methods where declared */ if (argument_types_convertible (method_v, current_v)) { - if (valid_method_invocation_conversion_p + if (valid_method_invocation_conversion_p (DECL_CONTEXT (method_v), DECL_CONTEXT (current_v)) || (INNER_CLASS_TYPE_P (DECL_CONTEXT (current_v)) && enclosing_context_p (DECL_CONTEXT (method_v), DECL_CONTEXT (current_v)))) { - int v = (DECL_SPECIFIC_COUNT (current_v) += + int v = (DECL_SPECIFIC_COUNT (current_v) += (INNER_CLASS_TYPE_P (DECL_CONTEXT (current_v)) ? 2 : 1)); max = (v > max ? v : max); } @@ -11074,25 +11094,14 @@ find_most_specific_methods_list (list) corresponding parameter of M1. Implementation expects M2_OR_ARGLIST to change less often than M1. */ +static GTY(()) tree m2_arg_value; +static GTY(()) tree m2_arg_cache; + static int -argument_types_convertible (m1, m2_or_arglist) - tree m1, m2_or_arglist; +argument_types_convertible (tree m1, tree m2_or_arglist) { - static tree m2_arg_value = NULL_TREE; - static tree m2_arg_cache = NULL_TREE; - static int initialized_p; - register tree m1_arg, m2_arg; - /* Register M2_ARG_VALUE and M2_ARG_CACHE with the garbage - collector. */ - if (!initialized_p) - { - ggc_add_tree_root (&m2_arg_value, 1); - ggc_add_tree_root (&m2_arg_cache, 1); - initialized_p = 1; - } - SKIP_THIS_AND_ARTIFICIAL_PARMS (m1_arg, m1) if (m2_arg_value == m2_or_arglist) @@ -11129,8 +11138,7 @@ argument_types_convertible (m1, m2_or_arglist) /* Qualification routines */ static void -qualify_ambiguous_name (id) - tree id; +qualify_ambiguous_name (tree id) { tree qual, qual_wfl, name = NULL_TREE, decl, ptr_type = NULL_TREE, saved_current_class; @@ -11157,7 +11165,9 @@ qualify_ambiguous_name (id) { case CALL_EXPR: qual_wfl = TREE_OPERAND (qual_wfl, 0); - if (TREE_CODE (qual_wfl) != EXPR_WITH_FILE_LOCATION) + if (TREE_CODE (qual_wfl) != EXPR_WITH_FILE_LOCATION + || (EXPR_WFL_QUALIFICATION (qual_wfl) + && TREE_CODE (EXPR_WFL_QUALIFICATION (qual_wfl)) == TREE_LIST)) { qual = EXPR_WFL_QUALIFICATION (qual_wfl); qual_wfl = QUAL_WFL (qual); @@ -11201,11 +11211,17 @@ qualify_ambiguous_name (id) else if (code == INTEGER_CST) name = qual_wfl; - + else if (code == CONVERT_EXPR && TREE_CODE (TREE_OPERAND (qual_wfl, 0)) == EXPR_WITH_FILE_LOCATION) name = TREE_OPERAND (qual_wfl, 0); - + + else if (code == CONVERT_EXPR + && TREE_CODE (TREE_OPERAND (qual_wfl, 0)) == CALL_EXPR + && (TREE_CODE (TREE_OPERAND (TREE_OPERAND (qual_wfl, 0), 0)) + == EXPR_WITH_FILE_LOCATION)) + name = TREE_OPERAND (TREE_OPERAND (qual_wfl, 0), 0); + else if ((code == ARRAY_REF || code == CALL_EXPR || code == MODIFY_EXPR) && TREE_CODE (TREE_OPERAND (qual_wfl, 0)) == EXPR_WITH_FILE_LOCATION) name = EXPR_WFL_NODE (TREE_OPERAND (qual_wfl, 0)); @@ -11213,7 +11229,7 @@ qualify_ambiguous_name (id) else if (code == TREE_LIST) name = EXPR_WFL_NODE (TREE_PURPOSE (qual_wfl)); - else if (code == STRING_CST || code == CONDITIONAL_EXPR + else if (code == STRING_CST || code == CONDITIONAL_EXPR || code == PLUS_EXPR) { qual = TREE_CHAIN (qual); @@ -11238,7 +11254,7 @@ qualify_ambiguous_name (id) if (TREE_CODE (TREE_PURPOSE (qual)) == ARRAY_REF && TREE_CODE (TREE_OPERAND (TREE_PURPOSE (qual), 0)) == EXPR_WITH_FILE_LOCATION - && EXPR_WFL_NODE (TREE_OPERAND (TREE_PURPOSE (qual), 0)) == + && EXPR_WFL_NODE (TREE_OPERAND (TREE_PURPOSE (qual), 0)) == this_identifier_node) { qual = TREE_OPERAND (TREE_PURPOSE (qual), 0); @@ -11271,12 +11287,12 @@ qualify_ambiguous_name (id) super_found = again = 1; } } while (again); - + /* If name appears within the scope of a local variable declaration or parameter declaration, then it is an expression name. We don't carry this test out if we're in the context of the use of SUPER or THIS */ - if (!this_found && !super_found + if (!this_found && !super_found && TREE_CODE (name) != STRING_CST && TREE_CODE (name) != INTEGER_CST && (decl = IDENTIFIER_LOCAL_VALUE (name))) { @@ -11302,7 +11318,7 @@ qualify_ambiguous_name (id) - NAME is declared in an another compilation unit of the package of the compilation unit containing NAME, - NAME is declared by exactly on type-import-on-demand declaration - of the compilation unit containing NAME. + of the compilation unit containing NAME. - NAME is actually a STRING_CST. This can't happen if the expression was qualified by `this.' */ else if (! this_found && @@ -11326,7 +11342,7 @@ qualify_ambiguous_name (id) containing NAME. FIXME */ /* Otherwise, NAME is reclassified as a package name */ - else + else RESOLVE_PACKAGE_NAME_P (qual_wfl) = 1; /* Propagate the qualification accross other components of the @@ -11336,7 +11352,7 @@ qualify_ambiguous_name (id) { if (RESOLVE_PACKAGE_NAME_P (qual_wfl)) RESOLVE_PACKAGE_NAME_P (QUAL_WFL (qual)) = 1; - else + else RESOLVE_EXPRESSION_NAME_P (QUAL_WFL (qual)) = 1; } @@ -11354,21 +11370,20 @@ qualify_ambiguous_name (id) } static int -breakdown_qualified (left, right, source) - tree *left, *right, source; +breakdown_qualified (tree *left, tree *right, tree source) { char *p, *base; - int l = IDENTIFIER_LENGTH (source); + int l = IDENTIFIER_LENGTH (source); base = alloca (l + 1); memcpy (base, IDENTIFIER_POINTER (source), l + 1); - /* Breakdown NAME into REMAINDER . IDENTIFIER */ + /* Breakdown NAME into REMAINDER . IDENTIFIER. */ p = base + l - 1; while (*p != '.' && p != base) p--; - /* We didn't find a '.'. Return an error */ + /* We didn't find a '.'. Return an error. */ if (p == base) return 1; @@ -11376,20 +11391,19 @@ breakdown_qualified (left, right, source) if (right) *right = get_identifier (p+1); *left = get_identifier (base); - + return 0; } /* Return TRUE if two classes are from the same package. */ static int -in_same_package (name1, name2) - tree name1, name2; +in_same_package (tree name1, tree name2) { tree tmp; tree pkg1; tree pkg2; - + if (TREE_CODE (name1) == TYPE_DECL) name1 = DECL_NAME (name1); if (TREE_CODE (name2) == TYPE_DECL) @@ -11405,7 +11419,7 @@ in_same_package (name1, name2) breakdown_qualified (&pkg1, &tmp, name1); breakdown_qualified (&pkg2, &tmp, name2); - + return (pkg1 == pkg2); } @@ -11414,37 +11428,22 @@ in_same_package (name1, name2) Same as java_complete_lhs, but does resolve static finals to values. */ static tree -java_complete_tree (node) - tree node; +java_complete_tree (tree node) { node = java_complete_lhs (node); if (JDECL_P (node) && CLASS_FINAL_VARIABLE_P (node) && DECL_INITIAL (node) != NULL_TREE && !flag_emit_xref) { - tree value = DECL_INITIAL (node); - DECL_INITIAL (node) = NULL_TREE; - value = fold_constant_for_init (value, node); - DECL_INITIAL (node) = value; + tree value = fold_constant_for_init (node, node); if (value != NULL_TREE) - { - /* fold_constant_for_init sometimes widens the original type - of the constant (i.e. byte to int). It's not desirable, - especially if NODE is a function argument. */ - if ((TREE_CODE (value) == INTEGER_CST - || TREE_CODE (value) == REAL_CST) - && TREE_TYPE (node) != TREE_TYPE (value)) - return convert (TREE_TYPE (node), value); - else - return value; - } + return value; } return node; } static tree -java_stabilize_reference (node) - tree node; +java_stabilize_reference (tree node) { if (TREE_CODE (node) == COMPOUND_EXPR) { @@ -11462,8 +11461,7 @@ java_stabilize_reference (node) Same as java_complete_tree, but does not resolve static finals to values. */ static tree -java_complete_lhs (node) - tree node; +java_complete_lhs (tree node) { tree nn, cn, wfl_op1, wfl_op2, wfl_op3; int flag; @@ -11498,7 +11496,7 @@ java_complete_lhs (node) int error_seen = 0; if (TREE_CODE (stmt) == COMPOUND_EXPR) { - /* Re-order from (((A; B); C); ...; Z) to + /* Re-order from (((A; B); C); ...; Z) to (A; (B; (C ; (...; Z)))). This makes it easier to scan the statements left-to-right without using recursion (which might overflow the stack @@ -11644,11 +11642,11 @@ java_complete_lhs (node) nn = ctxp->current_loop; /* It must be assignable to the type of the switch expression. */ - if (!try_builtin_assignconv (NULL_TREE, + if (!try_builtin_assignconv (NULL_TREE, TREE_TYPE (TREE_OPERAND (nn, 0)), cn)) { EXPR_WFL_LINECOL (wfl_operator) = EXPR_WFL_LINECOL (node); - parse_error_context + parse_error_context (wfl_operator, "Incompatible type for case. Can't convert `%s' to `int'", lang_printable_name (TREE_TYPE (cn), 0)); @@ -11679,7 +11677,7 @@ java_complete_lhs (node) if (SWITCH_HAS_DEFAULT (nn)) { EXPR_WFL_LINECOL (wfl_operator) = EXPR_WFL_LINECOL (node); - parse_error_context (wfl_operator, + parse_error_context (wfl_operator, "Duplicate case label: `default'"); return error_mark_node; } @@ -11754,7 +11752,7 @@ java_complete_lhs (node) /* 3- Expression section */ case COMPOUND_EXPR: wfl_op2 = TREE_OPERAND (node, 1); - TREE_OPERAND (node, 0) = nn = + TREE_OPERAND (node, 0) = nn = java_complete_tree (TREE_OPERAND (node, 0)); if (wfl_op2 == empty_stmt_node) CAN_COMPLETE_NORMALLY (node) = CAN_COMPLETE_NORMALLY (nn); @@ -11767,10 +11765,22 @@ java_complete_lhs (node) nn = wfl_op2; if (TREE_CODE (nn) == EXPR_WITH_FILE_LOCATION) nn = EXPR_WFL_NODE (nn); - if (TREE_CODE (nn) != EXIT_EXPR) + /* NN can be NULL_TREE exactly when UPDATE is, in + finish_for_loop. */ + if (nn != NULL_TREE && TREE_CODE (nn) != EXIT_EXPR) { SET_WFL_OPERATOR (wfl_operator, node, wfl_op2); - parse_error_context (wfl_operator, "Unreachable statement"); + if (SUPPRESS_UNREACHABLE_ERROR (nn)) + { + /* Perhaps this warning should have an + associated flag. The code being compiled is + pedantically correct, but useless. */ + parse_warning_context (wfl_operator, + "Unreachable statement"); + } + else + parse_error_context (wfl_operator, + "Unreachable statement"); } } TREE_OPERAND (node, 1) = java_complete_tree (TREE_OPERAND (node, 1)); @@ -11810,10 +11820,10 @@ java_complete_lhs (node) else { tree body; - int save_lineno = lineno; - lineno = EXPR_WFL_LINENO (node); + int save_lineno = input_line; + input_line = EXPR_WFL_LINENO (node); body = java_complete_tree (EXPR_WFL_NODE (node)); - lineno = save_lineno; + input_line = save_lineno; EXPR_WFL_NODE (node) = body; TREE_SIDE_EFFECTS (node) = TREE_SIDE_EFFECTS (body); CAN_COMPLETE_NORMALLY (node) = CAN_COMPLETE_NORMALLY (body); @@ -11831,7 +11841,7 @@ java_complete_lhs (node) } else TREE_TYPE (node) = TREE_TYPE (EXPR_WFL_NODE (node)); - + } break; @@ -11841,7 +11851,7 @@ java_complete_lhs (node) for (cn = TREE_OPERAND (node, 1); cn; cn = TREE_CHAIN (cn)) { int location = EXPR_WFL_LINECOL (TREE_VALUE (cn)); - tree dim = convert (int_type_node, + tree dim = convert (int_type_node, java_complete_tree (TREE_VALUE (cn))); if (dim == error_mark_node) { @@ -11853,7 +11863,7 @@ java_complete_lhs (node) TREE_VALUE (cn) = dim; /* Setup the location of the current dimension, for later error report. */ - TREE_PURPOSE (cn) = + TREE_PURPOSE (cn) = build_expr_wfl (NULL_TREE, input_filename, 0, 0); EXPR_WFL_LINECOL (TREE_PURPOSE (cn)) = location; } @@ -11902,8 +11912,8 @@ java_complete_lhs (node) check_thrown_exceptions (EXPR_WFL_LINECOL (node), decl); /* If we call this(...), register signature and positions */ if (in_this) - DECL_CONSTRUCTOR_CALLS (current_function_decl) = - tree_cons (wfl, decl, + DECL_CONSTRUCTOR_CALLS (current_function_decl) = + tree_cons (wfl, decl, DECL_CONSTRUCTOR_CALLS (current_function_decl)); CAN_COMPLETE_NORMALLY (node) = 1; return force_evaluation_order (node); @@ -11913,20 +11923,20 @@ java_complete_lhs (node) /* 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; - + value = fold_constant_for_init (nn, nn); /* When we have a primitype type, or a string and we're not emitting a class file, we actually don't want to generate anything for the assignment. */ if (value != NULL_TREE && - (JPRIMITIVE_TYPE_P (TREE_TYPE (value)) || + (JPRIMITIVE_TYPE_P (TREE_TYPE (value)) || (TREE_TYPE (value) == string_ptr_type_node && ! flag_emit_class_files))) { @@ -11962,11 +11972,11 @@ java_complete_lhs (node) { /* This might break when accessing outer field from inner class. TESTME, FIXME */ - tree lvalue = java_stabilize_reference (TREE_OPERAND (node, 0)); + tree lvalue = java_stabilize_reference (TREE_OPERAND (node, 0)); /* Hand stabilize the lhs on both places */ TREE_OPERAND (node, 0) = lvalue; - TREE_OPERAND (TREE_OPERAND (node, 1), 0) = + TREE_OPERAND (TREE_OPERAND (node, 1), 0) = (flag_emit_class_files ? lvalue : save_expr (lvalue)); /* 15.25.2.a: Left hand is not an array access. FIXME */ @@ -11976,9 +11986,9 @@ java_complete_lhs (node) if ((cn = patch_string (nn))) nn = cn; - /* The last part of the rewrite for E1 op= E2 is to have + /* The last part of the rewrite for E1 op= E2 is to have E1 = (T)(E1 op E2), with T being the type of E1. */ - nn = java_complete_tree (build_cast (EXPR_WFL_LINECOL (wfl_op2), + nn = java_complete_tree (build_cast (EXPR_WFL_LINECOL (wfl_op2), TREE_TYPE (lvalue), nn)); /* If the assignment is compound and has reference type, @@ -12029,8 +12039,10 @@ java_complete_lhs (node) else { node = patch_assignment (node, wfl_op1); + if (node == error_mark_node) + return error_mark_node; /* Reorganize the tree if necessary. */ - if (flag && (!JREFERENCE_TYPE_P (TREE_TYPE (node)) + if (flag && (!JREFERENCE_TYPE_P (TREE_TYPE (node)) || JSTRING_P (TREE_TYPE (node)))) node = java_refold (node); } @@ -12039,9 +12051,9 @@ java_complete_lhs (node) undergone a conversion in patch_assignment. We do that only when it's necessary to have DECL_INITIAL properly set. */ nn = TREE_OPERAND (node, 0); - if (TREE_CODE (nn) == VAR_DECL + if (TREE_CODE (nn) == VAR_DECL && DECL_INITIAL (nn) && CONSTANT_VALUE_P (DECL_INITIAL (nn)) - && FIELD_STATIC (nn) && FIELD_FINAL (nn) + && FIELD_STATIC (nn) && FIELD_FINAL (nn) && (JPRIMITIVE_TYPE_P (TREE_TYPE (nn)) || TREE_TYPE (nn) == string_ptr_type_node)) DECL_INITIAL (nn) = TREE_OPERAND (node, 1); @@ -12063,7 +12075,7 @@ java_complete_lhs (node) case RDIV_EXPR: case TRUTH_ANDIF_EXPR: case TRUTH_ORIF_EXPR: - case EQ_EXPR: + case EQ_EXPR: case NE_EXPR: case GT_EXPR: case GE_EXPR: @@ -12182,13 +12194,13 @@ java_complete_lhs (node) if (ctxp->explicit_constructor_p) { EXPR_WFL_LINECOL (wfl_operator) = EXPR_WFL_LINECOL (node); - parse_error_context + parse_error_context (wfl_operator, "Can't reference `this' or `super' before the superclass constructor has been called"); TREE_TYPE (node) = error_mark_node; return error_mark_node; } return current_this; - + case CLASS_LITERAL: CAN_COMPLETE_NORMALLY (node) = 1; node = patch_incomplete_class_ref (node); @@ -12208,12 +12220,11 @@ java_complete_lhs (node) return node; } -/* Complete function call's argument. Return a non zero value is an +/* Complete function call's argument. Return a nonzero value is an error was found. */ static int -complete_function_arguments (node) - tree node; +complete_function_arguments (tree node) { int flag = 0; tree cn; @@ -12246,9 +12257,7 @@ complete_function_arguments (node) debugable. */ static tree -build_debugable_stmt (location, stmt) - int location; - tree stmt; +build_debugable_stmt (int location, tree stmt) { if (TREE_CODE (stmt) != EXPR_WITH_FILE_LOCATION) { @@ -12260,8 +12269,8 @@ build_debugable_stmt (location, stmt) } static tree -build_expr_block (body, decls) - tree body, decls; +build_expr_block (tree body, tree decls) + { tree node = make_node (BLOCK); BLOCK_EXPR_DECLS (node) = decls; @@ -12276,7 +12285,7 @@ build_expr_block (body, decls) function block chain */ static tree -enter_block () +enter_block (void) { tree b = build_expr_block (NULL_TREE, NULL_TREE); @@ -12285,7 +12294,7 @@ enter_block () for the first time for a given function. The current function body (DECL_FUNCTION_BODY) is set to be block B. */ - tree fndecl = current_function_decl; + tree fndecl = current_function_decl; if (!fndecl) { BLOCK_SUPERCONTEXT (b) = current_static_block; @@ -12310,7 +12319,7 @@ enter_block () the block being exited isn't the method's top level one. */ static tree -exit_block () +exit_block (void) { tree b; if (current_function_decl) @@ -12334,8 +12343,7 @@ exit_block () scoping rules. */ static tree -lookup_name_in_blocks (name) - tree name; +lookup_name_in_blocks (tree name) { tree b = GET_CURRENT_BLOCK (current_function_decl); @@ -12347,7 +12355,7 @@ lookup_name_in_blocks (name) if (TREE_CODE (b) != BLOCK) abort (); - for (current = BLOCK_EXPR_DECLS (b); current; + for (current = BLOCK_EXPR_DECLS (b); current; current = TREE_CHAIN (current)) if (DECL_NAME (current) == name) return current; @@ -12357,13 +12365,13 @@ lookup_name_in_blocks (name) } static void -maybe_absorb_scoping_blocks () +maybe_absorb_scoping_blocks (void) { while (BLOCK_IS_IMPLICIT (GET_CURRENT_BLOCK (current_function_decl))) { tree b = exit_block (); java_method_add_stmt (current_function_decl, b); - SOURCE_FRONTEND_DEBUG (("Absorbing scoping block at line %d", lineno)); + SOURCE_FRONTEND_DEBUG (("Absorbing scoping block at line %d", input_line)); } } @@ -12375,12 +12383,10 @@ maybe_absorb_scoping_blocks () /* Wrap a non WFL node around a WFL. */ static tree -build_wfl_wrap (node, location) - tree node; - int location; +build_wfl_wrap (tree node, int location) { tree wfl, node_to_insert = node; - + /* We want to process THIS . xxx symbolicaly, to keep it consistent with the way we're processing SUPER. A THIS from a primary as a different form than a SUPER. Turn THIS into something symbolic */ @@ -12398,8 +12404,7 @@ build_wfl_wrap (node, location) we're currently dealing with the class java.lang.Object. */ static tree -build_super_invocation (mdecl) - tree mdecl; +build_super_invocation (tree mdecl) { if (DECL_CONTEXT (mdecl) == object_type_node) return empty_stmt_node; @@ -12422,13 +12427,11 @@ build_super_invocation (mdecl) /* Build a SUPER/THIS qualified method invocation. */ static tree -build_this_super_qualified_invocation (use_this, name, args, lloc, rloc) - int use_this; - tree name, args; - int lloc, rloc; +build_this_super_qualified_invocation (int use_this, tree name, tree args, + int lloc, int rloc) { tree invok; - tree wfl = + tree wfl = build_wfl_node (use_this ? this_identifier_node : super_identifier_node); EXPR_WFL_LINECOL (wfl) = lloc; invok = build_method_invocation (name, args); @@ -12438,9 +12441,7 @@ build_this_super_qualified_invocation (use_this, name, args, lloc, rloc) /* Build an incomplete CALL_EXPR node. */ static tree -build_method_invocation (name, args) - tree name; - tree args; +build_method_invocation (tree name, tree args) { tree call = build (CALL_EXPR, NULL_TREE, name, args, NULL_TREE); TREE_SIDE_EFFECTS (call) = 1; @@ -12451,8 +12452,7 @@ build_method_invocation (name, args) /* Build an incomplete new xxx(...) node. */ static tree -build_new_invocation (name, args) - tree name, args; +build_new_invocation (tree name, tree args) { tree call = build (NEW_CLASS_EXPR, NULL_TREE, name, args, NULL_TREE); TREE_SIDE_EFFECTS (call) = 1; @@ -12463,9 +12463,7 @@ build_new_invocation (name, args) /* Build an incomplete assignment expression. */ static tree -build_assignment (op, op_location, lhs, rhs) - int op, op_location; - tree lhs, rhs; +build_assignment (int op, int op_location, tree lhs, tree rhs) { tree assignment; /* Build the corresponding binop if we deal with a Compound @@ -12482,26 +12480,97 @@ build_assignment (op, op_location, lhs, rhs) return assignment; } -/* Print an INTEGER_CST node in a static buffer, and return the buffer. */ +/* Print an INTEGER_CST node as decimal in a static buffer, and return + the buffer. This is used only for string conversion. */ +static char * +string_convert_int_cst (tree node) +{ + /* Long.MIN_VALUE is -9223372036854775808, 20 characters. */ + static char buffer[21]; + + unsigned HOST_WIDE_INT lo = TREE_INT_CST_LOW (node); + unsigned HOST_WIDE_INT hi = TREE_INT_CST_HIGH (node); + char *p = buffer + sizeof (buffer); + int neg = 0; + + unsigned HOST_WIDE_INT hibit = (((unsigned HOST_WIDE_INT) 1) + << (HOST_BITS_PER_WIDE_INT - 1)); + + *--p = '\0'; + + /* If negative, note the fact and negate the value. */ + if ((hi & hibit)) + { + lo = ~lo; + hi = ~hi; + if (++lo == 0) + ++hi; + neg = 1; + } + + /* Divide by 10 until there are no bits left. */ + do + { + unsigned HOST_WIDE_INT acc = 0; + unsigned HOST_WIDE_INT outhi = 0, outlo = 0; + unsigned int i; + + /* Use long division to compute the result and the remainder. */ + for (i = 0; i < 2 * HOST_BITS_PER_WIDE_INT; ++i) + { + /* Shift a bit into accumulator. */ + acc <<= 1; + if ((hi & hibit)) + acc |= 1; + + /* Shift the value. */ + hi <<= 1; + if ((lo & hibit)) + hi |= 1; + lo <<= 1; + + /* Shift the correct bit into the result. */ + outhi <<= 1; + if ((outlo & hibit)) + outhi |= 1; + outlo <<= 1; + if (acc >= 10) + { + acc -= 10; + outlo |= 1; + } + } + + /* '0' == 060 in Java, but might not be here (think EBCDIC). */ + *--p = '\060' + acc; + + hi = outhi; + lo = outlo; + } + while (hi || lo); + + if (neg) + *--p = '\055'; /* '-' == 055 in Java, but might not be here. */ + return p; +} + +/* Print an INTEGER_CST node in a static buffer, and return the + buffer. This is used only for error handling. */ char * -print_int_node (node) - tree node; +print_int_node (tree node) { static char buffer [80]; if (TREE_CONSTANT_OVERFLOW (node)) sprintf (buffer, ""); - + if (TREE_INT_CST_HIGH (node) == 0) sprintf (buffer, HOST_WIDE_INT_PRINT_UNSIGNED, TREE_INT_CST_LOW (node)); else if (TREE_INT_CST_HIGH (node) == -1 && TREE_INT_CST_LOW (node) != 0) - { - buffer [0] = '-'; - sprintf (&buffer [1], HOST_WIDE_INT_PRINT_UNSIGNED, - -TREE_INT_CST_LOW (node)); - } + sprintf (buffer, "-" HOST_WIDE_INT_PRINT_UNSIGNED, + -TREE_INT_CST_LOW (node)); else sprintf (buffer, HOST_WIDE_INT_PRINT_DOUBLE_HEX, TREE_INT_CST_HIGH (node), TREE_INT_CST_LOW (node)); @@ -12516,9 +12585,7 @@ print_int_node (node) /* 15.25 Assignment operators. */ static tree -patch_assignment (node, wfl_op1) - tree node; - tree wfl_op1; +patch_assignment (tree node, tree wfl_op1) { tree rhs = TREE_OPERAND (node, 1); tree lvalue = TREE_OPERAND (node, 0), llvalue; @@ -12534,9 +12601,8 @@ patch_assignment (node, wfl_op1) { lhs_type = TREE_TYPE (lvalue); } - /* Or Lhs can be a array access. Should that be lvalue ? FIXME + - comment on reason why */ - else if (TREE_CODE (wfl_op1) == ARRAY_REF) + /* Or Lhs can be an array access. */ + else if (TREE_CODE (lvalue) == ARRAY_REF) { lhs_type = TREE_TYPE (lvalue); lvalue_from_array = 1; @@ -12562,7 +12628,7 @@ patch_assignment (node, wfl_op1) { lhs_type = TREE_TYPE (lvalue); } - else + else { parse_error_context (wfl_op1, "Invalid left hand side of assignment"); error_found = 1; @@ -12635,88 +12701,40 @@ patch_assignment (node, wfl_op1) /* 10.10: Array Store Exception runtime check */ if (!flag_emit_class_files && !flag_emit_xref - && lvalue_from_array + && lvalue_from_array && JREFERENCE_TYPE_P (TYPE_ARRAY_ELEMENT (lhs_type))) { - tree check; - tree base = lvalue; + tree array, store_check, base, index_expr; - /* We need to retrieve the right argument for - _Jv_CheckArrayStore. This is somewhat complicated by bounds - and null pointer checks, both of which wrap the operand in - one layer of COMPOUND_EXPR. */ - if (TREE_CODE (lvalue) == COMPOUND_EXPR) - base = TREE_OPERAND (lvalue, 0); - else - { - tree op = TREE_OPERAND (base, 0); - - /* We can have a SAVE_EXPR here when doing String +=. */ - if (TREE_CODE (op) == SAVE_EXPR) - op = TREE_OPERAND (op, 0); - /* We can have a COMPOUND_EXPR here when doing bounds check. */ - if (TREE_CODE (op) == COMPOUND_EXPR) - op = TREE_OPERAND (op, 1); - base = TREE_OPERAND (op, 0); - /* Strip the last PLUS_EXPR to obtain the base. */ - if (TREE_CODE (base) == PLUS_EXPR) - base = TREE_OPERAND (base, 0); - } - - /* Build the invocation of _Jv_CheckArrayStore */ + /* Save RHS so that it doesn't get re-evaluated by the store check. */ new_rhs = save_expr (new_rhs); - check = build (CALL_EXPR, void_type_node, - build_address_of (soft_checkarraystore_node), - tree_cons (NULL_TREE, base, - build_tree_list (NULL_TREE, new_rhs)), - NULL_TREE); - TREE_SIDE_EFFECTS (check) = 1; - - /* We have to decide on an insertion point */ - if (TREE_CODE (lvalue) == COMPOUND_EXPR) - { - tree t; - if (flag_bounds_check) - { - t = TREE_OPERAND (TREE_OPERAND (TREE_OPERAND (lvalue, 1), 0), 0); - TREE_OPERAND (TREE_OPERAND (TREE_OPERAND (lvalue, 1), 0), 0) = - build (COMPOUND_EXPR, void_type_node, t, check); - } - else - TREE_OPERAND (lvalue, 1) = build (COMPOUND_EXPR, lhs_type, - check, TREE_OPERAND (lvalue, 1)); - } - else if (flag_bounds_check) - { - tree hook = lvalue; - tree compound = TREE_OPERAND (lvalue, 0); - tree bound_check, new_compound; - - if (TREE_CODE (compound) == SAVE_EXPR) - { - compound = TREE_OPERAND (compound, 0); - hook = TREE_OPERAND (hook, 0); - } - /* Find the array bound check, hook the original array access. */ - bound_check = TREE_OPERAND (compound, 0); - TREE_OPERAND (hook, 0) = TREE_OPERAND (compound, 1); + /* Get the INDIRECT_REF. */ + array = TREE_OPERAND (TREE_OPERAND (lvalue, 0), 0); + /* Get the array pointer expr. */ + array = TREE_OPERAND (array, 0); + store_check = build_java_arraystore_check (array, new_rhs); - /* Make sure the bound check will happen before the store check */ - new_compound = - build (COMPOUND_EXPR, void_type_node, bound_check, check); + index_expr = TREE_OPERAND (lvalue, 1); - /* Re-assemble the augmented array access. */ - lvalue = build (COMPOUND_EXPR, TREE_TYPE (lvalue), - new_compound, lvalue); - } + if (TREE_CODE (index_expr) == COMPOUND_EXPR) + { + /* A COMPOUND_EXPR here is a bounds check. The bounds check must + happen before the store check, so prepare to insert the store + check within the second operand of the existing COMPOUND_EXPR. */ + base = index_expr; + } else - lvalue = build (COMPOUND_EXPR, TREE_TYPE (lvalue), check, lvalue); + base = lvalue; + + index_expr = TREE_OPERAND (base, 1); + TREE_OPERAND (base, 1) = build (COMPOUND_EXPR, TREE_TYPE (index_expr), + store_check, index_expr); } /* Final locals can be used as case values in switch statement. Prepare them for this eventuality. */ - if (TREE_CODE (lvalue) == VAR_DECL + if (TREE_CODE (lvalue) == VAR_DECL && DECL_FINAL (lvalue) && TREE_CONSTANT (new_rhs) && IDENTIFIER_LOCAL_VALUE (DECL_NAME (lvalue)) @@ -12727,6 +12745,43 @@ patch_assignment (node, wfl_op1) DECL_INITIAL (lvalue) = new_rhs; } + /* Copy the rhs if it's a reference. */ + if (! flag_check_references && ! flag_emit_class_files && optimize > 0) + { + switch (TREE_CODE (new_rhs)) + { + case ARRAY_REF: + case INDIRECT_REF: + case COMPONENT_REF: + /* Transform a = foo.bar + into a = { int tmp; tmp = foo.bar; tmp; ). + We need to ensure that if a read from memory fails + because of a NullPointerException, a destination variable + will remain unchanged. An explicit temporary does what + we need. + + If flag_check_references is set, this is unnecessary + because we'll check each reference before doing any + reads. If optimize is not set the result will never be + written to a stack slot that contains the LHS. */ + { + tree tmp = build_decl (VAR_DECL, get_identifier (""), + TREE_TYPE (new_rhs)); + tree block = build (BLOCK, TREE_TYPE (new_rhs), NULL); + tree assignment + = build (MODIFY_EXPR, TREE_TYPE (new_rhs), tmp, fold (new_rhs)); + BLOCK_VARS (block) = tmp; + BLOCK_EXPR_BODY (block) + = build (COMPOUND_EXPR, TREE_TYPE (new_rhs), assignment, tmp); + TREE_SIDE_EFFECTS (block) = 1; + new_rhs = block; + } + break; + default: + break; + } + } + TREE_OPERAND (node, 0) = lvalue; TREE_OPERAND (node, 1) = new_rhs; TREE_TYPE (node) = lhs_type; @@ -12738,8 +12793,7 @@ patch_assignment (node, wfl_op1) modified rhs. */ static tree -try_reference_assignconv (lhs_type, rhs) - tree lhs_type, rhs; +try_reference_assignconv (tree lhs_type, tree rhs) { tree new_rhs = NULL_TREE; tree rhs_type = TREE_TYPE (rhs); @@ -12765,8 +12819,7 @@ try_reference_assignconv (lhs_type, rhs) builtin type. Return a converted RHS if the conversion is possible. */ static tree -try_builtin_assignconv (wfl_op1, lhs_type, rhs) - tree wfl_op1, lhs_type, rhs; +try_builtin_assignconv (tree wfl_op1, tree lhs_type, tree rhs) { tree new_rhs = NULL_TREE; tree rhs_type = TREE_TYPE (rhs); @@ -12780,31 +12833,28 @@ try_builtin_assignconv (wfl_op1, lhs_type, rhs) new_rhs = rhs; } - /* Zero accepted everywhere */ - else if (TREE_CODE (rhs) == INTEGER_CST - && TREE_INT_CST_HIGH (rhs) == 0 && TREE_INT_CST_LOW (rhs) == 0 - && JPRIMITIVE_TYPE_P (rhs_type)) - new_rhs = convert (lhs_type, rhs); - /* 5.1.1 Try Identity Conversion, 5.1.2 Try Widening Primitive Conversion */ else if (valid_builtin_assignconv_identity_widening_p (lhs_type, rhs_type)) new_rhs = convert (lhs_type, rhs); - /* Try a narrowing primitive conversion (5.1.3): - - expression is a constant expression of type int AND + /* Try a narrowing primitive conversion (5.1.3): + - expression is a constant expression of type byte, short, char, + or int, AND - variable is byte, short or char AND - - The value of the expression is representable in the type of the + - The value of the expression is representable in the type of the variable */ - else if (rhs_type == int_type_node && TREE_CONSTANT (rhs) + else if ((rhs_type == byte_type_node || rhs_type == short_type_node + || rhs_type == char_type_node || rhs_type == int_type_node) + && TREE_CONSTANT (rhs) && (lhs_type == byte_type_node || lhs_type == char_type_node || lhs_type == short_type_node)) { if (int_fits_type_p (rhs, lhs_type)) new_rhs = convert (lhs_type, rhs); else if (wfl_op1) /* Might be called with a NULL */ - parse_warning_context - (wfl_op1, "Constant expression `%s' too wide for narrowing primitive conversion to `%s'", + parse_warning_context + (wfl_op1, "Constant expression `%s' too wide for narrowing primitive conversion to `%s'", print_int_node (rhs), lang_printable_name (lhs_type, 0)); /* Reported a warning that will turn into an error further down, so we don't return */ @@ -12819,8 +12869,7 @@ try_builtin_assignconv (wfl_op1, lhs_type, rhs) invocation convertion (5.3). */ static int -valid_builtin_assignconv_identity_widening_p (lhs_type, rhs_type) - tree lhs_type, rhs_type; +valid_builtin_assignconv_identity_widening_p (tree lhs_type, tree rhs_type) { /* 5.1.1: This is the identity conversion part. */ if (lhs_type == rhs_type) @@ -12849,7 +12898,7 @@ valid_builtin_assignconv_identity_widening_p (lhs_type, rhs_type) /* From here, an integral is widened if its precision is smaller than the precision of the LHS or if the LHS is a floating point type, or the RHS is a float and the RHS a double. */ - if ((JINTEGRAL_TYPE_P (rhs_type) && JINTEGRAL_TYPE_P (lhs_type) + if ((JINTEGRAL_TYPE_P (rhs_type) && JINTEGRAL_TYPE_P (lhs_type) && (TYPE_PRECISION (rhs_type) < TYPE_PRECISION (lhs_type))) || (JINTEGRAL_TYPE_P (rhs_type) && JFLOAT_TYPE_P (lhs_type)) || (rhs_type == float_type_node && lhs_type == double_type_node)) @@ -12865,10 +12914,7 @@ valid_builtin_assignconv_identity_widening_p (lhs_type, rhs_type) assignment check. */ static int -valid_ref_assignconv_cast_p (source, dest, cast) - tree source; - tree dest; - int cast; +valid_ref_assignconv_cast_p (tree source, tree dest, int cast) { /* SOURCE or DEST might be null if not from a declared entity. */ if (!source || !dest) @@ -12897,7 +12943,7 @@ valid_ref_assignconv_cast_p (source, dest, cast) if (TYPE_CLASS_P (source)) { if (TYPE_CLASS_P (dest)) - return (source == dest + return (source == dest || inherits_from_p (source, dest) || (cast && inherits_from_p (dest, source))); if (TYPE_INTERFACE_P (dest)) @@ -12938,16 +12984,16 @@ valid_ref_assignconv_cast_p (source, dest, cast) tree source_type; tree source_sig; tree source_name; - for (method_source = TYPE_METHODS (source); method_source; + for (method_source = TYPE_METHODS (source); method_source; method_source = TREE_CHAIN (method_source)) { - source_sig = + source_sig = build_java_argument_signature (TREE_TYPE (method_source)); source_type = TREE_TYPE (TREE_TYPE (method_source)); source_name = DECL_NAME (method_source); for (method_dest = TYPE_METHODS (dest); method_dest; method_dest = TREE_CHAIN (method_dest)) - if (source_sig == + if (source_sig == build_java_argument_signature (TREE_TYPE (method_dest)) && source_name == DECL_NAME (method_dest) && source_type != TREE_TYPE (TREE_TYPE (method_dest))) @@ -12962,9 +13008,10 @@ valid_ref_assignconv_cast_p (source, dest, cast) { /* Array */ return (cast - && (DECL_NAME (TYPE_NAME (source)) == java_lang_cloneable + && (DECL_NAME (TYPE_NAME (source)) + == java_lang_cloneable_identifier_node || (DECL_NAME (TYPE_NAME (source)) - == java_io_serializable))); + == java_io_serializable_identifier_node))); } } if (TYPE_ARRAY_P (source)) @@ -12974,13 +13021,15 @@ valid_ref_assignconv_cast_p (source, dest, cast) /* Can't cast an array to an interface unless the interface is java.lang.Cloneable or java.io.Serializable. */ if (TYPE_INTERFACE_P (dest)) - return (DECL_NAME (TYPE_NAME (dest)) == java_lang_cloneable - || DECL_NAME (TYPE_NAME (dest)) == java_io_serializable); + return (DECL_NAME (TYPE_NAME (dest)) + == java_lang_cloneable_identifier_node + || (DECL_NAME (TYPE_NAME (dest)) + == java_io_serializable_identifier_node)); else /* Arrays */ { tree source_element_type = TYPE_ARRAY_ELEMENT (source); tree dest_element_type = TYPE_ARRAY_ELEMENT (dest); - + /* In case of severe errors, they turn out null */ if (!dest_element_type || !source_element_type) return 0; @@ -12995,9 +13044,7 @@ valid_ref_assignconv_cast_p (source, dest, cast) } static int -valid_cast_to_p (source, dest) - tree source; - tree dest; +valid_cast_to_p (tree source, tree dest) { if (TREE_CODE (source) == POINTER_TYPE) source = TREE_TYPE (source); @@ -13018,8 +13065,7 @@ valid_cast_to_p (source, dest) } static tree -do_unary_numeric_promotion (arg) - tree arg; +do_unary_numeric_promotion (tree arg) { tree type = TREE_TYPE (arg); if ((TREE_CODE (type) == INTEGER_TYPE && TYPE_PRECISION (type) < 32) @@ -13028,11 +13074,10 @@ do_unary_numeric_promotion (arg) return arg; } -/* Return a non zero value if SOURCE can be converted into DEST using +/* Return a nonzero value if SOURCE can be converted into DEST using the method invocation conversion rule (5.3). */ static int -valid_method_invocation_conversion_p (dest, source) - tree dest, source; +valid_method_invocation_conversion_p (tree dest, tree source) { return ((JPRIMITIVE_TYPE_P (source) && JPRIMITIVE_TYPE_P (dest) && valid_builtin_assignconv_identity_widening_p (dest, source)) @@ -13044,10 +13089,7 @@ valid_method_invocation_conversion_p (dest, source) /* Build an incomplete binop expression. */ static tree -build_binop (op, op_location, op1, op2) - enum tree_code op; - int op_location; - tree op1, op2; +build_binop (enum tree_code op, int op_location, tree op1, tree op2) { tree binop = build (op, NULL_TREE, op1, op2); TREE_SIDE_EFFECTS (binop) = 1; @@ -13064,15 +13106,14 @@ build_binop (op, op_location, op1, op2) buffer. */ static char * -operator_string (node) - tree node; +operator_string (tree node) { #define BUILD_OPERATOR_STRING(S) \ { \ sprintf (buffer, "%s%s", S, (COMPOUND_ASSIGN_P (node) ? "=" : "")); \ return buffer; \ } - + static char buffer [10]; switch (TREE_CODE (node)) { @@ -13114,12 +13155,11 @@ operator_string (node) /* Return 1 if VAR_ACCESS1 is equivalent to VAR_ACCESS2. */ static int -java_decl_equiv (var_acc1, var_acc2) - tree var_acc1, var_acc2; +java_decl_equiv (tree var_acc1, tree var_acc2) { if (JDECL_P (var_acc1)) return (var_acc1 == var_acc2); - + return (TREE_CODE (var_acc1) == COMPONENT_REF && TREE_CODE (var_acc2) == COMPONENT_REF && TREE_OPERAND (TREE_OPERAND (var_acc1, 0), 0) @@ -13127,12 +13167,11 @@ java_decl_equiv (var_acc1, var_acc2) && TREE_OPERAND (var_acc1, 1) == TREE_OPERAND (var_acc2, 1)); } -/* Return a non zero value if CODE is one of the operators that can be +/* Return a nonzero value if CODE is one of the operators that can be used in conjunction with the `=' operator in a compound assignment. */ static int -binop_compound_p (code) - enum tree_code code; +binop_compound_p (enum tree_code code) { int i; for (i = 0; i < BINOP_COMPOUND_CANDIDATES; i++) @@ -13145,8 +13184,7 @@ binop_compound_p (code) /* Reorganize after a fold to get SAVE_EXPR to generate what we want. */ static tree -java_refold (t) - tree t; +java_refold (tree t) { tree c, b, ns, decl; @@ -13161,7 +13199,7 @@ java_refold (t) /* Now the left branch of the binary operator. */ b = TREE_OPERAND (TREE_OPERAND (c, 1), 0); - if (! (b && TREE_CODE (b) == NOP_EXPR + if (! (b && TREE_CODE (b) == NOP_EXPR && TREE_CODE (TREE_OPERAND (b, 0)) == SAVE_EXPR)) return t; @@ -13193,10 +13231,7 @@ java_refold (t) of remaining nodes and detects more errors in certain cases. */ static tree -patch_binop (node, wfl_op1, wfl_op2) - tree node; - tree wfl_op1; - tree wfl_op2; +patch_binop (tree node, tree wfl_op1, tree wfl_op2) { tree op1 = TREE_OPERAND (node, 0); tree op2 = TREE_OPERAND (node, 1); @@ -13215,7 +13250,7 @@ patch_binop (node, wfl_op1, wfl_op2) error situation, unless it's too early to tell (in case we're handling a `+', `==', `!=' or `instanceof'.) We want to set op_type correctly so the error can be later on reported accurately. */ - if (! (code == PLUS_EXPR || code == NE_EXPR + if (! (code == PLUS_EXPR || code == NE_EXPR || code == EQ_EXPR || code == INSTANCEOF_EXPR)) { tree n; @@ -13260,7 +13295,7 @@ patch_binop (node, wfl_op1, wfl_op2) parse_warning_context (wfl_operator, "Evaluating this expression will result in an arithmetic exception being thrown"); TREE_CONSTANT (node) = 0; } - + /* Change the division operator if necessary */ if (code == RDIV_EXPR && TREE_CODE (prom_type) == INTEGER_TYPE) TREE_SET_CODE (node, TRUNC_DIV_EXPR); @@ -13283,7 +13318,7 @@ patch_binop (node, wfl_op1, wfl_op2) && ! flag_emit_class_files && (code == RDIV_EXPR || code == TRUNC_MOD_EXPR)) return build_java_soft_divmod (TREE_CODE (node), prom_type, op1, op2); - + /* This one is more complicated. FLOATs are processed by a function call to soft_fmod. Duplicate the value of the COMPOUND_ASSIGN_P flag. */ @@ -13305,7 +13340,7 @@ patch_binop (node, wfl_op1, wfl_op2) purpose of the a previous usage of the String concatenation operator */ - if (TREE_CODE (op1) == STRING_CST + if (TREE_CODE (op1) == STRING_CST || TREE_CODE (op2) == STRING_CST || JSTRING_TYPE_P (op1_type) || JSTRING_TYPE_P (op2_type) @@ -13345,7 +13380,7 @@ patch_binop (node, wfl_op1, wfl_op2) lang_printable_name (op2_type, 0)); else parse_error_context (wfl_operator, - "Incompatible type for `%s'. Can't convert shift distance from `%s' to integral", + "Incompatible type for `%s'. Can't convert shift distance from `%s' to integral", operator_string (node), lang_printable_name (op2_type, 0)); } @@ -13359,23 +13394,28 @@ patch_binop (node, wfl_op1, wfl_op2) op1 = do_unary_numeric_promotion (op1); op2 = do_unary_numeric_promotion (op2); + /* If the right hand side is of type `long', first cast it to + `int'. */ + if (TREE_TYPE (op2) == long_type_node) + op2 = build1 (CONVERT_EXPR, int_type_node, op2); + /* The type of the shift expression is the type of the promoted type of the left-hand operand */ prom_type = TREE_TYPE (op1); /* Shift int only up to 0x1f and long up to 0x3f */ if (prom_type == int_type_node) - op2 = fold (build (BIT_AND_EXPR, int_type_node, op2, + op2 = fold (build (BIT_AND_EXPR, int_type_node, op2, build_int_2 (0x1f, 0))); else - op2 = fold (build (BIT_AND_EXPR, int_type_node, op2, + op2 = fold (build (BIT_AND_EXPR, int_type_node, op2, build_int_2 (0x3f, 0))); /* The >>> operator is a >> operating on unsigned quantities */ if (code == URSHIFT_EXPR && ! flag_emit_class_files) { tree to_return; - tree utype = unsigned_type (prom_type); + tree utype = java_unsigned_type (prom_type); op1 = convert (utype, op1); TREE_SET_CODE (node, RSHIFT_EXPR); TREE_OPERAND (node, 0) = op1; @@ -13390,11 +13430,20 @@ patch_binop (node, wfl_op1, wfl_op2) } break; - /* 15.19.1 Type Comparison Operator instaceof */ + /* 15.19.1 Type Comparison Operator instanceof */ case INSTANCEOF_EXPR: TREE_TYPE (node) = boolean_type_node; + /* OP1_TYPE might be NULL when OP1 is a string constant. */ + if ((cn = patch_string (op1))) + { + op1 = cn; + op1_type = TREE_TYPE (op1); + } + if (op1_type == NULL_TREE) + abort (); + if (!(op2_type = resolve_type_during_patch (op2))) return error_mark_node; @@ -13433,13 +13482,13 @@ patch_binop (node, wfl_op1, wfl_op2) { char *t1 = xstrdup (lang_printable_name (op1_type, 0)); SET_WFL_OPERATOR (wfl_operator, node, wfl_op1); - parse_error_context + parse_error_context (wfl_operator, "Impossible for `%s' to be instance of `%s'", t1, lang_printable_name (op2_type, 0)); free (t1); error_found = 1; } - + break; /* 15.21 Bitwise and Logical Operators */ @@ -13451,7 +13500,7 @@ patch_binop (node, wfl_op1, wfl_op2) expression retain that type */ prom_type = binary_numeric_promotion (op1_type, op2_type, &op1, &op2); - else if (TREE_CODE (op1_type) == BOOLEAN_TYPE + else if (TREE_CODE (op1_type) == BOOLEAN_TYPE && TREE_CODE (op1_type) == BOOLEAN_TYPE) /* The type of the bitwise operator expression is BOOLEAN */ prom_type = boolean_type_node; @@ -13473,7 +13522,7 @@ patch_binop (node, wfl_op1, wfl_op2) /* 15.23 Conditional-Or Operator */ case TRUTH_ORIF_EXPR: /* Operands must be of BOOLEAN type */ - if (TREE_CODE (op1_type) != BOOLEAN_TYPE || + if (TREE_CODE (op1_type) != BOOLEAN_TYPE || TREE_CODE (op2_type) != BOOLEAN_TYPE) { if (TREE_CODE (op1_type) != BOOLEAN_TYPE) @@ -13523,48 +13572,48 @@ patch_binop (node, wfl_op1, wfl_op2) case EQ_EXPR: case NE_EXPR: /* It's time for us to patch the strings. */ - if ((cn = patch_string (op1))) + if ((cn = patch_string (op1))) { op1 = cn; op1_type = TREE_TYPE (op1); } - if ((cn = patch_string (op2))) + if ((cn = patch_string (op2))) { op2 = cn; op2_type = TREE_TYPE (op2); } - + /* 15.20.1 Numerical Equality Operators == and != */ /* Binary numeric promotion is performed on the operands */ if (JNUMERIC_TYPE_P (op1_type) && JNUMERIC_TYPE_P (op2_type)) binary_numeric_promotion (op1_type, op2_type, &op1, &op2); - + /* 15.20.2 Boolean Equality Operators == and != */ else if (TREE_CODE (op1_type) == BOOLEAN_TYPE && TREE_CODE (op2_type) == BOOLEAN_TYPE) ; /* Nothing to do here */ - + /* 15.20.3 Reference Equality Operators == and != */ /* Types have to be either references or the null type. If they're references, it must be possible to convert either type to the other by casting conversion. */ - else if (op1 == null_pointer_node || op2 == null_pointer_node + else if (op1 == null_pointer_node || op2 == null_pointer_node || (JREFERENCE_TYPE_P (op1_type) && JREFERENCE_TYPE_P (op2_type) && (valid_ref_assignconv_cast_p (op1_type, op2_type, 1) - || valid_ref_assignconv_cast_p (op2_type, + || valid_ref_assignconv_cast_p (op2_type, op1_type, 1)))) ; /* Nothing to do here */ - + /* Else we have an error figure what can't be converted into what and report the error */ else { char *t1; t1 = xstrdup (lang_printable_name (op1_type, 0)); - parse_error_context + parse_error_context (wfl_operator, "Incompatible type for `%s'. Can't convert `%s' to `%s'", - operator_string (node), t1, + operator_string (node), t1, lang_printable_name (op2_type, 0)); free (t1); TREE_TYPE (node) = boolean_type_node; @@ -13584,7 +13633,7 @@ patch_binop (node, wfl_op1, wfl_op2) TREE_OPERAND (node, 1) = op2; TREE_TYPE (node) = prom_type; TREE_SIDE_EFFECTS (node) = TREE_SIDE_EFFECTS (op1) | TREE_SIDE_EFFECTS (op2); - + if (flag_emit_xref) return node; @@ -13602,10 +13651,7 @@ patch_binop (node, wfl_op1, wfl_op2) zero value, the value of CSTE comes after the valude of STRING */ static tree -do_merge_string_cste (cste, string, string_len, after) - tree cste; - const char *string; - int string_len, after; +do_merge_string_cste (tree cste, const char *string, int string_len, int after) { const char *old = TREE_STRING_POINTER (cste); int old_len = TREE_STRING_LENGTH (cste); @@ -13627,42 +13673,59 @@ do_merge_string_cste (cste, string, string_len, after) } /* Tries to merge OP1 (a STRING_CST) and OP2 (if suitable). Return a - new STRING_CST on success, NULL_TREE on failure */ + new STRING_CST on success, NULL_TREE on failure. */ static tree -merge_string_cste (op1, op2, after) - tree op1, op2; - int after; +merge_string_cste (tree op1, tree op2, int after) { - /* Handle two string constants right away */ + /* Handle two string constants right away. */ if (TREE_CODE (op2) == STRING_CST) - return do_merge_string_cste (op1, TREE_STRING_POINTER (op2), + return do_merge_string_cste (op1, TREE_STRING_POINTER (op2), TREE_STRING_LENGTH (op2), after); - - /* Reasonable integer constant can be treated right away */ + + /* Reasonable integer constant can be treated right away. */ if (TREE_CODE (op2) == INTEGER_CST && !TREE_CONSTANT_OVERFLOW (op2)) { static const char *const boolean_true = "true"; static const char *const boolean_false = "false"; static const char *const null_pointer = "null"; - char ch[3]; + char ch[4]; const char *string; - + if (op2 == boolean_true_node) string = boolean_true; else if (op2 == boolean_false_node) string = boolean_false; else if (op2 == null_pointer_node) + /* FIXME: null is not a compile-time constant, so it is only safe to + merge if the overall expression is non-constant. However, this + code always merges without checking the overall expression. */ string = null_pointer; else if (TREE_TYPE (op2) == char_type_node) { - ch[0] = (char )TREE_INT_CST_LOW (op2); - ch[1] = '\0'; + /* Convert the character into UTF-8. */ + unsigned int c = (unsigned int) TREE_INT_CST_LOW (op2); + unsigned char *p = (unsigned char *) ch; + if (0x01 <= c && c <= 0x7f) + *p++ = (unsigned char) c; + else if (c < 0x7ff) + { + *p++ = (unsigned char) (c >> 6 | 0xc0); + *p++ = (unsigned char) ((c & 0x3f) | 0x80); + } + else + { + *p++ = (unsigned char) (c >> 12 | 0xe0); + *p++ = (unsigned char) (((c >> 6) & 0x3f) | 0x80); + *p++ = (unsigned char) ((c & 0x3f) | 0x80); + } + *p = '\0'; + string = ch; } else - string = print_int_node (op2); - + string = string_convert_int_cst (op2); + return do_merge_string_cste (op1, string, strlen (string), after); } return NULL_TREE; @@ -13677,18 +13740,17 @@ merge_string_cste (op1, op2, after) NULL_TREE for each invocation of this routine. FIXME */ static tree -string_constant_concatenation (op1, op2) - tree op1, op2; +string_constant_concatenation (tree op1, tree op2) { if (TREE_CODE (op1) == STRING_CST || (TREE_CODE (op2) == STRING_CST)) { tree string, rest; int invert; - + string = (TREE_CODE (op1) == STRING_CST ? op1 : op2); rest = (string == op1 ? op2 : op1); invert = (string == op1 ? 0 : 1 ); - + /* Walk REST, only if it looks reasonable */ if (TREE_CODE (rest) != STRING_CST && !IS_CRAFTED_STRING_BUFFER_P (rest) @@ -13712,15 +13774,14 @@ string_constant_concatenation (op1, op2) called on it to turn it into a String object. */ static tree -build_string_concatenation (op1, op2) - tree op1, op2; +build_string_concatenation (tree op1, tree op2) { tree result; int side_effects = TREE_SIDE_EFFECTS (op1) | TREE_SIDE_EFFECTS (op2); if (flag_emit_xref) return build (PLUS_EXPR, string_type_node, op1, op2); - + /* Try to do some static optimization */ if ((result = string_constant_concatenation (op1, op2))) return result; @@ -13741,15 +13802,15 @@ build_string_concatenation (op1, op2) op2 = patch_string_cst (op2); /* If either one of the constant is null and the other non null - operand is a String object, return it. */ - if (JSTRING_TYPE_P (TREE_TYPE (op1)) && !op2) + operand is a String constant, return it. */ + if ((TREE_CODE (op1) == STRING_CST) && !op2) return op1; /* If OP1 isn't already a StringBuffer, create and initialize a new one */ if (!IS_CRAFTED_STRING_BUFFER_P (op1)) { - /* Two solutions here: + /* Two solutions here: 1) OP1 is a constant string reference, we call new StringBuffer(OP1) 2) OP1 is something else, we call new StringBuffer().append(OP1). */ if (TREE_CONSTANT (op1) && JSTRING_TYPE_P (TREE_TYPE (op1))) @@ -13782,8 +13843,7 @@ build_string_concatenation (op1, op2) NULL. */ static tree -patch_string (node) - tree node; +patch_string (tree node) { if (node == error_mark_node) return error_mark_node; @@ -13809,8 +13869,7 @@ patch_string (node) /* Build the internal representation of a string constant. */ static tree -patch_string_cst (node) - tree node; +patch_string_cst (tree node) { int location; if (! flag_emit_class_files) @@ -13827,9 +13886,7 @@ patch_string_cst (node) /* Build an incomplete unary operator expression. */ static tree -build_unaryop (op_token, op_location, op1) - int op_token, op_location; - tree op1; +build_unaryop (int op_token, int op_location, tree op1) { enum tree_code op; tree unaryop; @@ -13855,24 +13912,21 @@ build_unaryop (op_token, op_location, op1) later. IS_POST_P is 1 if the operator, 0 otherwise. */ static tree -build_incdec (op_token, op_location, op1, is_post_p) - int op_token, op_location; - tree op1; - int is_post_p; +build_incdec (int op_token, int op_location, tree op1, int is_post_p) { - static const enum tree_code lookup [2][2] = + static const enum tree_code lookup [2][2] = { { PREDECREMENT_EXPR, PREINCREMENT_EXPR, }, { POSTDECREMENT_EXPR, POSTINCREMENT_EXPR, }, }; - tree node = build (lookup [is_post_p][(op_token - DECR_TK)], + tree node = build (lookup [is_post_p][(op_token - DECR_TK)], NULL_TREE, op1, NULL_TREE); TREE_SIDE_EFFECTS (node) = 1; /* Store the location of the operator, for better error report. The string of the operator will be rebuild based on the OP value. */ EXPR_WFL_LINECOL (node) = op_location; return node; -} +} /* Build an incomplete cast operator, based on the use of the CONVERT_EXPR. Note that TREE_TYPE of the constructed node is @@ -13880,9 +13934,7 @@ build_incdec (op_token, op_location, op1, is_post_p) though its type is already set. */ static tree -build_cast (location, type, exp) - int location; - tree type, exp; +build_cast (int location, tree type, tree exp) { tree node = build1 (CONVERT_EXPR, type, exp); EXPR_WFL_LINECOL (node) = location; @@ -13891,9 +13943,7 @@ build_cast (location, type, exp) /* Build an incomplete class reference operator. */ static tree -build_incomplete_class_ref (location, class_name) - int location; - tree class_name; +build_incomplete_class_ref (int location, tree class_name) { tree node = build1 (CLASS_LITERAL, NULL_TREE, class_name); EXPR_WFL_LINECOL (node) = location; @@ -13902,8 +13952,7 @@ build_incomplete_class_ref (location, class_name) /* Complete an incomplete class reference operator. */ static tree -patch_incomplete_class_ref (node) - tree node; +patch_incomplete_class_ref (tree node) { tree type = TREE_OPERAND (node, 0); tree ref_type; @@ -13911,7 +13960,17 @@ patch_incomplete_class_ref (node) if (!(ref_type = resolve_type_during_patch (type))) return error_mark_node; - if (!flag_emit_class_files || JPRIMITIVE_TYPE_P (ref_type)) + /* Generate the synthetic static method `class$'. (Previously we + deferred this, causing different method tables to be emitted + for native code and bytecode.) */ + if (!TYPE_DOT_CLASS (current_class)) + build_dot_class_method (current_class); + + /* If we're not emitting class files and we know ref_type is a + compiled class, build a direct reference. */ + if ((! flag_emit_class_files && is_compiled_class (ref_type)) + || JPRIMITIVE_TYPE_P (ref_type) + || TREE_CODE (ref_type) == VOID_TYPE) { tree dot = build_class_ref (ref_type); /* A class referenced by `foo.class' is initialized. */ @@ -13921,10 +13980,7 @@ patch_incomplete_class_ref (node) } /* If we're emitting class files and we have to deal with non - primitive types, we invoke (and consider generating) the - synthetic static method `class$'. */ - if (!TYPE_DOT_CLASS (current_class)) - build_dot_class_method (current_class); + primitive types, we invoke the synthetic static method `class$'. */ ref_type = build_dot_class_method_invocation (ref_type); return java_complete_tree (ref_type); } @@ -13933,9 +13989,7 @@ patch_incomplete_class_ref (node) but preserve the type of NODE if the type is fixed. */ static tree -patch_unaryop (node, wfl_op) - tree node; - tree wfl_op; +patch_unaryop (tree node, tree wfl_op) { tree op = TREE_OPERAND (node, 0); tree op_type = TREE_TYPE (op); @@ -13973,7 +14027,7 @@ patch_unaryop (node, wfl_op) decl = DECL_FUNCTION_ACCESS_DECL (decl); } /* We really should have a JAVA_ARRAY_EXPR to avoid this */ - else if (!JDECL_P (decl) + else if (!JDECL_P (decl) && TREE_CODE (decl) != COMPONENT_REF && !(flag_emit_class_files && TREE_CODE (decl) == ARRAY_REF) && TREE_CODE (decl) != INDIRECT_REF @@ -13984,7 +14038,7 @@ patch_unaryop (node, wfl_op) TREE_TYPE (node) = error_mark_node; error_found = 1; } - + /* From now on, we know that op if a variable and that it has a valid wfl. We use wfl_op to locate errors related to the ++/-- operand. */ @@ -14008,8 +14062,8 @@ patch_unaryop (node, wfl_op) else { value = build_int_2 (1, 0); - TREE_TYPE (node) = - binary_numeric_promotion (op_type, + TREE_TYPE (node) = + binary_numeric_promotion (op_type, TREE_TYPE (value), &op, &value); } @@ -14017,10 +14071,10 @@ patch_unaryop (node, wfl_op) if (outer_field_flag) { /* We re-generate an access to the field */ - value = build (PLUS_EXPR, TREE_TYPE (op), + value = build (PLUS_EXPR, TREE_TYPE (op), build_outer_field_access (wfl_op, decl), value); - - /* And we patch the original access$() into a write + + /* And we patch the original access$() into a write with plus_op as a rhs */ return outer_field_access_fix (node, op, value); } @@ -14105,7 +14159,7 @@ patch_unaryop (node, wfl_op) } break; } - + if (error_found) return error_mark_node; @@ -14123,30 +14177,31 @@ patch_unaryop (node, wfl_op) message. Return the resolved type or NULL_TREE. */ static tree -resolve_type_during_patch (type) - tree type; +resolve_type_during_patch (tree type) { if (unresolved_type_p (type, NULL)) { tree type_decl = resolve_and_layout (EXPR_WFL_NODE (type), type); if (!type_decl) { - parse_error_context (type, + parse_error_context (type, "Class `%s' not found in type declaration", IDENTIFIER_POINTER (EXPR_WFL_NODE (type))); return NULL_TREE; } + + check_deprecation (type, type_decl); + return TREE_TYPE (type_decl); } return type; } + /* 5.5 Casting Conversion. error_mark_node is returned if an error is found. Otherwise NODE or something meant to replace it is returned. */ static tree -patch_cast (node, wfl_op) - tree node; - tree wfl_op; +patch_cast (tree node, tree wfl_op) { tree op = TREE_OPERAND (node, 0); tree cast_type = TREE_TYPE (node); @@ -14169,14 +14224,15 @@ patch_cast (node, wfl_op) if (cast_type == op_type) return node; - /* float and double type are converted to the original type main - variant and then to the target type. */ - if (JFLOAT_TYPE_P (op_type) && TREE_CODE (cast_type) == CHAR_TYPE) - op = convert (integer_type_node, op); + /* A narrowing conversion from a floating-point number to an + integral type requires special handling (5.1.3). */ + if (JFLOAT_TYPE_P (op_type) && JINTEGRAL_TYPE_P (cast_type)) + if (cast_type != long_type_node) + op = convert (integer_type_node, op); - /* Try widening/narowwing convertion. Potentially, things need + /* Try widening/narrowing convertion. Potentially, things need to be worked out in gcc so we implement the extreme cases - correctly. fold_convert() needs to be fixed. */ + correctly. fold_convert() needs to be fixed. */ return convert (cast_type, op); } @@ -14190,7 +14246,7 @@ patch_cast (node, wfl_op) /* The remaining legal casts involve conversion between reference types. Check for their compile time correctness. */ - if (JREFERENCE_TYPE_P (op_type) && JREFERENCE_TYPE_P (cast_type) + if (JREFERENCE_TYPE_P (op_type) && JREFERENCE_TYPE_P (cast_type) && valid_ref_assignconv_cast_p (op_type, cast_type, 1)) { TREE_TYPE (node) = promote_type (cast_type); @@ -14229,8 +14285,7 @@ patch_cast (node, wfl_op) /* Build a null constant and give it the type TYPE. */ static tree -build_null_of_type (type) - tree type; +build_null_of_type (tree type) { tree node = build_int_2 (0, 0); TREE_TYPE (node) = promote_type (type); @@ -14240,9 +14295,7 @@ build_null_of_type (type) /* Build an ARRAY_REF incomplete tree node. Note that operand 1 isn't a list of indices. */ static tree -build_array_ref (location, array, index) - int location; - tree array, index; +build_array_ref (int location, tree array, tree index) { tree node = build (ARRAY_REF, NULL_TREE, array, index); EXPR_WFL_LINECOL (node) = location; @@ -14252,8 +14305,7 @@ build_array_ref (location, array, index) /* 15.12 Array Access Expression */ static tree -patch_array_ref (node) - tree node; +patch_array_ref (tree node) { tree array = TREE_OPERAND (node, 0); tree array_type = TREE_TYPE (array); @@ -14269,7 +14321,7 @@ patch_array_ref (node) /* The array reference must be an array */ if (!TYPE_ARRAY_P (array_type)) { - parse_error_context + parse_error_context (wfl_operator, "`[]' can only be applied to arrays. It can't be applied to `%s'", lang_printable_name (array_type, 0)); @@ -14313,20 +14365,16 @@ patch_array_ref (node) /* 15.9 Array Creation Expressions */ static tree -build_newarray_node (type, dims, extra_dims) - tree type; - tree dims; - int extra_dims; +build_newarray_node (tree type, tree dims, int extra_dims) { tree node = - build (NEW_ARRAY_EXPR, NULL_TREE, type, nreverse (dims), + build (NEW_ARRAY_EXPR, NULL_TREE, type, nreverse (dims), build_int_2 (extra_dims, 0)); return node; } static tree -patch_newarray (node) - tree node; +patch_newarray (tree node) { tree type = TREE_OPERAND (node, 0); tree dims = TREE_OPERAND (node, 1); @@ -14361,9 +14409,9 @@ patch_newarray (node) /* Report errors on types here */ if (dim_error) { - parse_error_context - (TREE_PURPOSE (cdim), - "Incompatible type for dimension in array creation expression. %s convert `%s' to `int'", + parse_error_context + (TREE_PURPOSE (cdim), + "Incompatible type for dimension in array creation expression. %s convert `%s' to `int'", (valid_cast_to_p (TREE_TYPE (dim), int_type_node) ? "Explicit cast needed to" : "Can't"), lang_printable_name (TREE_TYPE (dim), 0)); @@ -14412,13 +14460,13 @@ patch_newarray (node) (primitive or not) matters. */ if (ndims == 1) return build_new_array (type, TREE_VALUE (dims)); - + /* Can't reuse what's already written in expr.c because it uses the JVM stack representation. Provide a build_multianewarray. FIXME */ return build (CALL_EXPR, array_type, build_address_of (soft_multianewarray_node), tree_cons (NULL_TREE, build_class_ref (TREE_TYPE (array_type)), - tree_cons (NULL_TREE, + tree_cons (NULL_TREE, build_int_2 (ndims, 0), dims )), NULL_TREE); } @@ -14429,8 +14477,7 @@ patch_newarray (node) pin-point errors. */ static tree -maybe_build_array_element_wfl (node) - tree node; +maybe_build_array_element_wfl (tree node) { if (TREE_CODE (node) != EXPR_WITH_FILE_LOCATION) return build_expr_wfl (NULL_TREE, ctxp->filename, @@ -14444,11 +14491,9 @@ maybe_build_array_element_wfl (node) and expansion. */ static tree -build_new_array_init (location, values) - int location; - tree values; +build_new_array_init (int location, tree values) { - tree constructor = build (CONSTRUCTOR, NULL_TREE, NULL_TREE, values); + tree constructor = build_constructor (NULL_TREE, values); tree to_return = build1 (NEW_ARRAY_INIT, NULL_TREE, constructor); EXPR_WFL_LINECOL (to_return) = location; return to_return; @@ -14459,8 +14504,7 @@ build_new_array_init (location, values) appropriately. */ static tree -patch_new_array_init (type, node) - tree type, node; +patch_new_array_init (tree type, tree node) { int error_seen = 0; tree current, element_type; @@ -14499,7 +14543,7 @@ patch_new_array_init (type, node) TREE_PURPOSE (current) = NULL_TREE; all_constant = 0; } - if (elt && TREE_CODE (elt) == TREE_LIST + if (elt && TREE_CODE (elt) == TREE_LIST && TREE_VALUE (elt) == error_mark_node) error_seen = 1; } @@ -14523,8 +14567,7 @@ patch_new_array_init (type, node) otherwise. */ static int -array_constructor_check_entry (type, entry) - tree type, entry; +array_constructor_check_entry (tree type, tree entry) { char *array_type_string = NULL; /* For error reports */ tree value, type_value, new_value, wfl_value, patched; @@ -14539,9 +14582,9 @@ array_constructor_check_entry (type, entry) value = patched; if (value == error_mark_node) return 1; - + type_value = TREE_TYPE (value); - + /* At anytime, try_builtin_assignconv can report a warning on constant overflow during narrowing. */ SET_WFL_OPERATOR (wfl_operator, TREE_PURPOSE (entry), wfl_value); @@ -14556,12 +14599,12 @@ array_constructor_check_entry (type, entry) "Can't" : "Explicit cast needed to"); if (!array_type_string) array_type_string = xstrdup (lang_printable_name (type, 1)); - parse_error_context + parse_error_context (wfl_operator, "Incompatible type for array. %s convert `%s' to `%s'", msg, lang_printable_name (type_value, 1), array_type_string); error_seen = 1; } - + if (new_value) TREE_VALUE (entry) = new_value; @@ -14573,8 +14616,7 @@ array_constructor_check_entry (type, entry) } static tree -build_this (location) - int location; +build_this (int location) { tree node = build_wfl_node (this_identifier_node); TREE_SET_CODE (node, THIS_EXPR); @@ -14587,9 +14629,7 @@ build_this (location) to be returned. */ static tree -build_return (location, op) - int location; - tree op; +build_return (int location, tree op) { tree node = build1 (RETURN_EXPR, NULL_TREE, op); EXPR_WFL_LINECOL (node) = location; @@ -14598,8 +14638,7 @@ build_return (location, op) } static tree -patch_return (node) - tree node; +patch_return (tree node) { tree return_exp = TREE_OPERAND (node, 0); tree meth = current_function_decl; @@ -14622,7 +14661,7 @@ patch_return (node) isn't declared with the keyword `void' */ if (!return_exp && (mtype != void_type_node && !DECL_CONSTRUCTOR_P (meth))) error_found = 2; - + if (DECL_INSTINIT_P (current_function_decl)) error_found = 1; @@ -14631,7 +14670,7 @@ patch_return (node) if (DECL_INSTINIT_P (current_function_decl)) parse_error_context (wfl_operator, "`return' inside instance initializer"); - + else if (DECL_CLINIT_P (current_function_decl)) parse_error_context (wfl_operator, "`return' inside static initializer"); @@ -14639,14 +14678,14 @@ patch_return (node) else if (!DECL_CONSTRUCTOR_P (meth)) { char *t = xstrdup (lang_printable_name (mtype, 0)); - parse_error_context (wfl_operator, + parse_error_context (wfl_operator, "`return' with%s value from `%s %s'", - (error_found == 1 ? "" : "out"), + (error_found == 1 ? "" : "out"), t, lang_printable_name (meth, 0)); free (t); } else - parse_error_context (wfl_operator, + parse_error_context (wfl_operator, "`return' with value from constructor `%s'", lang_printable_name (meth, 0)); return error_mark_node; @@ -14662,7 +14701,7 @@ patch_return (node) if ((patched = patch_string (exp))) exp = patched; - + modify = build (MODIFY_EXPR, NULL_TREE, DECL_RESULT (meth), exp); EXPR_WFL_LINECOL (modify) = EXPR_WFL_LINECOL (node); modify = java_complete_tree (modify); @@ -14683,9 +14722,8 @@ patch_return (node) /* 14.8 The if Statement */ static tree -build_if_else_statement (location, expression, if_body, else_body) - int location; - tree expression, if_body, else_body; +build_if_else_statement (int location, tree expression, tree if_body, + tree else_body) { tree node; if (!else_body) @@ -14697,8 +14735,7 @@ build_if_else_statement (location, expression, if_body, else_body) } static tree -patch_if_else_statement (node) - tree node; +patch_if_else_statement (tree node) { tree expression = TREE_OPERAND (node, 0); int can_complete_normally @@ -14712,13 +14749,13 @@ patch_if_else_statement (node) if (TREE_TYPE (expression) != boolean_type_node && TREE_TYPE (expression) != promoted_boolean_type_node) { - parse_error_context - (wfl_operator, - "Incompatible type for `if'. Can't convert `%s' to `boolean'", + parse_error_context + (wfl_operator, + "Incompatible type for `if'. Can't convert `%s' to `boolean'", lang_printable_name (TREE_TYPE (expression), 0)); return error_mark_node; } - + if (TREE_CODE (expression) == INTEGER_CST) { if (integer_zerop (expression)) @@ -14745,9 +14782,7 @@ patch_if_else_statement (node) label, yet. LABEL can be NULL_TREE for artificially-generated blocks. */ static tree -build_labeled_block (location, label) - int location; - tree label; +build_labeled_block (int location, tree label) { tree label_name ; tree label_decl, node; @@ -14764,7 +14799,7 @@ build_labeled_block (location, label) parse_error_context (wfl_operator, "Declaration of `%s' shadows a previous label declaration", IDENTIFIER_POINTER (label)); - EXPR_WFL_LINECOL (wfl_operator) = + EXPR_WFL_LINECOL (wfl_operator) = EXPR_WFL_LINECOL (IDENTIFIER_LOCAL_VALUE (label_name)); parse_error_context (wfl_operator, "This is the location of the previous declaration of label `%s'", @@ -14783,9 +14818,8 @@ build_labeled_block (location, label) /* A labeled statement LBE is attached a statement. */ static tree -finish_labeled_statement (lbe, statement) - tree lbe; /* Labeled block expr */ - tree statement; +finish_labeled_statement (tree lbe, /* Labeled block expr */ + tree statement) { /* In anyways, tie the loop to its statement */ LABELED_BLOCK_BODY (lbe) = statement; @@ -14800,8 +14834,7 @@ finish_labeled_statement (lbe, statement) list. */ static tree -build_new_loop (loop_body) - tree loop_body; +build_new_loop (tree loop_body) { tree loop = build (LOOP_EXPR, NULL_TREE, loop_body); TREE_SIDE_EFFECTS (loop) = 1; @@ -14814,11 +14847,11 @@ build_new_loop (loop_body) COMPOUND_EXPR (loop main body) EXIT_EXPR (this order is for while/for loops. LABELED_BLOCK_EXPR the order is reversed for do loops) - LABEL_DECL (a continue occurring here branches at the + LABEL_DECL (a continue occurring here branches at the BODY end of this labeled block) INCREMENT (if any) - REVERSED, if non zero, tells that the loop condition expr comes + REVERSED, if nonzero, tells that the loop condition expr comes after the body, like in the do-while loop. To obtain a loop, the loop body structure described above is @@ -14830,10 +14863,7 @@ build_new_loop (loop_body) */ static tree -build_loop_body (location, condition, reversed) - int location; - tree condition; - int reversed; +build_loop_body (int location, tree condition, int reversed) { tree first, second, body; @@ -14845,8 +14875,8 @@ build_loop_body (location, condition, reversed) body = build_labeled_block (0, continue_identifier_node); first = (reversed ? body : condition); second = (reversed ? condition : body); - return - build (COMPOUND_EXPR, NULL_TREE, + return + build (COMPOUND_EXPR, NULL_TREE, build (COMPOUND_EXPR, NULL_TREE, first, second), empty_stmt_node); } @@ -14855,10 +14885,7 @@ build_loop_body (location, condition, reversed) loop list. */ static tree -finish_loop_body (location, condition, body, reversed) - int location; - tree condition, body; - int reversed; +finish_loop_body (int location, tree condition, tree body, int reversed) { tree to_return = ctxp->current_loop; tree loop_body = LOOP_EXPR_BODY (to_return); @@ -14881,14 +14908,32 @@ finish_loop_body (location, condition, body, reversed) loops feature the condition part */ static tree -finish_for_loop (location, condition, update, body) - int location; - tree condition, update, body; +finish_for_loop (int location, tree condition, tree update, tree body) { /* Put the condition and the loop body in place */ tree loop = finish_loop_body (location, condition, body, 0); /* LOOP is the current loop which has been now popped of the loop - stack. Install the update block */ + stack. Mark the update block as reachable and install it. We do + this because the (current interpretation of the) JLS requires + that the update expression be considered reachable even if the + for loop's body doesn't complete normally. */ + if (update != NULL_TREE && update != empty_stmt_node) + { + tree up2 = update; + if (TREE_CODE (up2) == EXPR_WITH_FILE_LOCATION) + up2 = EXPR_WFL_NODE (up2); + /* It is possible for the update expression to be an + EXPR_WFL_NODE wrapping nothing. */ + if (up2 != NULL_TREE && up2 != empty_stmt_node) + { + /* Try to detect constraint violations. These would be + programming errors somewhere. */ + if (! IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (up2))) + || TREE_CODE (up2) == LOOP_EXPR) + abort (); + SUPPRESS_UNREACHABLE_ERROR (up2) = 1; + } + } LOOP_EXPR_BODY_UPDATE_BLOCK (LOOP_EXPR_BODY (loop)) = update; return loop; } @@ -14902,8 +14947,7 @@ finish_for_loop (location, condition, update, body) LABELED_BLOCK_EXPR's block. */ static tree -search_loop (statement) - tree statement; +search_loop (tree statement) { if (TREE_CODE (statement) == LOOP_EXPR) return statement; @@ -14925,8 +14969,7 @@ search_loop (statement) returned otherwise. */ static int -labeled_block_contains_loop_p (block, loop) - tree block, loop; +labeled_block_contains_loop_p (tree block, tree loop) { if (!block) return 0; @@ -14944,8 +14987,7 @@ labeled_block_contains_loop_p (block, loop) insert LOOP as its body. */ static tree -patch_loop_statement (loop) - tree loop; +patch_loop_statement (tree loop) { tree loop_label; @@ -14967,15 +15009,13 @@ patch_loop_statement (loop) unlabeled break/continue statement. */ static tree -build_bc_statement (location, is_break, name) - int location, is_break; - tree name; +build_bc_statement (int location, int is_break, tree name) { tree break_continue, label_block_expr = NULL_TREE; if (name) { - if (!(label_block_expr = IDENTIFIER_LOCAL_VALUE + if (!(label_block_expr = IDENTIFIER_LOCAL_VALUE (merge_qualified_name (label_id, EXPR_WFL_NODE (name))))) /* Null means that we don't have a target for this named break/continue. In this case, we make the target to be the @@ -14985,7 +15025,7 @@ build_bc_statement (location, is_break, name) } /* Unlabeled break/continue will be handled during the break/continue patch operation */ - break_continue + break_continue = build (EXIT_BLOCK_EXPR, NULL_TREE, label_block_expr, NULL_TREE); IS_BREAK_STMT_P (break_continue) = is_break; @@ -14998,13 +15038,12 @@ build_bc_statement (location, is_break, name) /* Verification of a break/continue statement. */ static tree -patch_bc_statement (node) - tree node; +patch_bc_statement (tree node) { tree bc_label = EXIT_BLOCK_LABELED_BLOCK (node), target_stmt; tree labeled_block = ctxp->current_labeled_block; EXPR_WFL_LINECOL (wfl_operator) = EXPR_WFL_LINECOL (node); - + /* Having an identifier here means that the target is unknown. */ if (bc_label != NULL_TREE && TREE_CODE (bc_label) == IDENTIFIER_NODE) { @@ -15023,7 +15062,7 @@ patch_bc_statement (node) parse_error_context (wfl_operator, "`continue' must be in loop"); else - parse_error_context + parse_error_context (wfl_operator, "continue label `%s' does not name a loop", IDENTIFIER_POINTER (bc_label)); return error_mark_node; @@ -15039,7 +15078,7 @@ patch_bc_statement (node) } } else if (!bc_label) - { + { for (;; labeled_block = TREE_CHAIN (labeled_block)) { if (labeled_block == NULL_TREE) @@ -15075,8 +15114,7 @@ patch_bc_statement (node) boolean. */ static tree -patch_exit_expr (node) - tree node; +patch_exit_expr (tree node) { tree expression = TREE_OPERAND (node, 0); TREE_TYPE (node) = error_mark_node; @@ -15085,15 +15123,15 @@ patch_exit_expr (node) /* The type of expression must be boolean */ if (TREE_TYPE (expression) != boolean_type_node) { - parse_error_context - (wfl_operator, - "Incompatible type for loop conditional. Can't convert `%s' to `boolean'", + parse_error_context + (wfl_operator, + "Incompatible type for loop conditional. Can't convert `%s' to `boolean'", lang_printable_name (TREE_TYPE (expression), 0)); return error_mark_node; } /* Now we know things are allright, invert the condition, fold and return */ - TREE_OPERAND (node, 0) = + TREE_OPERAND (node, 0) = fold (build1 (TRUTH_NOT_EXPR, boolean_type_node, expression)); if (! integer_zerop (TREE_OPERAND (node, 0)) @@ -15111,8 +15149,7 @@ patch_exit_expr (node) /* 14.9 Switch statement */ static tree -patch_switch_statement (node) - tree node; +patch_switch_statement (tree node) { tree se = TREE_OPERAND (node, 0), se_type; tree save, iter; @@ -15157,8 +15194,8 @@ patch_switch_statement (node) = EXPR_WFL_LINECOL (TREE_PURPOSE (iter)); /* The case_label_list is in reverse order, so print the outer label first. */ - parse_error_context (wfl_operator, "duplicate case label: `%d'", - subval); + parse_error_context (wfl_operator, "duplicate case label: `" + HOST_WIDE_INT_PRINT_DEC "'", subval); EXPR_WFL_LINECOL (wfl_operator) = EXPR_WFL_LINECOL (TREE_PURPOSE (subiter)); parse_error_context (wfl_operator, "original label is here"); @@ -15179,20 +15216,95 @@ patch_switch_statement (node) TREE_TYPE (node) = void_type_node; TREE_SIDE_EFFECTS (node) = 1; CAN_COMPLETE_NORMALLY (node) - = CAN_COMPLETE_NORMALLY (TREE_OPERAND (node, 1)) + = CAN_COMPLETE_NORMALLY (TREE_OPERAND (node, 1)) || ! SWITCH_HAS_DEFAULT (node); return node; } +/* Assertions. */ + +/* Build an assertion expression for `assert CONDITION : VALUE'; VALUE + might be NULL_TREE. */ +static tree +build_assertion (int location, tree condition, tree value) +{ + tree node; + tree klass = GET_CPC (); + + if (! CLASS_USES_ASSERTIONS (klass)) + { + tree field, classdollar, id, call; + tree class_type = TREE_TYPE (klass); + + field = add_field (class_type, + get_identifier ("$assertionsDisabled"), + boolean_type_node, + ACC_PRIVATE | ACC_STATIC | ACC_FINAL); + MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (field); + FIELD_SYNTHETIC (field) = 1; + + if (!TYPE_DOT_CLASS (class_type)) + build_dot_class_method (class_type); + classdollar = build_dot_class_method_invocation (class_type); + + /* Call CLASS.desiredAssertionStatus(). */ + id = build_wfl_node (get_identifier ("desiredAssertionStatus")); + call = build (CALL_EXPR, NULL_TREE, id, NULL_TREE, NULL_TREE); + call = make_qualified_primary (classdollar, call, location); + TREE_SIDE_EFFECTS (call) = 1; + + /* Invert to obtain !CLASS.desiredAssertionStatus(). This may + seem odd, but we do it to generate code identical to that of + the JDK. */ + call = build1 (TRUTH_NOT_EXPR, NULL_TREE, call); + TREE_SIDE_EFFECTS (call) = 1; + DECL_INITIAL (field) = call; + + /* Record the initializer in the initializer statement list. */ + call = build (MODIFY_EXPR, NULL_TREE, field, call); + TREE_CHAIN (call) = CPC_STATIC_INITIALIZER_STMT (ctxp); + SET_CPC_STATIC_INITIALIZER_STMT (ctxp, call); + MODIFY_EXPR_FROM_INITIALIZATION_P (call) = 1; + + CLASS_USES_ASSERTIONS (klass) = 1; + } + + if (value != NULL_TREE) + value = tree_cons (NULL_TREE, value, NULL_TREE); + + node = build_wfl_node (get_identifier ("java")); + node = make_qualified_name (node, build_wfl_node (get_identifier ("lang")), + location); + node = make_qualified_name (node, build_wfl_node (get_identifier ("AssertionError")), + location); + + node = build (NEW_CLASS_EXPR, NULL_TREE, node, value, NULL_TREE); + TREE_SIDE_EFFECTS (node) = 1; + /* It is too early to use BUILD_THROW. */ + node = build1 (THROW_EXPR, NULL_TREE, node); + TREE_SIDE_EFFECTS (node) = 1; + + /* We invert the condition; if we just put NODE as the `else' part + then we generate weird-looking bytecode. */ + condition = build1 (TRUTH_NOT_EXPR, NULL_TREE, condition); + /* Check $assertionsDisabled. */ + condition + = build (TRUTH_ANDIF_EXPR, NULL_TREE, + build1 (TRUTH_NOT_EXPR, NULL_TREE, + build_wfl_node (get_identifier ("$assertionsDisabled"))), + condition); + node = build_if_else_statement (location, condition, node, NULL_TREE); + return node; +} + /* 14.18 The try/catch statements */ /* Encapsulate TRY_STMTS' in a try catch sequence. The catch clause catches TYPE and executes CATCH_STMTS. */ static tree -encapsulate_with_try_catch (location, type, try_stmts, catch_stmts) - int location; - tree type, try_stmts, catch_stmts; +encapsulate_with_try_catch (int location, tree type, tree try_stmts, + tree catch_stmts) { tree try_block, catch_clause_param, catch_block, catch; @@ -15200,11 +15312,11 @@ encapsulate_with_try_catch (location, type, try_stmts, catch_stmts) try_block = build_expr_block (try_stmts, NULL_TREE); /* Build a catch block: we need a catch clause parameter */ - catch_clause_param = build_decl (VAR_DECL, + catch_clause_param = build_decl (VAR_DECL, wpv_id, build_pointer_type (type)); /* And a block */ catch_block = build_expr_block (NULL_TREE, catch_clause_param); - + /* Initialize the variable and store in the block */ catch = build (MODIFY_EXPR, NULL_TREE, catch_clause_param, build (JAVA_EXC_OBJ_EXPR, ptr_type_node)); @@ -15220,9 +15332,7 @@ encapsulate_with_try_catch (location, type, try_stmts, catch_stmts) } static tree -build_try_statement (location, try_block, catches) - int location; - tree try_block, catches; +build_try_statement (int location, tree try_block, tree catches) { tree node = build (TRY_EXPR, NULL_TREE, try_block, catches); EXPR_WFL_LINECOL (node) = location; @@ -15230,9 +15340,7 @@ build_try_statement (location, try_block, catches) } static tree -build_try_finally_statement (location, try_block, finally) - int location; - tree try_block, finally; +build_try_finally_statement (int location, tree try_block, tree finally) { tree node = build (TRY_FINALLY_EXPR, NULL_TREE, try_block, finally); EXPR_WFL_LINECOL (node) = location; @@ -15240,8 +15348,7 @@ build_try_finally_statement (location, try_block, finally) } static tree -patch_try_statement (node) - tree node; +patch_try_statement (tree node) { int error_found = 0; tree try = TREE_OPERAND (node, 0); @@ -15275,7 +15382,7 @@ patch_try_statement (node) only parameter of the clause statement in of class Throwable or a subclass of Throwable, but that was done earlier. The catch clause parameter type has also been resolved. */ - + /* Just make sure that the catch clause parameter type inherits from java.lang.Throwable */ if (!inherits_from_p (carg_type, throwable_type_node)) @@ -15287,7 +15394,7 @@ patch_try_statement (node) error_found = 1; continue; } - + /* Partial check for unreachable catch statement: The catch clause is reachable iff is no earlier catch block A in the try statement such that the type of the catch @@ -15304,7 +15411,7 @@ patch_try_statement (node) if (inherits_from_p (carg_type, TREE_TYPE (TREE_TYPE (decl)))) { EXPR_WFL_LINECOL (wfl_operator) = EXPR_WFL_LINECOL (current); - parse_error_context + parse_error_context (wfl_operator, "`catch' not reached because of the catch clause at line %d", EXPR_WFL_LINENO (sub_current)); @@ -15340,7 +15447,7 @@ patch_try_statement (node) POP_EXCEPTIONS (); /* Verification ends here */ - if (error_found) + if (error_found) return error_mark_node; TREE_OPERAND (node, 0) = try; @@ -15352,8 +15459,7 @@ patch_try_statement (node) /* 14.17 The synchronized Statement */ static tree -patch_synchronized_statement (node, wfl_op1) - tree node, wfl_op1; +patch_synchronized_statement (tree node, tree wfl_op1) { tree expr = java_complete_tree (TREE_OPERAND (node, 0)); tree block = TREE_OPERAND (node, 1); @@ -15391,7 +15497,7 @@ patch_synchronized_statement (node, wfl_op1) that the handler that catches all throw exception calls _Jv_MonitorExit and then rethrow the exception. The synchronized statement is then implemented as: - TRY + TRY { _Jv_MonitorEnter (expression) synchronized_block @@ -15422,8 +15528,7 @@ patch_synchronized_statement (node, wfl_op1) /* 14.16 The throw Statement */ static tree -patch_throw_statement (node, wfl_op1) - tree node, wfl_op1; +patch_throw_statement (tree node, tree wfl_op1) { tree expr = TREE_OPERAND (node, 0); tree type = TREE_TYPE (expr); @@ -15453,17 +15558,17 @@ patch_throw_statement (node, wfl_op1) is explicitly declared in the `throws' clause of each constructor. This doesn't apply to anonymous classes, since they don't have declared constructors. */ - if (!unchecked_ok + if (!unchecked_ok && DECL_INSTINIT_P (current_function_decl) && !ANONYMOUS_CLASS_P (current_class)) { tree current; - for (current = TYPE_METHODS (current_class); current; + for (current = TYPE_METHODS (current_class); current; current = TREE_CHAIN (current)) - if (DECL_CONSTRUCTOR_P (current) + if (DECL_CONSTRUCTOR_P (current) && !check_thrown_exceptions_do (TREE_TYPE (expr))) { - parse_error_context (wfl_operator, "Checked exception `%s' can't be thrown in instance initializer (not all declared constructor are declaring it in their `throws' clause)", + parse_error_context (wfl_operator, "Checked exception `%s' can't be thrown in instance initializer (not all declared constructor are declaring it in their `throws' clause)", lang_printable_name (TREE_TYPE (expr), 0)); return error_mark_node; } @@ -15492,7 +15597,7 @@ patch_throw_statement (node, wfl_op1) /* We report that the exception can't be throw from a try block in all circumstances but when the `throw' is inside a static block. */ - else if (!EXCEPTIONS_P (currently_caught_type_list) + else if (!EXCEPTIONS_P (currently_caught_type_list) && !tryblock_throws_ok) { if (DECL_CLINIT_P (current_function_decl)) @@ -15501,13 +15606,13 @@ patch_throw_statement (node, wfl_op1) lang_printable_name (type, 0)); else parse_error_context (wfl_operator, - "Checked exception `%s' isn't thrown from a `try' block", + "Checked exception `%s' isn't thrown from a `try' block", lang_printable_name (type, 0)); } /* Otherwise, the current method doesn't have the appropriate throws declaration */ else - parse_error_context (wfl_operator, "Checked exception `%s' doesn't match any of current method's `throws' declaration(s)", + parse_error_context (wfl_operator, "Checked exception `%s' doesn't match any of current method's `throws' declaration(s)", lang_printable_name (type, 0)); return error_mark_node; } @@ -15525,14 +15630,12 @@ patch_throw_statement (node, wfl_op1) effectively caught from where DECL is invoked. */ static void -check_thrown_exceptions (location, decl) - int location; - tree decl; +check_thrown_exceptions (int location, tree decl) { tree throws; /* For all the unchecked exceptions thrown by DECL */ - for (throws = DECL_FUNCTION_THROWS (decl); throws; - throws = TREE_CHAIN (throws)) + for (throws = DECL_FUNCTION_THROWS (decl); throws; + throws = TREE_CHAIN (throws)) if (!check_thrown_exceptions_do (TREE_VALUE (throws))) { #if 1 @@ -15545,10 +15648,10 @@ check_thrown_exceptions (location, decl) parse_error_context (wfl_operator, "Exception `%s' can't be thrown in initializer", lang_printable_name (TREE_VALUE (throws), 0)); - else + else { - parse_error_context - (wfl_operator, "Exception `%s' must be caught, or it must be declared in the `throws' clause of `%s'", + parse_error_context + (wfl_operator, "Exception `%s' must be caught, or it must be declared in the `throws' clause of `%s'", lang_printable_name (TREE_VALUE (throws), 0), (DECL_INIT_P (current_function_decl) ? IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (current_class))) : @@ -15562,8 +15665,7 @@ check_thrown_exceptions (location, decl) current method. */ static int -check_thrown_exceptions_do (exception) - tree exception; +check_thrown_exceptions_do (tree exception) { tree list = currently_caught_type_list; resolve_and_layout (exception, NULL_TREE); @@ -15583,8 +15685,7 @@ check_thrown_exceptions_do (exception) } static void -purge_unchecked_exceptions (mdecl) - tree mdecl; +purge_unchecked_exceptions (tree mdecl) { tree throws = DECL_FUNCTION_THROWS (mdecl); tree new = NULL_TREE; @@ -15609,8 +15710,7 @@ purge_unchecked_exceptions (mdecl) otherwise. */ static bool -ctors_unchecked_throws_clause_p (class_type) - tree class_type; +ctors_unchecked_throws_clause_p (tree class_type) { tree current; @@ -15638,8 +15738,7 @@ ctors_unchecked_throws_clause_p (class_type) /* 15.24 Conditional Operator ?: */ static tree -patch_conditional_expr (node, wfl_cond, wfl_op1) - tree node, wfl_cond, wfl_op1; +patch_conditional_expr (tree node, tree wfl_cond, tree wfl_op1) { tree cond = TREE_OPERAND (node, 0); tree op1 = TREE_OPERAND (node, 1); @@ -15671,7 +15770,7 @@ patch_conditional_expr (node, wfl_cond, wfl_op1) /* Second and third can be numeric, boolean (i.e. primitive), references or null. Anything else results in an error */ if (!((JNUMERIC_TYPE_P (t1) && JNUMERIC_TYPE_P (t2)) - || ((JREFERENCE_TYPE_P (t1) || op1 == null_pointer_node) + || ((JREFERENCE_TYPE_P (t1) || op1 == null_pointer_node) && (JREFERENCE_TYPE_P (t2) || op2 == null_pointer_node)) || (t1 == boolean_type_node && t2 == boolean_type_node))) error_found = 1; @@ -15703,9 +15802,9 @@ patch_conditional_expr (node, wfl_cond, wfl_op1) /* Otherwise, binary numeric promotion is applied and the resulting type is the promoted type of operand 1 and 2 */ - else - resulting_type = binary_numeric_promotion (t1, t2, - &TREE_OPERAND (node, 1), + else + resulting_type = binary_numeric_promotion (t1, t2, + &TREE_OPERAND (node, 1), &TREE_OPERAND (node, 2)); } @@ -15752,8 +15851,7 @@ patch_conditional_expr (node, wfl_cond, wfl_op1) /* Wrap EXPR with code to initialize DECL's class, if appropriate. */ static tree -maybe_build_class_init_for_field (decl, expr) - tree decl, expr; +maybe_build_class_init_for_field (tree decl, tree expr) { tree clas = DECL_CONTEXT (decl); if (flag_emit_class_files || flag_emit_xref) @@ -15777,17 +15875,17 @@ maybe_build_class_init_for_field (decl, expr) CONTEXT is a static final VAR_DECL whose initializer we are folding. */ static tree -fold_constant_for_init (node, context) - tree node; - tree context; +fold_constant_for_init (tree node, tree context) { tree op0, op1, val; enum tree_code code = TREE_CODE (node); switch (code) { - case STRING_CST: case INTEGER_CST: + if (node == null_pointer_node) + return NULL_TREE; + case STRING_CST: case REAL_CST: return node; @@ -15804,7 +15902,7 @@ fold_constant_for_init (node, context) case BIT_IOR_EXPR: case TRUTH_ANDIF_EXPR: case TRUTH_ORIF_EXPR: - case EQ_EXPR: + case EQ_EXPR: case NE_EXPR: case GT_EXPR: case GE_EXPR: @@ -15860,6 +15958,8 @@ fold_constant_for_init (node, context) /* Guard against infinite recursion. */ DECL_INITIAL (node) = NULL_TREE; val = fold_constant_for_init (val, node); + if (val != NULL_TREE && TREE_CODE (val) != STRING_CST) + val = try_builtin_assignconv (NULL_TREE, TREE_TYPE (node), val); DECL_INITIAL (node) = val; return val; @@ -15875,7 +15975,7 @@ fold_constant_for_init (node, context) else if (! QUALIFIED_P (name)) { decl = lookup_field_wrapper (DECL_CONTEXT (context), name); - if (decl == NULL_TREE + if (decl == NULL_TREE || (! FIELD_STATIC (decl) && ! FIELD_FINAL (decl))) return NULL_TREE; return fold_constant_for_init (decl, decl); @@ -15922,59 +16022,22 @@ fold_constant_for_init (node, context) 'M' for MethodName, 'E' for ExpressionName, and 'A' for AmbiguousName. */ tree -resolve_simple_name (name, context) - tree name; - int context; +resolve_simple_name (tree name, int context) { } tree -resolve_qualified_name (name, context) - tree name; - int context; +resolve_qualified_name (tree name, int context) { } #endif -/* Mark P, which is really a `struct parser_ctxt **' for GC. */ - -static void -mark_parser_ctxt (p) - void *p; -{ - struct parser_ctxt *pc = *((struct parser_ctxt **) p); - int i; - - if (!pc) - return; - -#ifndef JC1_LITE - for (i = 0; i < 11; ++i) - ggc_mark_tree (pc->modifier_ctx[i]); - ggc_mark_tree (pc->class_type); - ggc_mark_tree (pc->function_decl); - ggc_mark_tree (pc->package); - ggc_mark_tree (pc->class_list); - ggc_mark_tree (pc->current_parsed_class); - ggc_mark_tree (pc->current_parsed_class_un); - ggc_mark_tree (pc->non_static_initialized); - ggc_mark_tree (pc->static_initialized); - ggc_mark_tree (pc->instance_initializers); - ggc_mark_tree (pc->import_list); - ggc_mark_tree (pc->import_demand_list); - ggc_mark_tree (pc->current_loop); - ggc_mark_tree (pc->current_labeled_block); -#endif /* JC1_LITE */ - - if (pc->next) - mark_parser_ctxt (&pc->next); -} - void -init_src_parse () +init_src_parse (void) { - /* Register roots with the garbage collector. */ - ggc_add_tree_root (src_parse_roots, sizeof (src_parse_roots) / sizeof(tree)); + /* Sanity check; we've been bit by this before. */ + if (ARRAY_SIZE (ctxp->modifier_ctx) != MODIFIER_TK - PUBLIC_TK) + abort (); } @@ -15984,16 +16047,17 @@ init_src_parse () /* Attach to PTR (a block) the declaration found in ENTRY. */ -static bool -attach_init_test_initialization_flags (entry, ptr) - struct hash_entry *entry; - PTR ptr; +static int +attach_init_test_initialization_flags (void **entry, void *ptr) { tree block = (tree)ptr; - struct init_test_hash_entry *ite = (struct init_test_hash_entry *) entry; - - TREE_CHAIN (ite->init_test_decl) = BLOCK_EXPR_DECLS (block); - BLOCK_EXPR_DECLS (block) = ite->init_test_decl; + struct treetreehash_entry *ite = (struct treetreehash_entry *) *entry; + + if (block != error_mark_node) + { + TREE_CHAIN (ite->value) = BLOCK_EXPR_DECLS (block); + BLOCK_EXPR_DECLS (block) = ite->value; + } return true; } @@ -16003,31 +16067,30 @@ attach_init_test_initialization_flags (entry, ptr) initialized static class flags if a flag already existed, otherwise a new one is created. */ -static bool -emit_test_initialization (entry, info) - struct hash_entry *entry; - PTR info; +static int +emit_test_initialization (void **entry_p, void *info) { tree l = (tree) info; tree decl, init; - - struct init_test_hash_entry *ite = (struct init_test_hash_entry *) - hash_lookup (&DECL_FUNCTION_INIT_TEST_TABLE (current_function_decl), - entry->key, - current_function_decl != TREE_PURPOSE (l), NULL); + tree key = (tree) *entry_p; + tree *ite; + htab_t cf_ht = DECL_FUNCTION_INIT_TEST_TABLE (current_function_decl); /* If we haven't found a flag and we're dealing with self registered with current_function_decl, then don't do anything. Self is always added as definitely initialized but this information is valid only if used outside the current function. */ - if (! ite) + if (current_function_decl == TREE_PURPOSE (l) + && java_treetreehash_find (cf_ht, key) == NULL) return true; + ite = java_treetreehash_new (cf_ht, key); + /* If we don't have a variable, create one and install it. */ - if (! ite->init_test_decl) + if (*ite == NULL) { tree block; - + decl = build_decl (VAR_DECL, NULL_TREE, boolean_type_node); MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (decl); LOCAL_CLASS_INITIALIZATION_FLAG (decl) = 1; @@ -16038,10 +16101,10 @@ emit_test_initialization (entry, info) block = BLOCK_SUBBLOCKS (GET_CURRENT_BLOCK (current_function_decl)); TREE_CHAIN (decl) = BLOCK_EXPR_DECLS (block); BLOCK_EXPR_DECLS (block) = decl; - ite->init_test_decl = decl; + *ite = decl; } else - decl = ite->init_test_decl; + decl = *ite; /* Now simply augment the compound that holds all the assignments pertaining to this method invocation. */ @@ -16052,3 +16115,6 @@ emit_test_initialization (entry, info) return true; } + +#include "gt-java-parse.h" +#include "gtype-java.h"