/* 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.
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.
%{
#include "config.h"
#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
#include <dirent.h>
#include "tree.h"
#include "rtl.h"
+#include "real.h"
#include "obstack.h"
#include "toplev.h"
#include "flags.h"
#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;
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,
#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]
#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)); \
%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
%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
%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
%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
%type <node> 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 <node> class_body_declaration class_member_declaration
static_initializer constructor_declaration block
%type <node> class_body_declarations constructor_header
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 <node> return_statement break_statement continue_statement
-%type <operator> ASSIGN_TK MULT_ASSIGN_TK DIV_ASSIGN_TK
+%type <operator> ASSIGN_TK MULT_ASSIGN_TK DIV_ASSIGN_TK
%type <operator> REM_ASSIGN_TK PLUS_ASSIGN_TK MINUS_ASSIGN_TK
%type <operator> LS_ASSIGN_TK SRS_ASSIGN_TK ZRS_ASSIGN_TK
%type <operator> AND_ASSIGN_TK XOR_ASSIGN_TK OR_ASSIGN_TK
%type <operator> ASSIGN_ANY_TK assignment_operator
-%token <operator> EQ_TK GTE_TK ZRS_TK SRS_TK GT_TK LTE_TK LS_TK
+%token <operator> EQ_TK GTE_TK ZRS_TK SRS_TK GT_TK LTE_TK LS_TK
%token <operator> BOOL_AND_TK AND_TK BOOL_OR_TK OR_TK INCR_TK PLUS_TK
%token <operator> DECR_TK MINUS_TK MULT_TK DIV_TK XOR_TK REM_TK NEQ_TK
%token <operator> NEG_TK REL_QM_TK REL_CL_TK NOT_TK LT_TK OCB_TK CCB_TK
%token <operator> OP_TK OSB_TK DOT_TK THROW_TK INSTANCEOF_TK
-%type <operator> THIS_TK SUPER_TK RETURN_TK BREAK_TK CONTINUE_TK
+%type <operator> THIS_TK SUPER_TK RETURN_TK BREAK_TK CONTINUE_TK
%type <operator> CASE_TK DEFAULT_TK TRY_TK CATCH_TK SYNCHRONIZED_TK
-%type <operator> NEW_TK
+%type <operator> NEW_TK ASSERT_TK
+
+%type <node> method_body
-%type <node> method_body
-
%type <node> literal INT_LIT_TK FP_LIT_TK BOOL_LIT_TK CHAR_LIT_TK
STRING_LIT_TK NULL_TK VOID_TK
%type <node> formal_parameter_list formal_parameter
method_declarator method_header
-%type <node> primitive_type reference_type type
+%type <node> primitive_type reference_type type
BOOLEAN_TK INTEGRAL_TK FP_TK
/* Added or modified JDK 1.1 rule types */
%%
/* 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
{}
;
array_type:
primitive_type dims
- {
+ {
int osb = pop_current_osb (ctxp);
tree t = build_java_array_type (($1), -1);
while (--osb)
$$ = t;
}
| name dims
- {
+ {
int osb = pop_current_osb (ctxp);
tree t = $1;
while (osb--)
package_declaration:
PACKAGE_TK name SC_TK
- {
+ {
ctxp->package = EXPR_WFL_NODE ($2);
register_package (ctxp->package);
}
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);
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));
}
{
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
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:
| 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));
}
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 ();
}
{ 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);
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
| 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
/* 19.8.3 Productions from 8.4: Method Declarations */
method_declaration:
- method_header
+ method_header
{
current_function_decl = $1;
if (current_function_decl
{YYNOT_TWICE yyerror ("'{' expected"); RECOVER;}
;
-method_header:
+method_header:
type method_declarator throws
{ $$ = method_header (0, $1, $2, $3); }
| VOID_TK method_declarator throws
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");
method_declarator:
identifier OP_TK CP_TK
- {
+ {
ctxp->formal_parameter_number = 0;
$$ = method_declarator ($1, NULL_TREE);
}
| 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
$$ = build_tree_list ($2, $1);
}
| final type variable_declarator_id /* Added, JDK1.1 final parms */
- {
+ {
$$ = build_tree_list ($3, $2);
ARG_FINAL_P ($$) = 1;
}
/* 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 ())));
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
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;
}
/* 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, $$);
}
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));
}
abstract_method_declaration:
method_header SC_TK
- {
+ {
check_abstract_method_header ($1);
current_function_decl = NULL_TREE; /* FIXME ? */
}
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
/* 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; }
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;
| 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);
}
| 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;
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 ($$);
{
/* 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);
{yyerror ("';' expected"); RECOVER;}
;
-statement_expression:
+statement_expression:
assignment
| pre_increment_expression
| pre_decrement_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
enter_block ();
}
switch_block
- {
+ {
/* Make into "proper list" of COMPOUND_EXPRs.
I.e. make the last statement also have its own
COMPOUND_EXPR. */
switch_expression:
SWITCH_TK OP_TK expression CP_TK
- {
+ {
$$ = build (SWITCH_EXPR, NULL_TREE, $3, NULL_TREE);
EXPR_WFL_LINECOL ($$) = $2.location;
}
{ $$ = NULL_TREE; }
;
-switch_block_statement_groups:
+switch_block_statement_groups:
switch_block_statement_group
| switch_block_statement_groups switch_block_statement_group
;
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);
while_expression:
WHILE_TK OP_TK expression CP_TK
- {
+ {
tree body = build_loop_body ($2.location, $3, 0);
$$ = build_new_loop (body);
}
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); }
;
$$ = 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
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);}
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);
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;
throw_statement:
THROW_TK expression SC_TK
- {
+ {
$$ = build1 (THROW_EXPR, NULL_TREE, $2);
EXPR_WFL_LINECOL ($$) = $1.location;
}
{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
"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);
}
;
| 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);
}
catches:
catch_clause
| catches catch_clause
- {
+ {
TREE_CHAIN ($2) = $1;
$$ = $2;
}
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),
}
| 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 () */
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;}
| 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);
}
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;}
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);
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
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);
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
{
$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
dim_expr:
OSB_TK expression CSB_TK
- {
+ {
if (JNUMERIC_TYPE_P (TREE_TYPE ($2)))
{
$2 = build_wfl_node ($2);
}
;
-dims:
+dims:
OSB_TK CSB_TK
- {
+ {
int allocate = 0;
/* If not initialized, allocate memory for the osb
numbers stack */
/* 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;
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
{
| 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
{
}
}
| 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
{
}
}
| 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
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--)
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;}
| 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;}
| 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;}
| 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); }
| 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;}
| 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;}
| 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;}
| 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;}
| 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;}
| 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;}
`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;
}
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;
}
/* 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;
next = ctxp->next;
if (next)
{
- lineno = ctxp->lineno;
+ input_line = ctxp->lineno;
current_class = ctxp->class_type;
}
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. */
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)
{
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;
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)
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 = "<inner buffer context>";
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 */
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
linked. */
static void
-java_parser_context_push_initialized_field ()
+java_parser_context_push_initialized_field (void)
{
tree node;
or <clinit> 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 ());
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)
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);
}
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);
{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)
fprintf (stderr, "lineno: %d\n", copy->lineno);
TAB_CONTEXT (tab);
fprintf (stderr, "package: %s\n",
- (copy->package ?
+ (copy->package ?
IDENTIFIER_POINTER (copy->package) : "<none>"));
TAB_CONTEXT (tab);
fprintf (stderr, "context for saving: %d\n", copy->saved_data_ctx);
debugger. */
void
-java_debug_context ()
+java_debug_context (void)
{
java_debug_context_do (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");
}
/* 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++;
static int do_warning = 0;
void
-yyerror (msg)
- const char *msg;
+yyerror (const char *msg)
{
static java_lc elc;
static int prev_lineno;
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
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)
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];
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 */
/* 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)
{
case LOOP_EXPR:
node = TREE_OPERAND (node, 0);
continue;
-
+
case LABELED_BLOCK_EXPR:
node = TREE_OPERAND (node, 1);
continue;
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");
/* 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 */
}
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 ? ", " : ""),
}
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;}
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;
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);
}
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);
}
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)
{
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;
}
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",
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 */
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:
&& (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));
}
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;
}
{
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));
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;
}
}
}
- 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
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;
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;
{
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;
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;
/* 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)));
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)
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;
{
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);
/* A NULL qual and a decl means that the search ended
successfully?!? We have to do something then. FIXME */
-
+
if (decl)
enclosing = decl;
else
/* 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);
}
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;
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)
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);
/* 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 ()
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);
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 ();
- 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));
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);
}
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;
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;
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 ())
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
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)
}
/* 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;
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)
}
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;
{
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);
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
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
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))
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;
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;
}
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));
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;
/* 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;
/* 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));
/* 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
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)
{
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;
}
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
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,
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;
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;
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);
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,
/* FIXME */
static tree
-build_instinit_invocation (class_type)
- tree class_type;
+build_instinit_invocation (tree class_type)
{
tree to_return = NULL_TREE;
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;
return error_mark_node;
meth = TREE_VALUE (mdecl);
id = TREE_PURPOSE (mdecl);
-
+
check_modifiers_consistency (flags);
if (GET_CPC ())
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))
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)
{
/* 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
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
/* 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));
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 */
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 */
/* 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.
{
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;
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++;
}
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)
/* 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;
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"),
{
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);
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;
/* 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));
/* 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;
}
/* 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;
/* 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)));
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);
this$<n> 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);
list = tree_cons (build_wfl_node (thisn), build_pointer_type (type),
list);
}
-
+
for (current = list; current; current = TREE_CHAIN (current))
{
int must_chain = 0;
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;
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;
}
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)
{
qualification from the current package definition. */
static tree
-parser_qualified_classname (name)
- tree name;
+parser_qualified_classname (tree name)
{
tree nested_class_name;
if (ctxp->package)
return merge_qualified_name (ctxp->package, name);
- else
+ else
return 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),
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"),
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))));
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)
registered again. */
static tree
-obtain_incomplete_type (type_name)
- tree type_name;
+obtain_incomplete_type (tree type_name)
{
tree ptr = NULL_TREE, 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;
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);
&& 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 ();
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;
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 */
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;
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);
}
void
-java_check_circular_reference ()
+java_check_circular_reference (void)
{
tree current;
for (current = ctxp->class_list; current; current = TREE_CHAIN (current))
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;
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)
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,
}
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);
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;
int i = 0, artificial = 0;
tree decl, ctor_name;
char buffer [80];
-
+
/* The constructor name is <init> unless we're dealing with an
anonymous class, in which case the name will be fixed after having
be expanded. */
/* 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);
}
}
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;
}
compilation triggered this one to be simply loaded. */
void
-java_fix_constructors ()
+java_fix_constructors (void)
{
tree current;
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;
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))
/* Complete unsatisfied class declaration and their dependencies */
void
-java_complete_class ()
+java_complete_class (void)
{
tree cclass;
jdeplist *cclassd;
/* 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;
/* 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;
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))));
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))));
}
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;
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);
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--)
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 */
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;
/* 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)
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;
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;
/* 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);
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;
}
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;
/* 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;
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))));
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;
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;
<init> */
static const char *
-get_printable_method_name (decl)
- tree decl;
+get_printable_method_name (tree decl)
{
const char *to_return;
tree name = NULL_TREE;
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;
}
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;
&& 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));
/* 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;
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)
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)
}
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"),
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;
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);
/* 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;
java_check_abstract_methods (class_decl);
else
java_check_regular_methods (class_decl);
-
+
CLASS_METHOD_CHECKED_P (TREE_TYPE (class_decl)) = 1;
}
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;
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);
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);
/* 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))
{
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);
}
/* 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"),
/* 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),
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;
}
/* Inheriting multiple methods with the same signature. FIXME */
}
-
+
if (!TYPE_NVIRTUALS (class))
TYPE_METHODS (class) = nreverse (TYPE_METHODS (class));
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;
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)))));
}
}
/* 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;
{
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;
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)))));
}
}
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;
{
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;
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));
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;
}
/* 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;
/* Process all single-type import. */
static int
-process_imports ()
+process_imports (void)
{
tree import;
int error_found;
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;
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
error_found = 1;
}
- obstack_free (&temporary_obstack, original_name);
+ free (original_name);
if (error_found)
return 1;
}
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)
{
}
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)
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);
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,
*filename->ptr++ = '/';
for (;;)
{
- int len;
+ int len;
const char *d_name;
struct dirent *direntp = readdir (dirp);
if (!direntp)
/* 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) :
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;
/* 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
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))
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));
}
}
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. */
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;
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))
/* 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);
{
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))
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;
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));
/* 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;
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;
}
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)
{
build_debugable_stmt (EXPR_WFL_LINECOL (init),
init));
}
-
+
/* Setup dependency the type of the decl */
if (must_chain)
{
/* 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;
{
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))
/* 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);
}
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,
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;
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
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
/* 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);
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;
}
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;
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;
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;
}
}
+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));
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;
}
classes */
void
-java_layout_classes ()
+java_layout_classes (void)
{
tree current;
int save_error_count = java_error_count;
generation. */
static void
-java_complete_expand_classes ()
+java_complete_expand_classes (void)
{
tree current;
classes, if any. */
static void
-java_complete_expand_class (outer)
- tree outer;
+java_complete_expand_class (tree outer)
{
tree inner_list;
constructors and then <clinit>. */
static void
-java_complete_expand_methods (class_decl)
- tree class_decl;
+java_complete_expand_methods (tree class_decl)
{
tree clinit, decl, first_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. */
/* 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)))
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;
}
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));
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;
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;
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));
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))
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 <clinit> */
is empty. Return 1 if <clinit> 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;
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;
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)
{
expansion of mdecl's body. */
static void
-start_complete_expand_method (mdecl)
- tree mdecl;
+start_complete_expand_method (tree mdecl)
{
tree tem;
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
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);
}
/* 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;
/* 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;
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
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
/* 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))
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. */
/* 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);
}
}
- /* Prepare the function for RTL expansion */
+ /* Prepare the function for RTL expansion */
start_complete_expand_method (decl);
/* Expand function start, generate initialization flag
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)));
&& (!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
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)))
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;
/* 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;
}
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);
}
}
/* Construct the expression that calls an access method:
- <type>.access$<n>(<arg1> [, <arg2>]);
+ <type>.access$<n>(<arg1> [, <arg2>]);
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);
}
static tree
-build_new_access_id ()
+build_new_access_id (void)
{
static int access_n_counter = 1;
char buffer [128];
*/
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 ();
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;
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;
/* 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;
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;
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
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);
the enclosing instance of an inner class. The enclosing instance is
kept in a generated field called this$<n>, with <n> being the
inner class nesting level (starting from 0.) */
-
+
/* Build an access to a given this$<n>, always chaining access call to
others. Access methods to this$<n> are build on the fly if
necessary. This CAN'T be used to solely access this$<n-1> from
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)
{
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;
/* Build an access function to the this$<n> 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;
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);
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;
}
if (i == saved_i)
return saved_thisn;
-
+
sprintf (buffer, "this$%d", i);
saved_i = i;
saved_thisn = get_identifier (buffer);
form used is `this.this$<n> = this$<n>;'. */
static tree
-build_thisn_assign ()
+build_thisn_assign (void)
{
if (current_class && PURE_INNER_CLASS_TYPE_P (current_class))
{
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;
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 */
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));
}
static tree
-build_dot_class_method_invocation (type)
- tree type;
+build_dot_class_method_invocation (tree type)
{
tree sig_id, s;
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));
necessary. */
static void
-fix_constructors (mdecl)
- tree mdecl;
+fix_constructors (tree mdecl)
{
tree iii; /* Instance Initializer Invocation */
tree body = DECL_FUNCTION_BODY (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$<n> hidden field, if
necessary */
if ((thisn_assign = build_thisn_assign ()))
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))
{
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. */
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);
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;
/* 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;
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;
}
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;
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);
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;
/* 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)
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);
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));
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;
/* 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;
return decl;
/* 15.13.1: NAME can appear within a class declaration */
- else
+ else
{
decl = lookup_field_wrapper (current_class, name);
if (decl)
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. */
/* 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))));
}
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;
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);
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;
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;
}
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)
{
/* 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;
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;}
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;
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))
{
*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;
}
*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 ? "" :
RESTORE_THIS_AND_CURRENT_CLASS;
/* EH check. No check on access$<n> 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);
{
if (!current_this)
{
- parse_error_context
+ parse_error_context
(wfl, "Keyword `this' used outside allowed context");
return 1;
}
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;
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);
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);
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)),
else
parse_error_context
(qual_wfl, "Undefined variable or class name: `%s'",
- IDENTIFIER_POINTER (EXPR_WFL_NODE (qual_wfl)));
+ IDENTIFIER_POINTER (name));
return 1;
}
}
/* 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'",
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),
from_type = 1;
}
/* We resolve an expression name */
- else
+ else
{
tree field_decl = NULL_TREE;
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));
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;
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;
}
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);
/* 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;
}
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);
/* Access always granted for members declared public */
if (access_flag & ACC_PUBLIC)
return 0;
-
+
/* Check access on protected members */
if (access_flag & ACC_PROTECTED)
{
/* 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",
/* 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)))));
}
/* 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)));
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;
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;
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);
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,
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);
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);
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 ();
}
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;
}
{
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)) ==
{
is_super_init = 1;
if (CLASSTYPE_SUPER (current_class))
- class_to_search =
+ class_to_search =
DECL_NAME (TYPE_NAME (CLASSTYPE_SUPER (current_class)));
else
{
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 ();
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 ();
&& 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 ? "" :
x(a1,...,an) into TYPE_OF(this$<n>).x(a1,....an)
2) We're generating bytecodes:
-
+
- LIST is non static. It's invocation is transformed from
x(a1,....,an) into access$<n>(this$<n>,a1,...,an).
- LIST is static. It's invocation is transformed from
x(a1,....,an) into TYPE_OF(this$<n>).x(a1,....an).
Of course, this$<n> 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. */
/* 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)
}
/* 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
/* 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);
}
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))
{
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 */
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;
}
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);
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
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);
}
}
*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. */
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;
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))
func = method;
else
{
- tree signature = build_java_signature (TREE_TYPE (method));
switch (invocation_mode (method, CALL_USING_SUPER (patch)))
{
case INVOKE_VIRTUAL:
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:
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
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);
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;
}
{
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);
}
static int
-invocation_mode (method, super)
- tree method;
- int super;
+invocation_mode (tree method, int super)
{
int access = get_access_flags_from_decl (method);
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;
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. */
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)))),
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))
{
}
/* 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++)
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);
}
/* 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
{
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);
}
{
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;
}
/* 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))
{
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
/* 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;
/* 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);
}
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)
/* 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;
{
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);
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));
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);
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);
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)))
{
- 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 &&
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
{
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;
}
}
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;
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)
breakdown_qualified (&pkg1, &tmp, name1);
breakdown_qualified (&pkg2, &tmp, name2);
-
+
return (pkg1 == pkg2);
}
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)
{
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;
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
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));
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;
}
/* 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);
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));
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);
}
else
TREE_TYPE (node) = TREE_TYPE (EXPR_WFL_NODE (node));
-
+
}
break;
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)
{
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;
}
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);
/* 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)))
{
{
/* 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 */
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,
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);
}
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);
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:
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);
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;
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)
{
}
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;
function block chain */
static tree
-enter_block ()
+enter_block (void)
{
tree b = build_expr_block (NULL_TREE, NULL_TREE);
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;
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)
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);
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;
}
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));
}
}
/* 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 */
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;
/* 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);
/* 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;
/* 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;
/* 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
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, "<overflow>");
-
+
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));
/* 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;
{
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;
{
lhs_type = TREE_TYPE (lvalue);
}
- else
+ else
{
parse_error_context (wfl_op1, "Invalid left hand side of assignment");
error_found = 1;
/* 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))
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 ("<tmp>"),
+ 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;
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);
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);
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 */
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)
/* 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))
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)
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))
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)))
{
/* 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))
/* 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;
}
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);
}
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)
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))
/* 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;
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))
{
/* 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)
&& 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++)
/* 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;
/* 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;
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);
error situation, unless it's too early to tell (in case we're
handling a `+', `==', `!=' or `instanceof'.) We want to set op<n>_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;
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);
&& ! 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. */
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)
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));
}
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;
}
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;
{
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 */
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;
/* 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)
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;
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;
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);
}
/* 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;
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)
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;
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)))
NULL. */
static tree
-patch_string (node)
- tree node;
+patch_string (tree node)
{
if (node == error_mark_node)
return error_mark_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)
/* 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;
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
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;
/* 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;
/* 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;
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. */
}
/* 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);
}
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);
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
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. */
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);
}
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);
}
}
break;
}
-
+
if (error_found)
return error_mark_node;
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);
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);
}
/* 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);
/* 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);
/* 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;
/* 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);
/* 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));
/* 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);
/* 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));
(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);
}
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,
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;
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;
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;
}
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;
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);
"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;
}
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);
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;
}
static tree
-patch_return (node)
- tree node;
+patch_return (tree node)
{
tree return_exp = TREE_OPERAND (node, 0);
tree meth = current_function_decl;
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;
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");
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;
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);
/* 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)
}
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
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))
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;
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'",
/* 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;
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;
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
<structure described above> */
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;
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);
}
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);
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;
}
LABELED_BLOCK_EXPR's block. */
static tree
-search_loop (statement)
- tree statement;
+search_loop (tree statement)
{
if (TREE_CODE (statement) == LOOP_EXPR)
return 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;
insert LOOP as its body. */
static tree
-patch_loop_statement (loop)
- tree loop;
+patch_loop_statement (tree loop)
{
tree loop_label;
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
}
/* 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;
/* 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)
{
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;
}
}
else if (!bc_label)
- {
+ {
for (;; labeled_block = TREE_CHAIN (labeled_block))
{
if (labeled_block == NULL_TREE)
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;
/* 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))
/* 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;
= 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");
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;
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));
}
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;
}
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;
}
static tree
-patch_try_statement (node)
- tree node;
+patch_try_statement (tree node)
{
int error_found = 0;
tree try = TREE_OPERAND (node, 0);
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))
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
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));
POP_EXCEPTIONS ();
/* Verification ends here */
- if (error_found)
+ if (error_found)
return error_mark_node;
TREE_OPERAND (node, 0) = try;
/* 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);
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
/* 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);
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;
}
/* 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))
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;
}
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
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))) :
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);
}
static void
-purge_unchecked_exceptions (mdecl)
- tree mdecl;
+purge_unchecked_exceptions (tree mdecl)
{
tree throws = DECL_FUNCTION_THROWS (mdecl);
tree new = NULL_TREE;
otherwise. */
static bool
-ctors_unchecked_throws_clause_p (class_type)
- tree class_type;
+ctors_unchecked_throws_clause_p (tree class_type)
{
tree current;
/* 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);
/* 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;
/* 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));
}
/* 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)
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;
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:
/* 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;
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);
'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 ();
}
\f
/* 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;
}
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;
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. */
return true;
}
+
+#include "gt-java-parse.h"
+#include "gtype-java.h"