From: apbianco Date: Tue, 10 Nov 1998 18:04:25 +0000 (+0000) Subject: Tue Nov 10 12:34:03 1998 Alexandre Petit-Bianco X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=23b7f2e1831e8923b44a0f3a4093adb35f2ac257;p=platform%2Fupstream%2Flinaro-gcc.git Tue Nov 10 12:34:03 1998 Alexandre Petit-Bianco * class.c (is_compiled_class): Call safe_layout_class for class compiled from source. * conver.h (convert_to_integer, convert_to_real, convert_to_pointer): Added prototypes. * decl.c (init_decl_processing): Non longer push the decls of `methodtable', `constants', `Class', `Field', `dispatchTable' `jexception' and `Method'. * expr.c (build_invokeinterface): New function. (expand_invoke): static variable CLASS_IDENT now in build_invokeinterface. Use build_invokeinterface. (expand_java_field_op): Moved code to inline java.lang.PRIMTYPE.TYPE into a function. (build_primtype_type_ref): New function. * java-tree.def (INSTANCEOF_EXPR): New tree code. * java-tree.h (CLASS_METHOD_CHECKED_P, METHOD_DEPRECATED, FIELD_DEPRECATED, CLASS_DEPRECATED): New flag macros. (DECL_CONSTRUCTOR_P): Fixed typo in comment. (DECL_LOCAL_STATIC_VALUE): New macro. (build_invokeinterface, build_primtype_type_ref): New function prototypes. (java_parse_abort_on_error): Macro rewritten. * jcf-parse.c (current_method): Add comment to declaration. (parse_zip_file_entries, process_zip_dir, void parse_source_file): Function prototypes fixed. (jcf_parse_source): push/pop parser context. save/restore global. (parse_source_file): Fixed leading comment. Now take a IDENTIFIER_NODE as an argument. Doesn't check methods, layout classes and pop the parser context anymore. (yyparse): Push parser context, save globals, parse the source file, restore globals and pop the parser context when processing a source file. * jcf.h (VERBOSE_SKELETON): Replaces SOURCE_FRONTEND_DEBUG define. * lex.c (java_parse_doc_section): New function. (java_lex): Call java_parse_doc_section when appropriate. Build an operator around INSTANCEOF_TK. * lex.h (java_lineterminator, java_sprint_unicode, java_unicode_2_utf8, java_lex_error, java_store_unicode): Prototypes rewritten. (java_parse_escape_sequence, java_letter_or_digit_p, java_parse_doc_section, java_parse_end_comment, java_get_unicode, java_read_unicode, java_store_unicode, java_read_char, java_allocate_new_line, java_unget_unicode, java_sneak_unicode): Added function prototypes. * parse.h (VERBOSE_SKELETON): Replaces SOURCE_FRONTEND_DEBUG define. (JNULLP_TYPE_P, CHECK_METHODS, CHECK_DEPRECATED, REGISTER_IMPORT): New macros (struct parser_ctxt): New fields: deprecated, current_parsed_class_un, gclass_list. (fix_method_argument_names, issue_warning_error_from_context, resolve_package, lookup_package_type): New function prototypes. (resolve_expression_name): Fixed function prototype. (find_applicable_accessible_methods_list): Fixed indentation, added extra argument in prototype. (check_final_assignment, build_null_of_type, check_deprecation, check_method_redefinition, reset_method_name, java_check_regular_methods, java_check_abstract_methods, maybe_build_primttype_type_ref): New function prototype. * parse.y (conver.h): Include. (INSTANCEOF_TK): Tagged . (single_type_import_declaration): Use REGISTER_IMPORT macro. (relational_expression:): Build binop for instanceof. (java_push_parser_context): Remember ctxp->gclass_list across contexts. (java_pop_parser_context): Simply return if no context exists. Remember gclass_list across contexts. (issue_warning_error_from_context): New function. (parse_error_context): Don't setup ctxp->elc here. Call issue_warning_error_from_context instead. (parse_warning_context): Likewise. (maybe_create_class_interface_decl): Removed DECL_ARTIFICIAL setup. Link new class/interface to ctxp->gclass_list. (add_superinterfaces): Register interface as incomplete if not loaded. (create_class): Remember class unqualified name in ctxp->current_parsed_class_un. Check class deprecation. (register_fields): Check field deprecation. Remember static final field value in DECL_LOCAL_STATIC_VALUE. Changed comment in part processing INIT. (method_header): New local variable ORIG_ARG. Use unqualified current class name for check on constructor errors. Promote return type if of record type. Argument list fix moved in fix_method_argument_names, called here. Check method deprecation. (fix_method_argument_names): New function. (method_declarator): Promote record typed arguments. (safe_layout_class): Check class methods before layout. (java_complete_class): Compute field layout when patched. (do_resolve_class): Try to load class after having it renamed after the package name. (get_printable_method_name): Use DECL_CONTEXT. (reset_method_name): New function. (check_method_redefinition): Use reset_method_name. (java_check_regular_methods): New local variable SAVED_FOUND_WFL. Temporarily reinstall overriding/hiding method names for error report. Check for compile-time error when method found has default (package) access. (java_check_abstract_methods): Now takes an interface DECL node as an argument. Also reinstall real name on unchecked overriding/hiding methods for error report. (java_check_methods): Fixed leading comment. Get classes to verify from ctxp->gclass_list. Use CHECK_METHODS macro and set CLASS_METHOD_CHECKED_P on class verification. (lookup_java_method2): Get real method name if necessary. (find_in_imports): Don't check package class access here. (resolve_package, lookup_package_type): New functions. (java_layout_classes): Fixed leading comment. Take classes to be laid out from ctxp->gclass_list. (java_complete_expand_methods): Don't expand native and abstract methods. (java_expand_classes): New function. (resolve_expression_name): Use additional argument ORIG. Retrieve values of static final field of primitive types. (resolve_field_access): Handles static final field of promotive type. (resolve_qualified_expression_name): Handle STRING_CST as primaries and package name resolution. Check deprecation on found decls. Set where_found and type_found on non static field resolved during qualification. Layout non primitive field decl types. (check_deprecation): New function. (maybe_access_field): Simplified. (patch_method_invocation_stmt): Local variable CLASS_TYPE removed. Reverse method's argument when primary is a type. Don't use CLASS_TYPE to report problems, use IDENTIFIER_WFL instead. Include abstract class in the list of class searchable for constructors. Use DECL_CONTEXT of found method for access checks. Check method deprecation. (patch_invoke): Pay extra care to NEW_CLASS_EXPR type call when converting arguments. Handle INVOKE_INTERFACE. (lookup_method_invoke): Search constructor using existing infrastructure (don't rely on lookup_java_constructor anymore). (find_applicable_accessible_methods_list): Extra argument flag LC. Now include constructor in the search. (qualify_ambiguous_name): Conditional expression are primaries. (not_initialized_as_it_should_p): static final are always initialized. (java_complete_tree): Pass extra NULL argument to resolve_expression_name. Stricter test to carry on patching assignments. New case for INSTANCEOF_EXPR. (complete_function_arguments): Inline PRIMTYPE.TYPE read access. (check_final_assignment, maybe_build_primttype_type_ref): New functions. (patch_assignment): Detect resolved static finals and carry normal assignment error check on them. Inline PRIMTYPE.TYPE read access. (try_builtin_assignconv): Access constant 0 on all primitive types. (valid_builtin_assignconv_identity_widening_p): Accept identical types. Accept all promoted type on int type. (valid_ref_assignconv_cast_p): Accept a null pointer to be assigned to a reference. (valid_method_invocation_conversion_p): Accept to check null pointers. (build_binop): Merge declaration and initialization of local variable BINOP. (patch_binop): New case for INSTANCEOF_EXPR. NE_EXPR to accept all numeric types. Improved validity test for qualify operators on references. (patch_unaryop): Broadened rejection test for PREDECREMENT_EXPR and PREINCREMENT_EXPR. Also detect resolved static finals of a primitive type and issue the appropriate error message. (resolve_type_during_patch): Mark class loaded when resolved. (patch_cast): Allow null to be cased to reference types. (build_null_of_type): New function. (patch_array_ref): Handle array on references correctly. (patch_return): Removed unused local variable MODIFY. Force boolean to be returned as integers. Allows null to be returned by a function returning a reference. * typeck.c (convert_to_integer, convert_to_real, convert_to_pointer): Prototypes moved to convert.h (lookup_argument_method): Use method real name, if necessary. This improves method checking, gets rid of a cross file type dependency bug and does a more robust job at laying out classes when necessary. It unifies the regular methods and constructors lookup. It implements the `instanceof' operator and interface method invocations. It also fixes random bugs. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@23599 138bc75d-0d04-0410-961f-82ee72b054a4 --- diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog index c19f23f..c225fdf 100644 --- a/gcc/java/ChangeLog +++ b/gcc/java/ChangeLog @@ -1,3 +1,175 @@ +Tue Nov 10 12:34:03 1998 Alexandre Petit-Bianco + + * class.c (is_compiled_class): Call safe_layout_class for class + compiled from source. + * conver.h (convert_to_integer, convert_to_real, + convert_to_pointer): Added prototypes. + * decl.c (init_decl_processing): Non longer push the decls of + `methodtable', `constants', `Class', `Field', `dispatchTable' + `jexception' and `Method'. + * expr.c (build_invokeinterface): New function. + (expand_invoke): static variable CLASS_IDENT now in + build_invokeinterface. Use build_invokeinterface. + (expand_java_field_op): Moved code to inline + java.lang.PRIMTYPE.TYPE into a function. + (build_primtype_type_ref): New function. + * java-tree.def (INSTANCEOF_EXPR): New tree code. + * java-tree.h (CLASS_METHOD_CHECKED_P, METHOD_DEPRECATED, + FIELD_DEPRECATED, CLASS_DEPRECATED): New flag macros. + (DECL_CONSTRUCTOR_P): Fixed typo in comment. + (DECL_LOCAL_STATIC_VALUE): New macro. + (build_invokeinterface, build_primtype_type_ref): New function + prototypes. + (java_parse_abort_on_error): Macro rewritten. + * jcf-parse.c (current_method): Add comment to declaration. + (parse_zip_file_entries, process_zip_dir, void parse_source_file): + Function prototypes fixed. + (jcf_parse_source): push/pop parser context. save/restore global. + (parse_source_file): Fixed leading comment. Now take a + IDENTIFIER_NODE as an argument. Doesn't check methods, layout + classes and pop the parser context anymore. + (yyparse): Push parser context, save globals, parse the source + file, restore globals and pop the parser context when processing a + source file. + * jcf.h (VERBOSE_SKELETON): Replaces SOURCE_FRONTEND_DEBUG define. + * lex.c (java_parse_doc_section): New function. + (java_lex): Call java_parse_doc_section when appropriate. Build an + operator around INSTANCEOF_TK. + * lex.h (java_lineterminator, java_sprint_unicode, + java_unicode_2_utf8, java_lex_error, java_store_unicode): + Prototypes rewritten. + (java_parse_escape_sequence, java_letter_or_digit_p, + java_parse_doc_section, java_parse_end_comment, java_get_unicode, + java_read_unicode, java_store_unicode, java_read_char, + java_allocate_new_line, java_unget_unicode, java_sneak_unicode): + Added function prototypes. + * parse.h (VERBOSE_SKELETON): Replaces SOURCE_FRONTEND_DEBUG + define. + (JNULLP_TYPE_P, CHECK_METHODS, CHECK_DEPRECATED, REGISTER_IMPORT): + New macros + (struct parser_ctxt): New fields: deprecated, + current_parsed_class_un, gclass_list. + (fix_method_argument_names, issue_warning_error_from_context, + resolve_package, lookup_package_type): New function prototypes. + (resolve_expression_name): Fixed function prototype. + (find_applicable_accessible_methods_list): Fixed indentation, added + extra argument in prototype. + (check_final_assignment, build_null_of_type, check_deprecation, + check_method_redefinition, reset_method_name, + java_check_regular_methods, java_check_abstract_methods, + maybe_build_primttype_type_ref): New function prototype. + * parse.y (conver.h): Include. + (INSTANCEOF_TK): Tagged . + (single_type_import_declaration): Use REGISTER_IMPORT macro. + (relational_expression:): Build binop for instanceof. + (java_push_parser_context): Remember ctxp->gclass_list across + contexts. + (java_pop_parser_context): Simply return if no context + exists. Remember gclass_list across contexts. + (issue_warning_error_from_context): New function. + (parse_error_context): Don't setup ctxp->elc here. Call + issue_warning_error_from_context instead. + (parse_warning_context): Likewise. + (maybe_create_class_interface_decl): Removed DECL_ARTIFICIAL + setup. Link new class/interface to ctxp->gclass_list. + (add_superinterfaces): Register interface as incomplete if not + loaded. + (create_class): Remember class unqualified name in + ctxp->current_parsed_class_un. Check class deprecation. + (register_fields): Check field deprecation. Remember static final + field value in DECL_LOCAL_STATIC_VALUE. Changed comment in part + processing INIT. + (method_header): New local variable ORIG_ARG. Use unqualified + current class name for check on constructor errors. Promote return + type if of record type. Argument list fix moved in + fix_method_argument_names, called here. Check method deprecation. + (fix_method_argument_names): New function. + (method_declarator): Promote record typed arguments. + (safe_layout_class): Check class methods before layout. + (java_complete_class): Compute field layout when patched. + (do_resolve_class): Try to load class after having it renamed + after the package name. + (get_printable_method_name): Use DECL_CONTEXT. + (reset_method_name): New function. + (check_method_redefinition): Use reset_method_name. + (java_check_regular_methods): New local variable + SAVED_FOUND_WFL. Temporarily reinstall overriding/hiding method + names for error report. Check for compile-time error when method + found has default (package) access. + (java_check_abstract_methods): Now takes an interface DECL node as + an argument. Also reinstall real name on unchecked + overriding/hiding methods for error report. + (java_check_methods): Fixed leading comment. Get classes to verify + from ctxp->gclass_list. Use CHECK_METHODS macro and set + CLASS_METHOD_CHECKED_P on class verification. + (lookup_java_method2): Get real method name if necessary. + (find_in_imports): Don't check package class access here. + (resolve_package, lookup_package_type): New functions. + (java_layout_classes): Fixed leading comment. Take classes to be + laid out from ctxp->gclass_list. + (java_complete_expand_methods): Don't expand native and abstract + methods. + (java_expand_classes): New function. + (resolve_expression_name): Use additional argument ORIG. Retrieve + values of static final field of primitive types. + (resolve_field_access): Handles static final field of promotive + type. + (resolve_qualified_expression_name): Handle STRING_CST as + primaries and package name resolution. Check deprecation on found + decls. Set where_found and type_found on non static field resolved + during qualification. Layout non primitive field decl types. + (check_deprecation): New function. + (maybe_access_field): Simplified. + (patch_method_invocation_stmt): Local variable CLASS_TYPE + removed. Reverse method's argument when primary is a type. Don't + use CLASS_TYPE to report problems, use IDENTIFIER_WFL + instead. Include abstract class in the list of class searchable + for constructors. Use DECL_CONTEXT of found method for access + checks. Check method deprecation. + (patch_invoke): Pay extra care to NEW_CLASS_EXPR type call when + converting arguments. Handle INVOKE_INTERFACE. + (lookup_method_invoke): Search constructor using existing + infrastructure (don't rely on lookup_java_constructor anymore). + (find_applicable_accessible_methods_list): Extra argument flag + LC. Now include constructor in the search. + (qualify_ambiguous_name): Conditional expression are primaries. + (not_initialized_as_it_should_p): static final are always + initialized. + (java_complete_tree): Pass extra NULL argument to + resolve_expression_name. Stricter test to carry on patching + assignments. New case for INSTANCEOF_EXPR. + (complete_function_arguments): Inline PRIMTYPE.TYPE read access. + (check_final_assignment, maybe_build_primttype_type_ref): New + functions. + (patch_assignment): Detect resolved static finals and carry normal + assignment error check on them. Inline PRIMTYPE.TYPE read access. + (try_builtin_assignconv): Access constant 0 on all primitive + types. + (valid_builtin_assignconv_identity_widening_p): Accept identical + types. Accept all promoted type on int type. + (valid_ref_assignconv_cast_p): Accept a null pointer to be + assigned to a reference. + (valid_method_invocation_conversion_p): Accept to check null + pointers. + (build_binop): Merge declaration and initialization of local + variable BINOP. + (patch_binop): New case for INSTANCEOF_EXPR. NE_EXPR to accept all + numeric types. Improved validity test for qualify operators on + references. + (patch_unaryop): Broadened rejection test for PREDECREMENT_EXPR + and PREINCREMENT_EXPR. Also detect resolved static finals of a + primitive type and issue the appropriate error message. + (resolve_type_during_patch): Mark class loaded when resolved. + (patch_cast): Allow null to be cased to reference types. + (build_null_of_type): New function. + (patch_array_ref): Handle array on references correctly. + (patch_return): Removed unused local variable MODIFY. Force + boolean to be returned as integers. Allows null to be returned by + a function returning a reference. + * typeck.c (convert_to_integer, convert_to_real, + convert_to_pointer): Prototypes moved to convert.h + (lookup_argument_method): Use method real name, if necessary. + 1998-10-30 Tom Tromey * class.c (build_class_ref): Changed name of primitive classes to diff --git a/gcc/java/class.c b/gcc/java/class.c index 4a2d8fa..47e9f5c 100644 --- a/gcc/java/class.c +++ b/gcc/java/class.c @@ -1153,7 +1153,12 @@ is_compiled_class (class) if (flag_assume_compiled) { if (!CLASS_LOADED_P (class)) - load_class (class, 1); + { + if (CLASS_FROM_SOURCE_P (class)) + safe_layout_class (class); + else + load_class (class, 1); + } return 1; } diff --git a/gcc/java/convert.h b/gcc/java/convert.h index 1e1373e..a627bc2 100644 --- a/gcc/java/convert.h +++ b/gcc/java/convert.h @@ -1,3 +1,4 @@ + /* Definition of conversion functions. Copyright (C) 1993 Free Software Foundation, Inc. @@ -22,3 +23,6 @@ Boston, MA 02111-1307, USA. */ extern tree convert_to_boolean PROTO ((tree, tree)); extern tree convert_to_char PROTO ((tree, tree)); +extern tree convert_to_integer PROTO ((tree type, tree expr)); +extern tree convert_to_real PROTO ((tree type, tree expr)); +extern tree convert_to_pointer PROTO ((tree type, tree expr)); diff --git a/gcc/java/decl.c b/gcc/java/decl.c index 6c44d15..0831a37 100644 --- a/gcc/java/decl.c +++ b/gcc/java/decl.c @@ -527,8 +527,7 @@ init_decl_processing () methodtable_type = make_node (RECORD_TYPE); layout_type (methodtable_type); - pushdecl (build_decl (TYPE_DECL, get_identifier ("methodtable"), - methodtable_type)); + build_decl (TYPE_DECL, get_identifier ("methodtable"), methodtable_type); methodtable_ptr_type = build_pointer_type (methodtable_type); TYPE_identifier_node = get_identifier ("TYPE"); @@ -554,8 +553,7 @@ init_decl_processing () PUSH_FIELD (constants_type_node, field, "tags", ptr_type_node); PUSH_FIELD (constants_type_node, field, "data", ptr_type_node); FINISH_RECORD (constants_type_node); - pushdecl (build_decl (TYPE_DECL, get_identifier ("constants"), - constants_type_node)); + build_decl (TYPE_DECL, get_identifier ("constants"), constants_type_node); access_flags_type_node = unsigned_short_type_node; @@ -606,7 +604,7 @@ init_decl_processing () FIELD_PRIVATE (t) = 1; push_super_field (class_type_node, object_type_node); FINISH_RECORD (class_type_node); - pushdecl (build_decl (TYPE_DECL, get_identifier ("Class"), class_type_node)); + build_decl (TYPE_DECL, get_identifier ("Class"), class_type_node); field_info_union_node = make_node (UNION_TYPE); PUSH_FIELD (field_info_union_node, field, "boffset", int_type_node); @@ -623,7 +621,7 @@ init_decl_processing () PUSH_FIELD (field_type_node, field, "info", field_info_union_node); FINISH_RECORD (field_type_node); CLASS_LOADED_P (field_type_node) = 1; - pushdecl (build_decl (TYPE_DECL, get_identifier ("Field"), field_type_node)); + build_decl (TYPE_DECL, get_identifier ("Field"), field_type_node); one_elt_array_domain_type = build_index_type (integer_one_node); nativecode_ptr_array_type_node @@ -632,7 +630,7 @@ init_decl_processing () PUSH_FIELD (dtable_type, field, "class", class_ptr_type); PUSH_FIELD (dtable_type, field, "methods", nativecode_ptr_array_type_node); FINISH_RECORD (dtable_type); - pushdecl (build_decl (TYPE_DECL, get_identifier ("dispatchTable"), dtable_type)); + build_decl (TYPE_DECL, get_identifier ("dispatchTable"), dtable_type); #define jint_type int_type_node #define jint_ptr_type ptr_type_node @@ -643,7 +641,7 @@ init_decl_processing () PUSH_FIELD (jexception_type, field, "handler_pc", ptr_type_node); PUSH_FIELD (jexception_type, field, "catch_type", class_ptr_type); FINISH_RECORD (jexception_type); - pushdecl (build_decl (TYPE_DECL, get_identifier ("jexception"), field_type_node)); + build_decl (TYPE_DECL, get_identifier ("jexception"), field_type_node); jexception_ptr_type = build_pointer_type (jexception_type); lineNumberEntry_type = make_node (RECORD_TYPE); @@ -665,7 +663,7 @@ init_decl_processing () PUSH_FIELD (method_type_node, field, "ncode", nativecode_ptr_type_node); FINISH_RECORD (method_type_node); CLASS_LOADED_P (method_type_node) = 1; - pushdecl (build_decl (TYPE_DECL, get_identifier ("Method"), method_type_node)); + build_decl (TYPE_DECL, get_identifier ("Method"), method_type_node); t = tree_cons (NULL_TREE, class_ptr_type, build_tree_list (NULL_TREE, int_type_node)); diff --git a/gcc/java/expr.c b/gcc/java/expr.c index 5759b6b..37c5122 100644 --- a/gcc/java/expr.c +++ b/gcc/java/expr.c @@ -1431,6 +1431,32 @@ build_invokevirtual (dtable, method) return func; } +tree +build_invokeinterface (dtable, method_name, method_signature) + tree dtable, method_name, method_signature; +{ + static tree class_ident = NULL_TREE; + tree lookup_arg; + + /* We expand invokeinterface here. _Jv_LookupInterfaceMethod() will + ensure that the selected method exists, is public and not + abstract nor static. */ + + if (class_ident == NULL_TREE) + class_ident = get_identifier ("class"); + + dtable = build1 (INDIRECT_REF, dtable_type, dtable); + dtable = build (COMPONENT_REF, class_ptr_type, dtable, + lookup_field (&dtable_type, class_ident)); + lookup_arg = build_tree_list (NULL_TREE, build_utf8_ref (method_signature)); + lookup_arg = tree_cons (NULL_TREE, dtable, + tree_cons (NULL_TREE, build_utf8_ref (method_name), + lookup_arg)); + return build (CALL_EXPR, ptr_type_node, + build_address_of (soft_lookupinterfacemethod_node), + lookup_arg, NULL_TREE); +} + /* Expand one of the invoke_* opcodes. OCPODE is the specific opcode. METHOD_REF_INDEX is an index into the constant pool. @@ -1449,8 +1475,6 @@ expand_invoke (opcode, method_ref_index, nargs) char *self_name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (self_type))); tree call, func, method, arg_list, method_type; - static tree class_ident = NULL_TREE; - if (! CLASS_LOADED_P (self_type)) { load_class (self_type, 1); @@ -1522,30 +1546,7 @@ expand_invoke (opcode, method_ref_index, nargs) if (opcode == OPCODE_invokevirtual) func = build_invokevirtual (dtable, method); else - { - /* We expand invokeinterface here. - _Jv_LookupInterfaceMethod() will ensure that the selected - method exists, is public and not abstract nor static. */ - - tree lookup_arg; - - if (class_ident == NULL_TREE) - class_ident = get_identifier ("class"); - - dtable = build1 (INDIRECT_REF, dtable_type, dtable); - dtable = build (COMPONENT_REF, class_ptr_type, dtable, - lookup_field (&dtable_type, class_ident)); - lookup_arg = build_tree_list (NULL_TREE, - build_utf8_ref (method_signature)); - lookup_arg = tree_cons (NULL_TREE, dtable, - tree_cons (NULL_TREE, - build_utf8_ref (method_name), - lookup_arg)); - func = build (CALL_EXPR, - ptr_type_node, - build_address_of (soft_lookupinterfacemethod_node), - lookup_arg, NULL_TREE); - } + func = build_invokeinterface (dtable, method_name, method_signature); } func = build1 (NOP_EXPR, build_pointer_type (method_type), func); call = build (CALL_EXPR, TREE_TYPE (method_type), func, arg_list, NULL_TREE); @@ -1615,29 +1616,10 @@ expand_java_field_op (is_static, is_putting, field_ref_index) && field_type == class_ptr_type && strncmp (self_name, "java.lang.", 10) == 0) { - char *class_name = self_name+10; - tree typ; - if (strcmp(class_name, "Byte") == 0) - typ = byte_type_node; - else if (strcmp(class_name, "Short") == 0) - typ = short_type_node; - else if (strcmp(class_name, "Integer") == 0) - typ = int_type_node; - else if (strcmp(class_name, "Long") == 0) - typ = long_type_node; - else if (strcmp(class_name, "Float") == 0) - typ = float_type_node; - else if (strcmp(class_name, "Boolean") == 0) - typ = boolean_type_node; - else if (strcmp(class_name, "Char") == 0) - typ = char_type_node; - else if (strcmp(class_name, "Void") == 0) - typ = void_type_node; - else - typ = NULL_TREE; - if (typ != NULL_TREE) + tree typ = build_primtype_type_ref (self_name); + if (typ) { - push_value (build_class_ref (typ)); + push_value (typ); return; } } @@ -1672,6 +1654,36 @@ expand_java_field_op (is_static, is_putting, field_ref_index) push_value (field_ref); } +tree +build_primtype_type_ref (self_name) + char *self_name; +{ + char *class_name = self_name+10; + tree typ; + if (strncmp(class_name, "Byte", 4) == 0) + typ = byte_type_node; + else if (strncmp(class_name, "Short", 5) == 0) + typ = short_type_node; + else if (strncmp(class_name, "Integer", 7) == 0) + typ = int_type_node; + else if (strncmp(class_name, "Long", 4) == 0) + typ = long_type_node; + else if (strncmp(class_name, "Float", 5) == 0) + typ = float_type_node; + else if (strncmp(class_name, "Boolean", 7) == 0) + typ = boolean_type_node; + else if (strncmp(class_name, "Char", 4) == 0) + typ = char_type_node; + else if (strncmp(class_name, "Void", 4) == 0) + typ = void_type_node; + else + typ = NULL_TREE; + if (typ != NULL_TREE) + return build_class_ref (typ); + else + return NULL_TREE; +} + void load_type_state (label) tree label; diff --git a/gcc/java/java-tree.def b/gcc/java/java-tree.def index 5bd63c4..b367066 100644 --- a/gcc/java/java-tree.def +++ b/gcc/java/java-tree.def @@ -70,3 +70,10 @@ DEFTREECODE (THROW_EXPR, "throw", '1', 1) Operand 1 is the then-value Operand 2 is the else-value. */ DEFTREECODE (CONDITIONAL_EXPR, "?:", 'e', 3) + +/* instanceof operator. + Operand 0 is the expression that is getting tested + Operand 1 is the class used for the test. */ +DEFTREECODE (INSTANCEOF_EXPR, "instanceof", 'e', 2) + + diff --git a/gcc/java/java-tree.h b/gcc/java/java-tree.h index 711e441..d80c6c9 100644 --- a/gcc/java/java-tree.h +++ b/gcc/java/java-tree.h @@ -56,6 +56,7 @@ struct JCF; IS_CRAFTED_STRING_BUFFER_P (in CALL_EXPR) Usage of TYPE_LANG_FLAG_?: + 0: CLASS_METHOD_CHECKED_P (in RECORD_TYPE) 1: TYPE_ARRAY_P (in RECORD_TYPE). 2: CLASS_LOADED_P (in RECORD_TYPE). 3: CLASS_FROM_SOURCE_P (in RECORD_TYPE). @@ -64,6 +65,9 @@ struct JCF; 6: CLASS_HAS_FINIT_P (in RECORD_TYPE) Usage of DECL_LANG_FLAG_?: + 0: METHOD_DEPRECATED (in FUNCTION_DECL). + FIELD_DEPRECATED (in FIELD_DECL). + CLASS_DEPRECATED (in TYPE_DECL). 1: METHOD_PUBLIC (in FUNCTION_DECL). FIELD_PUBLIC (in FIELD_DECL). CLASS_PUBLIC (in TYPE_DECL). @@ -85,7 +89,7 @@ struct JCF; LABEL_CHANGED (in LABEL_DECL) CLASS_SUPER (in TYPE_DECL, ACC_SUPER flag) INITIALIZED_P (in FIELD_DECL, VAR_DECL, PARM_DECL) - 7: DECL_CONSTRUCTOR_P (in FUNCTION_DECL) + 7: DECL_CONSTRUCTOR_P (in FUNCTION_DECL). */ /* True if the class whose TYPE_BINFO this is has a superclass. @@ -396,6 +400,9 @@ struct lang_identifier slot_number in decl_map. */ #define DECL_LOCAL_SLOT_CHAIN(NODE) \ (((struct lang_decl_var*)DECL_LANG_SPECIFIC(NODE))->slot_chain) +/* For a static field seen from the parser, it holds its associated + value, the one returned when the field is looked up. */ +#define DECL_LOCAL_STATIC_VALUE(NODE) DECL_LOCAL_SLOT_CHAIN (NODE) /* DECL_LANG_SPECIFIC for FUNCTION_DECLs. */ struct lang_decl @@ -501,6 +508,7 @@ extern tree lookup_name PROTO ((tree)); extern tree build_known_method_ref PROTO ((tree, tree, tree, tree, tree)); extern tree build_class_init PROTO ((tree, tree)); extern tree build_invokevirtual PROTO ((tree, tree)); +extern tree build_invokeinterface PROTO ((tree, tree, tree)); extern tree invoke_build_dtable PROTO ((int, tree)); extern tree build_field_ref PROTO ((tree, tree, tree)); extern void pushdecl_force_head PROTO ((tree)); @@ -533,6 +541,7 @@ extern int alloc_name_constant PROTO ((int, tree)); extern void emit_register_classes PROTO (()); extern void lang_init_source PROTO ((int)); extern void write_classfile PROTO ((tree)); +extern tree build_primtype_type_ref PROTO ((char *)); /* Access flags etc for a method (a FUNCTION_DECL): */ @@ -570,6 +579,13 @@ extern void write_classfile PROTO ((tree)); #define CLASS_ABSTRACT(DECL) DECL_LANG_FLAG_5 (DECL) #define CLASS_SUPER(DECL) DECL_LANG_FLAG_6 (DECL) +/* @deprecated marker flag on methods, fields and classes */ + +#define METHOD_DEPRECATED(DECL) DECL_LANG_FLAG_0 (DECL) +#define FIELD_DEPRECATED(DECL) DECL_LANG_FLAG_0 (DECL) +#define CLASS_DEPRECATED(DECL) DECL_LANG_FLAG_0 (DECL) +#define DECL_DEPRECATED(DECL) DECL_LANG_FLAG_0 (DECL) + /* The number of virtual methods in this class's dispatch table. Does not include initial two dummy entries (one points to the Class object, and the other is for G++ -fvtable-thunks compatibility). */ @@ -657,6 +673,9 @@ extern tree *type_map; /* FIXME this use of TREE_TYPE conflicts with something or other. */ #define TYPE_ARRAY_ELEMENT(ATYPE) TREE_TYPE(ATYPE) +/* True if methods in class TYPE have been checked. */ +#define CLASS_METHOD_CHECKED_P(TYPE) TYPE_LANG_FLAG_0 (TYPE) + /* True if class TYPE has been loaded. */ #define CLASS_LOADED_P(TYPE) TYPE_LANG_FLAG_2 (TYPE) @@ -795,13 +814,12 @@ extern tree *type_map; /* Make the current function where this macro is invoked report error messages and and return, if any */ -#define java_parse_abort_on_error() \ - { \ - extern int java_error_count; \ - if (java_error_count) \ - { \ - java_report_errors (); \ - java_pop_parser_context (0); \ - return; \ - } \ +#define java_parse_abort_on_error() \ + { \ + extern int java_error_count; \ + if (java_error_count) \ + { \ + java_report_errors (); \ + return; \ + } \ } diff --git a/gcc/java/jcf-parse.c b/gcc/java/jcf-parse.c index 0761362..df4881d 100644 --- a/gcc/java/jcf-parse.c +++ b/gcc/java/jcf-parse.c @@ -64,15 +64,14 @@ tree main_class = NULL_TREE; /* The FIELD_DECL for the current field. */ static tree current_field = NULL_TREE; +/* The METHOD_DECL for the current method. */ static tree current_method = NULL_TREE; +/* Declarations of some functions used here. */ static tree give_name_to_class PROTO ((JCF *jcf, int index)); - -void parse_zip_file_entries (void); -void process_zip_dir(); - -/* Source file compilation declarations */ -static void parse_source_file (); +void parse_zip_file_entries PROTO (()); +void process_zip_dir PROTO (()); +static void parse_source_file PROTO ((tree)); /* Handle "SourceFile" attribute. */ @@ -506,14 +505,17 @@ int jcf_parse_source (jcf) JCF *jcf; { - tree filename = get_identifier (input_filename); - java_parser_context_save_global (); + tree file; + java_parser_context_save_global (); + java_push_parser_context (); input_filename = current_jcf->filename; + file = get_identifier (input_filename); if (!(finput = fopen (input_filename, "r"))) fatal ("input file `%s' just disappeared - jcf_parse_source", input_filename); - parse_source_file (IS_A_COMMAND_LINE_FILENAME_P (filename)); + parse_source_file (file); + java_pop_parser_context (IS_A_COMMAND_LINE_FILENAME_P (file)); java_parser_context_restore_global (); } @@ -658,22 +660,16 @@ parse_class_file () lineno = save_lineno; } -/* Parse a source file, as pointed by the current JCF. If PARSE_ONLY - is non zero, we're not parsing a file found on the command line and - we skip things related to code generation. */ +/* Parse a source file, as pointed by the current value of INPUT_FILENAME. */ static void -parse_source_file (parse_only) - int parse_only; +parse_source_file (file) + tree file; { - int remember_for_generation; - tree filename = get_identifier (input_filename); - /* Mark the file as parsed */ - HAS_BEEN_ALREADY_PARSED_P (filename) = 1; + HAS_BEEN_ALREADY_PARSED_P (file) = 1; lang_init_source (1); /* Error msgs have no method prototypes */ - java_push_parser_context (); java_init_lex (); /* Initialize the parser */ java_parse_abort_on_error (); java_parse (); /* Parse and build partial tree nodes. */ @@ -682,17 +678,6 @@ parse_source_file (parse_only) java_parse_abort_on_error (); java_check_circular_reference (); /* Check on circular references */ java_parse_abort_on_error (); - java_check_methods (); /* Check the methods */ - java_parse_abort_on_error (); - java_layout_classes (); - java_parse_abort_on_error (); - - /* If only parsing, make sure that the currently parsed file isn't - also present in the argument list. If it's the case, remember - that we should generate it. */ - remember_for_generation = !parse_only - || IS_A_COMMAND_LINE_FILENAME_P (filename); - java_pop_parser_context (remember_for_generation); } int @@ -775,7 +760,11 @@ yyparse () parse_class_file (); break; case JCF_SOURCE: - parse_source_file (0); /* Parse and generate */ + java_push_parser_context (); + java_parser_context_save_global (); + parse_source_file (name); + java_parser_context_restore_global (); + java_pop_parser_context (1); break; } } diff --git a/gcc/java/jcf-write.c b/gcc/java/jcf-write.c index bf0c16d..5d092c6 100644 --- a/gcc/java/jcf-write.c +++ b/gcc/java/jcf-write.c @@ -706,7 +706,6 @@ emit_iinc (var, value, state) static void emit_load_or_store (var, opcode, state) tree var; - int opcode; struct jcf_partial *state; { tree type = TREE_TYPE (var); diff --git a/gcc/java/jcf.h b/gcc/java/jcf.h index 3f98814..1b8aff2 100644 --- a/gcc/java/jcf.h +++ b/gcc/java/jcf.h @@ -248,7 +248,7 @@ extern int jcf_unexpected_eof PROTO ((JCF*, int)); /* Debug macros, for the front end */ extern int quiet_flag; -#ifdef SOURCE_FRONTEND_DEBUG +#ifdef VERBOSE_SKELETON #undef SOURCE_FRONTEND_DEBUG #define SOURCE_FRONTEND_DEBUG(X) \ {if (!quiet_flag) {printf ("* "); printf X; putchar ('\n');} } diff --git a/gcc/java/lang-options.h b/gcc/java/lang-options.h index 0f0f74b..4610193 100644 --- a/gcc/java/lang-options.h +++ b/gcc/java/lang-options.h @@ -22,11 +22,14 @@ Java and all Java-based marks are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries. The Free Software Foundation is independent of Sun Microsystems, Inc. */ -DEFINE_LANG_NAME ("Java") - /* This is the contribution to the `lang_options' array in gcc.c for java. */ +/* CYGNUS LOCAL - the format of this file has been changed to + allow cc1 to implement --help. nickc/--help */ + +DEFINE_LANG_NAME ("Java") + { "-fbounds-check", "" }, { "-fno-bounds-check", "Disable automatic array bounds checking" }, { "-fassume-compiled", "Make is_compiled_class return 1"}, diff --git a/gcc/java/lex.c b/gcc/java/lex.c index 504c841..0a632f1 100644 --- a/gcc/java/lex.c +++ b/gcc/java/lex.c @@ -368,6 +368,62 @@ java_parse_end_comment () } } +/* Parse the documentation section. Keywords must be at the beginning + of a documentation comment line (ignoring white space and any `*' + character). Parsed keyword(s): @DEPRECATED. */ + +static int +java_parse_doc_section (c) + unicode_t c; +{ + int valid_tag = 0, seen_star; + + while (JAVA_WHITE_SPACE_P (c) || (c == '*') || c == '\n') + { + switch (c) + { + case '*': + seen_star = 1; + break; + case '\n': /* ULT */ + valid_tag = 1; + break; + default: + seen_star = 0; + } + c = java_get_unicode(); + } + + if (c == UEOF) + java_lex_error ("Comment not terminated at end of input", 0); + + if (seen_star && (c == '/')) + return 1; /* Goto step1 in caller */ + + /* We're parsing @deprecated */ + if (valid_tag && (c == '@')) + { + char tag [10]; + int tag_index = 0; + + while (tag_index < 10 && c != UEOF && c != ' ' && c != '\n') + { + c = java_get_unicode (); + tag [tag_index++] = c; + } + + if (c == UEOF) + java_lex_error ("Comment not terminated at end of input", 0); + + java_unget_unicode (); + tag [tag_index] = '\0'; + + if (!strcmp (tag, "deprecated")) + ctxp->deprecated = 1; + } + return 0; +} + /* This function to be used only by JAVA_ID_CHAR_P (), otherwise it will return a wrong result. */ static int @@ -494,62 +550,8 @@ java_lex (java_lval) { if ((c = java_get_unicode ()) == '/') goto step1; /* Empy documentation comment */ - - else - /* Parsing the documentation section. We're looking - for the @depracated pseudo keyword. the @deprecated - tag must be at the beginning of a doc comment line - (ignoring white space and any * character) */ - - { - int valid_tag = 0, seen_star; - - while (JAVA_WHITE_SPACE_P (c) || (c == '*') || c == '\n') - { - switch (c) - { - case '*': - seen_star = 1; - break; - case '\n': /* ULT */ - valid_tag = 1; - break; - default: - seen_star = 0; - } - c = java_get_unicode(); - } - - if (c == UEOF) - java_lex_error - ("Comment not terminated at end of input", 0); - - if (seen_star && (c == '/')) - goto step1; /* End of documentation */ - - if (valid_tag && (c == '@')) - { - char deprecated [10]; - int deprecated_index = 0; - - for (deprecated_index = 0, c = java_get_unicode (); - deprecated_index < 10 && c != UEOF; - c = java_get_unicode ()) - deprecated [deprecated_index++] = c; - - if (c == UEOF) - java_lex_error - ("Comment not terminated at end of input", 0); - - java_unget_unicode (); - deprecated [deprecated_index] = '\0'; - if (!strcmp (deprecated, "deprecated")) - { - /* Set global flag to be checked by class. FIXME */ - warning ("deprecated implementation found"); - } - } - } + else if (java_parse_doc_section (c)) + goto step1; } else java_unget_unicode (); @@ -1206,6 +1208,7 @@ java_lex (java_lval) case TRY_TK: case CATCH_TK: case THROW_TK: + case INSTANCEOF_TK: BUILD_OPERATOR (kw->token); default: diff --git a/gcc/java/lex.h b/gcc/java/lex.h index b8dc5c2..621cfa6 100644 --- a/gcc/java/lex.h +++ b/gcc/java/lex.h @@ -35,13 +35,6 @@ extern int lineno; /* A Unicode character, as read from the input file */ typedef unsigned short unicode_t; -/* Function declaration */ -static int java_lineterminator (); -static char *java_sprint_unicode (); -static void java_unicode_2_utf8 (); -static void java_lex_error (); -static void java_store_unicode (); - /* Debug macro to print-out what we match */ #ifdef JAVA_LEX_DEBUG #ifdef JAVA_LEX_DEBUG_CHAR @@ -511,4 +504,23 @@ static tree build_wfl_node (); #define JAVA_READ_BUFFER 256 #define UEOF (unicode_t)0xffff +/* Function declaration */ +static int java_lineterminator PROTO ((unicode_t)); +static char *java_sprint_unicode PROTO ((struct java_line *, int)); +static void java_unicode_2_utf8 PROTO ((unicode_t)); +static void java_lex_error PROTO ((char *, int)); +static int java_is_eol PROTO ((FILE *, int)); +static void java_store_unicode PROTO ((struct java_line *, unicode_t, int)); +static unicode_t java_parse_escape_sequence PROTO (()); +static int java_letter_or_digit_p PROTO ((unicode_t)); +static int java_parse_doc_section PROTO ((unicode_t)); +static void java_parse_end_comment PROTO (()); +static unicode_t java_get_unicode PROTO (()); +static unicode_t java_read_unicode PROTO ((int, int *)); +static void java_store_unicode PROTO ((struct java_line *, unicode_t, int)); +static unicode_t java_read_char PROTO (()); +static void java_allocate_new_line PROTO (()); +static void java_unget_unicode PROTO (()); +static unicode_t java_sneak_unicode PROTO (()); + #endif diff --git a/gcc/java/mangle.c b/gcc/java/mangle.c index dff9ddf..08f587a 100644 --- a/gcc/java/mangle.c +++ b/gcc/java/mangle.c @@ -70,7 +70,6 @@ void emit_unicode_mangled_name (obstack, name, len) struct obstack *obstack; char *name; - int len; { unsigned char *ptr; unsigned char *limit = (unsigned char *)name + len; diff --git a/gcc/java/parse.c b/gcc/java/parse.c index 2775f3c..8646523 100644 --- a/gcc/java/parse.c +++ b/gcc/java/parse.c @@ -143,6 +143,7 @@ #include "lex.h" #include "parse.h" #include "zipfile.h" +#include "convert.h" /* Number of error found so far. */ int java_error_count; @@ -188,7 +189,7 @@ static tree wfl_append = NULL_TREE; /* The "toString" identifier used for String `+' operator. */ static tree wfl_to_string = NULL_TREE; -#line 116 "./parse.y" +#line 117 "./parse.y" typedef union { tree node; int sub_token; @@ -492,56 +493,56 @@ static const short yyrhs[] = { 123, #if YYDEBUG != 0 static const short yyrline[] = { 0, - 270, 276, 278, 279, 280, 281, 282, 286, 288, 291, - 293, 294, 297, 299, 302, 306, 310, 314, 320, 322, - 324, 326, 331, 333, 336, 340, 345, 350, 352, 353, - 354, 355, 356, 357, 358, 361, 366, 372, 374, 377, - 380, 382, 386, 388, 391, 421, 423, 427, 440, 442, - 446, 453, 454, 456, 466, 471, 486, 490, 493, 496, - 499, 501, 503, 505, 509, 511, 513, 515, 519, 521, - 523, 530, 536, 541, 545, 548, 552, 554, 557, 559, - 560, 561, 565, 567, 568, 570, 575, 578, 588, 591, - 593, 597, 600, 607, 613, 621, 623, 625, 627, 629, - 633, 635, 640, 647, 648, 652, 655, 657, 659, 661, - 663, 665, 667, 669, 676, 679, 681, 686, 688, 692, - 697, 702, 706, 711, 713, 715, 722, 724, 726, 730, - 733, 735, 739, 741, 742, 747, 752, 758, 766, 773, - 776, 779, 783, 786, 790, 799, 801, 803, 808, 815, - 823, 825, 829, 837, 848, 852, 855, 858, 861, 864, - 867, 870, 873, 875, 879, 885, 890, 892, 896, 899, - 903, 905, 908, 910, 911, 913, 917, 921, 927, 932, - 937, 941, 945, 951, 953, 954, 959, 962, 966, 971, - 979, 981, 984, 986, 988, 992, 996, 999, 1003, 1005, - 1006, 1007, 1008, 1009, 1019, 1021, 1022, 1023, 1024, 1027, - 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, - 1041, 1046, 1057, 1064, 1068, 1079, 1089, 1095, 1101, 1107, - 1109, 1115, 1117, 1123, 1125, 1127, 1129, 1131, 1135, 1137, - 1138, 1139, 1140, 1141, 1142, 1145, 1148, 1150, 1152, 1156, - 1161, 1166, 1174, 1180, 1182, 1184, 1188, 1191, 1193, 1195, - 1204, 1206, 1213, 1218, 1227, 1229, 1236, 1242, 1247, 1249, - 1251, 1255, 1263, 1266, 1268, 1270, 1274, 1279, 1288, 1293, - 1296, 1303, 1305, 1307, 1311, 1314, 1323, 1330, 1332, 1336, - 1349, 1351, 1357, 1363, 1367, 1369, 1373, 1376, 1378, 1382, - 1385, 1387, 1389, 1393, 1396, 1398, 1400, 1404, 1407, 1409, - 1411, 1415, 1421, 1423, 1427, 1434, 1436, 1438, 1440, 1444, - 1452, 1455, 1457, 1459, 1463, 1465, 1472, 1480, 1497, 1499, - 1501, 1505, 1511, 1516, 1518, 1521, 1523, 1525, 1527, 1528, - 1529, 1530, 1534, 1536, 1538, 1543, 1545, 1547, 1549, 1551, - 1555, 1558, 1563, 1565, 1570, 1571, 1572, 1573, 1574, 1576, - 1578, 1580, 1582, 1584, 1588, 1590, 1593, 1599, 1604, 1608, - 1611, 1613, 1615, 1619, 1621, 1623, 1625, 1629, 1632, 1636, - 1642, 1644, 1652, 1655, 1657, 1661, 1664, 1672, 1676, 1679, - 1681, 1692, 1703, 1708, 1717, 1719, 1723, 1726, 1728, 1733, - 1738, 1743, 1750, 1752, 1753, 1754, 1757, 1762, 1767, 1769, - 1770, 1772, 1774, 1775, 1777, 1781, 1784, 1788, 1791, 1795, - 1797, 1799, 1801, 1802, 1804, 1808, 1816, 1818, 1820, 1832, - 1834, 1840, 1842, 1844, 1848, 1850, 1855, 1860, 1865, 1867, - 1869, 1873, 1875, 1880, 1885, 1887, 1891, 1893, 1898, 1903, - 1908, 1910, 1912, 1916, 1918, 1923, 1928, 1933, 1938, 1939, - 1941, 1943, 1945, 1947, 1951, 1953, 1958, 1963, 1965, 1969, - 1971, 1976, 1980, 1982, 1987, 1991, 1993, 1998, 2002, 2004, - 2009, 2013, 2015, 2020, 2024, 2026, 2031, 2037, 2039, 2043, - 2045, 2048, 2051, 2059, 2061, 2062, 2065, 2067, 2070, 2074 + 271, 277, 279, 280, 281, 282, 283, 287, 289, 292, + 294, 295, 298, 300, 303, 307, 311, 315, 321, 323, + 325, 327, 332, 334, 337, 341, 346, 351, 353, 354, + 355, 356, 357, 358, 359, 362, 367, 373, 375, 378, + 381, 383, 387, 389, 392, 419, 421, 425, 438, 440, + 444, 451, 452, 454, 464, 469, 484, 488, 491, 494, + 497, 499, 501, 503, 507, 509, 511, 513, 517, 519, + 521, 528, 534, 539, 543, 546, 550, 552, 555, 557, + 558, 559, 563, 565, 566, 568, 573, 576, 586, 589, + 591, 595, 598, 605, 611, 619, 621, 623, 625, 627, + 631, 633, 638, 645, 646, 650, 653, 655, 657, 659, + 661, 663, 665, 667, 674, 677, 679, 684, 686, 690, + 695, 700, 704, 709, 711, 713, 720, 722, 724, 728, + 731, 733, 737, 739, 740, 745, 750, 756, 764, 771, + 774, 777, 781, 784, 788, 797, 799, 801, 806, 813, + 821, 823, 827, 835, 846, 850, 853, 856, 859, 862, + 865, 868, 871, 873, 877, 883, 888, 890, 894, 897, + 901, 903, 906, 908, 909, 911, 915, 919, 925, 930, + 935, 939, 943, 949, 951, 952, 957, 960, 964, 969, + 977, 979, 982, 984, 986, 990, 994, 997, 1001, 1003, + 1004, 1005, 1006, 1007, 1017, 1019, 1020, 1021, 1022, 1025, + 1027, 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, + 1039, 1044, 1055, 1062, 1066, 1077, 1087, 1093, 1099, 1105, + 1107, 1113, 1115, 1121, 1123, 1125, 1127, 1129, 1133, 1135, + 1136, 1137, 1138, 1139, 1140, 1143, 1146, 1148, 1150, 1154, + 1159, 1164, 1172, 1178, 1180, 1182, 1186, 1189, 1191, 1193, + 1202, 1204, 1211, 1216, 1225, 1227, 1234, 1240, 1245, 1247, + 1249, 1253, 1261, 1264, 1266, 1268, 1272, 1277, 1286, 1291, + 1294, 1301, 1303, 1305, 1309, 1312, 1321, 1328, 1330, 1334, + 1347, 1349, 1355, 1361, 1365, 1367, 1371, 1374, 1376, 1380, + 1383, 1385, 1387, 1391, 1394, 1396, 1398, 1402, 1405, 1407, + 1409, 1413, 1419, 1421, 1425, 1432, 1434, 1436, 1438, 1442, + 1450, 1453, 1455, 1457, 1461, 1463, 1470, 1478, 1495, 1497, + 1499, 1503, 1509, 1514, 1516, 1519, 1521, 1523, 1525, 1526, + 1527, 1528, 1532, 1534, 1536, 1541, 1543, 1545, 1547, 1549, + 1553, 1556, 1561, 1563, 1568, 1569, 1570, 1571, 1572, 1574, + 1576, 1578, 1580, 1582, 1586, 1588, 1591, 1597, 1602, 1606, + 1609, 1611, 1613, 1617, 1619, 1621, 1623, 1627, 1630, 1634, + 1640, 1642, 1650, 1653, 1655, 1659, 1662, 1670, 1674, 1677, + 1679, 1690, 1701, 1706, 1715, 1717, 1721, 1724, 1726, 1731, + 1736, 1741, 1748, 1750, 1751, 1752, 1755, 1760, 1765, 1767, + 1768, 1770, 1772, 1773, 1775, 1779, 1782, 1786, 1789, 1793, + 1795, 1797, 1799, 1800, 1802, 1806, 1814, 1816, 1818, 1830, + 1832, 1838, 1840, 1842, 1846, 1848, 1853, 1858, 1863, 1865, + 1867, 1871, 1873, 1878, 1883, 1885, 1889, 1891, 1896, 1901, + 1906, 1908, 1910, 1914, 1916, 1921, 1926, 1931, 1936, 1938, + 1940, 1942, 1944, 1946, 1950, 1952, 1957, 1962, 1964, 1968, + 1970, 1975, 1979, 1981, 1986, 1990, 1992, 1997, 2001, 2003, + 2008, 2012, 2014, 2019, 2023, 2025, 2030, 2036, 2038, 2042, + 2044, 2047, 2050, 2058, 2060, 2061, 2064, 2066, 2069, 2073 }; #endif @@ -2531,66 +2532,66 @@ yyreduce: switch (yyn) { case 1: -#line 272 "./parse.y" +#line 273 "./parse.y" {; break;} case 18: -#line 316 "./parse.y" +#line 317 "./parse.y" { yyval.node = build_java_array_type (yyvsp[-2].node, -1); CLASS_LOADED_P (yyval.node) = 1; ; break;} case 19: -#line 321 "./parse.y" +#line 322 "./parse.y" { yyval.node = build_unresolved_array_type (yyvsp[-2].node); ; break;} case 20: -#line 323 "./parse.y" +#line 324 "./parse.y" { yyval.node = build_unresolved_array_type (yyvsp[-2].node); ; break;} case 21: -#line 325 "./parse.y" +#line 326 "./parse.y" {RULE ("']' expected"); RECOVER;; break;} case 22: -#line 327 "./parse.y" +#line 328 "./parse.y" {RULE ("']' expected"); RECOVER;; break;} case 26: -#line 342 "./parse.y" +#line 343 "./parse.y" { yyval.node = make_qualified_name (yyvsp[-2].node, yyvsp[0].node, yyvsp[-1].operator.location); ; break;} case 28: -#line 351 "./parse.y" +#line 352 "./parse.y" {yyval.node = NULL;; break;} case 36: -#line 363 "./parse.y" +#line 364 "./parse.y" { yyval.node = NULL; ; break;} case 37: -#line 367 "./parse.y" +#line 368 "./parse.y" { yyval.node = NULL; ; break;} case 40: -#line 379 "./parse.y" +#line 380 "./parse.y" { ctxp->package = EXPR_WFL_NODE (yyvsp[-1].node); ; break;} case 41: -#line 381 "./parse.y" +#line 382 "./parse.y" {yyerror ("Missing name"); RECOVER;; break;} case 42: -#line 383 "./parse.y" +#line 384 "./parse.y" {yyerror ("';' expected"); RECOVER;; break;} case 45: -#line 393 "./parse.y" +#line 394 "./parse.y" { tree name = EXPR_WFL_NODE (yyvsp[-1].node), node, last_name; int i = IDENTIFIER_LENGTH (name)-1; @@ -2610,26 +2611,23 @@ case 45: (yyvsp[-1].node, "Ambiguous class: `%s' and `%s'", IDENTIFIER_POINTER (name), IDENTIFIER_POINTER (err)); + else + REGISTER_IMPORT (yyvsp[-1].node, last_name) } else - { - IS_A_SINGLE_IMPORT_CLASSFILE_NAME_P (last_name) = 1; - node = build_tree_list (yyvsp[-1].node, last_name); - TREE_CHAIN (node) = ctxp->import_list; - ctxp->import_list = node; - } + REGISTER_IMPORT (yyvsp[-1].node, last_name); ; break;} case 46: -#line 422 "./parse.y" +#line 420 "./parse.y" {yyerror ("Missing name"); RECOVER;; break;} case 47: -#line 424 "./parse.y" +#line 422 "./parse.y" {yyerror ("';' expected"); RECOVER;; break;} case 48: -#line 429 "./parse.y" +#line 427 "./parse.y" { tree name = EXPR_WFL_NODE (yyvsp[-3].node); tree node = build_tree_list (yyvsp[-3].node, NULL_TREE); @@ -2643,15 +2641,15 @@ case 48: ; break;} case 49: -#line 441 "./parse.y" +#line 439 "./parse.y" {yyerror ("'*' expected"); RECOVER;; break;} case 50: -#line 443 "./parse.y" +#line 441 "./parse.y" {yyerror ("';' expected"); RECOVER;; break;} case 51: -#line 448 "./parse.y" +#line 446 "./parse.y" { maybe_generate_clinit (); maybe_generate_finit (); @@ -2659,24 +2657,24 @@ case 51: ; break;} case 53: -#line 455 "./parse.y" +#line 453 "./parse.y" { yyval.node = NULL; ; break;} case 54: -#line 457 "./parse.y" +#line 455 "./parse.y" { YYERROR_NOW; yyerror ("Class or interface declaration expected"); ; break;} case 55: -#line 468 "./parse.y" +#line 466 "./parse.y" { yyval.value = (1 << yyvsp[0].value); ; break;} case 56: -#line 472 "./parse.y" +#line 470 "./parse.y" { int acc = (1 << yyvsp[0].value); if (yyval.value & acc) @@ -2690,116 +2688,116 @@ case 56: ; break;} case 57: -#line 488 "./parse.y" +#line 486 "./parse.y" { create_class (yyvsp[-4].value, yyvsp[-2].node, yyvsp[-1].node, yyvsp[0].node); ; break;} case 58: -#line 490 "./parse.y" +#line 488 "./parse.y" { yyval.node = yyvsp[0].node; ; break;} case 59: -#line 494 "./parse.y" +#line 492 "./parse.y" { create_class (0, yyvsp[-2].node, yyvsp[-1].node, yyvsp[0].node); ; break;} case 60: -#line 496 "./parse.y" +#line 494 "./parse.y" { yyval.node = yyvsp[0].node; ; break;} case 61: -#line 500 "./parse.y" +#line 498 "./parse.y" {yyerror ("Missing class name"); RECOVER;; break;} case 62: -#line 502 "./parse.y" +#line 500 "./parse.y" {yyerror ("Missing class name"); RECOVER;; break;} case 63: -#line 504 "./parse.y" +#line 502 "./parse.y" {if (!ctxp->class_err) yyerror ("'{' expected"); DRECOVER(class1);; break;} case 64: -#line 506 "./parse.y" +#line 504 "./parse.y" {if (!ctxp->class_err) yyerror ("'{' expected"); RECOVER;; break;} case 65: -#line 510 "./parse.y" +#line 508 "./parse.y" { yyval.node = NULL; ; break;} case 66: -#line 512 "./parse.y" +#line 510 "./parse.y" { yyval.node = yyvsp[0].node; ; break;} case 67: -#line 514 "./parse.y" +#line 512 "./parse.y" {yyerror ("'{' expected"); ctxp->class_err=1;; break;} case 68: -#line 516 "./parse.y" +#line 514 "./parse.y" {yyerror ("Missing super class name"); ctxp->class_err=1;; break;} case 69: -#line 520 "./parse.y" +#line 518 "./parse.y" { yyval.node = NULL_TREE; ; break;} case 70: -#line 522 "./parse.y" +#line 520 "./parse.y" { yyval.node = yyvsp[0].node; ; break;} case 71: -#line 524 "./parse.y" +#line 522 "./parse.y" { ctxp->class_err=1; yyerror ("Missing interface name"); ; break;} case 72: -#line 532 "./parse.y" +#line 530 "./parse.y" { ctxp->interface_number = 1; yyval.node = build_tree_list (yyvsp[0].node, NULL_TREE); ; break;} case 73: -#line 537 "./parse.y" +#line 535 "./parse.y" { ctxp->interface_number++; yyval.node = chainon (yyvsp[-2].node, build_tree_list (yyvsp[0].node, NULL_TREE)); ; break;} case 74: -#line 542 "./parse.y" +#line 540 "./parse.y" {yyerror ("Missing interface name"); RECOVER;; break;} case 75: -#line 547 "./parse.y" +#line 545 "./parse.y" { yyval.node = ctxp->current_parsed_class; ; break;} case 76: -#line 549 "./parse.y" +#line 547 "./parse.y" { yyval.node = ctxp->current_parsed_class; ; break;} case 82: -#line 562 "./parse.y" +#line 560 "./parse.y" { yyval.node = parse_jdk1_1_error ("instance initializer"); ; break;} case 85: -#line 569 "./parse.y" +#line 567 "./parse.y" { yyval.node = parse_jdk1_1_error ("inner classe declaration"); ; break;} case 86: -#line 571 "./parse.y" +#line 569 "./parse.y" { yyval.node = parse_jdk1_1_error ("inner interface declaration"); ; break;} case 87: -#line 577 "./parse.y" +#line 575 "./parse.y" { register_fields (0, yyvsp[-2].node, yyvsp[-1].node); ; break;} case 88: -#line 579 "./parse.y" +#line 577 "./parse.y" { check_modifiers ("Illegal modifier `%s' for field declaration", @@ -2809,19 +2807,19 @@ case 88: ; break;} case 90: -#line 592 "./parse.y" +#line 590 "./parse.y" { yyval.node = chainon (yyvsp[-2].node, yyvsp[0].node); ; break;} case 91: -#line 594 "./parse.y" +#line 592 "./parse.y" {yyerror ("Missing term"); RECOVER;; break;} case 92: -#line 599 "./parse.y" +#line 597 "./parse.y" { yyval.node = build_tree_list (yyvsp[0].node, NULL_TREE); ; break;} case 93: -#line 601 "./parse.y" +#line 599 "./parse.y" { if (java_error_count) yyvsp[0].node = NULL_TREE; @@ -2830,7 +2828,7 @@ case 93: ; break;} case 94: -#line 608 "./parse.y" +#line 606 "./parse.y" { yyerror ("Missing variable initializer"); yyval.node = build_tree_list (yyvsp[-2].node, NULL_TREE); @@ -2838,7 +2836,7 @@ case 94: ; break;} case 95: -#line 614 "./parse.y" +#line 612 "./parse.y" { yyerror ("';' expected"); yyval.node = build_tree_list (yyvsp[-3].node, NULL_TREE); @@ -2846,234 +2844,234 @@ case 95: ; break;} case 97: -#line 624 "./parse.y" +#line 622 "./parse.y" { yyval.node = build_unresolved_array_type (yyvsp[-2].node); ; break;} case 98: -#line 626 "./parse.y" +#line 624 "./parse.y" {yyerror ("Invalid declaration"); DRECOVER(vdi);; break;} case 99: -#line 628 "./parse.y" +#line 626 "./parse.y" {yyerror ("']' expected"); DRECOVER(vdi);; break;} case 100: -#line 630 "./parse.y" +#line 628 "./parse.y" {yyerror ("Unbalanced ']'"); DRECOVER(vdi);; break;} case 102: -#line 636 "./parse.y" +#line 634 "./parse.y" { yyval.node = NULL; ; break;} case 103: -#line 642 "./parse.y" +#line 640 "./parse.y" { current_function_decl = yyvsp[0].node; source_start_java_method (current_function_decl); ; break;} case 104: -#line 647 "./parse.y" +#line 645 "./parse.y" { complete_method_declaration (yyvsp[0].node); ; break;} case 105: -#line 649 "./parse.y" +#line 647 "./parse.y" {YYNOT_TWICE yyerror ("'{' expected"); RECOVER;; break;} case 106: -#line 654 "./parse.y" +#line 652 "./parse.y" { yyval.node = method_header (0, yyvsp[-2].node, yyvsp[-1].node, yyvsp[0].node); ; break;} case 107: -#line 656 "./parse.y" +#line 654 "./parse.y" { yyval.node = method_header (0, void_type_node, yyvsp[-1].node, yyvsp[0].node); ; break;} case 108: -#line 658 "./parse.y" +#line 656 "./parse.y" { yyval.node = method_header (yyvsp[-3].value, yyvsp[-2].node, yyvsp[-1].node, yyvsp[0].node); ; break;} case 109: -#line 660 "./parse.y" +#line 658 "./parse.y" { yyval.node = method_header (yyvsp[-3].value, void_type_node, yyvsp[-1].node, yyvsp[0].node); ; break;} case 110: -#line 662 "./parse.y" +#line 660 "./parse.y" {RECOVER;; break;} case 111: -#line 664 "./parse.y" +#line 662 "./parse.y" {RECOVER;; break;} case 112: -#line 666 "./parse.y" +#line 664 "./parse.y" {yyerror ("Identifier expected"); RECOVER;; break;} case 113: -#line 668 "./parse.y" +#line 666 "./parse.y" {yyerror ("Identifier expected"); RECOVER;; break;} case 114: -#line 670 "./parse.y" +#line 668 "./parse.y" { yyerror ("Invalid method declaration, return type required"); RECOVER; ; break;} case 115: -#line 678 "./parse.y" +#line 676 "./parse.y" { yyval.node = method_declarator (yyvsp[-2].node, NULL_TREE); ; break;} case 116: -#line 680 "./parse.y" +#line 678 "./parse.y" { yyval.node = method_declarator (yyvsp[-3].node, yyvsp[-1].node); ; break;} case 117: -#line 682 "./parse.y" +#line 680 "./parse.y" { /* Issue a warning here: obsolete declaration. FIXME */ yyval.node = NULL; /* FIXME */ ; break;} case 118: -#line 687 "./parse.y" +#line 685 "./parse.y" {yyerror ("')' expected"); DRECOVER(method_declarator);; break;} case 119: -#line 689 "./parse.y" +#line 687 "./parse.y" {yyerror ("']' expected"); RECOVER;; break;} case 120: -#line 694 "./parse.y" +#line 692 "./parse.y" { ctxp->formal_parameter_number = 1; ; break;} case 121: -#line 698 "./parse.y" +#line 696 "./parse.y" { ctxp->formal_parameter_number += 1; yyval.node = chainon (yyvsp[-2].node, yyvsp[0].node); ; break;} case 122: -#line 703 "./parse.y" +#line 701 "./parse.y" {yyerror ("Missing formal parameter term"); RECOVER;; break;} case 123: -#line 708 "./parse.y" +#line 706 "./parse.y" { yyval.node = build_tree_list (yyvsp[0].node, yyvsp[-1].node); ; break;} case 124: -#line 712 "./parse.y" +#line 710 "./parse.y" { yyval.node = parse_jdk1_1_error ("final local"); ; break;} case 125: -#line 714 "./parse.y" +#line 712 "./parse.y" {yyerror ("Missing identifier"); RECOVER;; break;} case 126: -#line 716 "./parse.y" +#line 714 "./parse.y" { SOURCE_FRONTEND_DEBUG (("Modifiers: %d", yyvsp[-2].value)); yyerror ("Missing identifier"); RECOVER; ; break;} case 127: -#line 723 "./parse.y" +#line 721 "./parse.y" { yyval.node = NULL_TREE; ; break;} case 128: -#line 725 "./parse.y" +#line 723 "./parse.y" { yyval.node = yyvsp[0].node; ; break;} case 129: -#line 727 "./parse.y" +#line 725 "./parse.y" {yyerror ("Missing class type term"); RECOVER;; break;} case 130: -#line 732 "./parse.y" +#line 730 "./parse.y" { yyval.node = build_tree_list (NULL_TREE, yyvsp[0].node); ; break;} case 131: -#line 734 "./parse.y" +#line 732 "./parse.y" { yyval.node = tree_cons (NULL_TREE, yyvsp[0].node, yyvsp[-2].node); ; break;} case 132: -#line 736 "./parse.y" +#line 734 "./parse.y" {yyerror ("Missing class type term"); RECOVER;; break;} case 135: -#line 743 "./parse.y" +#line 741 "./parse.y" { yyval.node = NULL_TREE; ; break;} case 136: -#line 749 "./parse.y" +#line 747 "./parse.y" { RULE ("STATIC_INITIALIZER"); ; break;} case 137: -#line 753 "./parse.y" +#line 751 "./parse.y" { RULE ("STATIC_INITIALIZER"); ; break;} case 138: -#line 760 "./parse.y" +#line 758 "./parse.y" { SOURCE_FRONTEND_DEBUG (("Modifiers: %d", yyvsp[0].value)); ; break;} case 139: -#line 768 "./parse.y" +#line 766 "./parse.y" { current_function_decl = yyvsp[0].node; source_start_java_method (current_function_decl); ; break;} case 140: -#line 773 "./parse.y" +#line 771 "./parse.y" { complete_method_declaration (yyvsp[0].node); ; break;} case 141: -#line 778 "./parse.y" +#line 776 "./parse.y" { yyval.node = method_header (0, NULL_TREE, yyvsp[-1].node, yyvsp[0].node); ; break;} case 142: -#line 780 "./parse.y" +#line 778 "./parse.y" { yyval.node = method_header (yyvsp[-2].value, NULL_TREE, yyvsp[-1].node, yyvsp[0].node); ; break;} case 143: -#line 785 "./parse.y" +#line 783 "./parse.y" { yyval.node = method_declarator (yyvsp[-2].node, NULL_TREE); ; break;} case 144: -#line 787 "./parse.y" +#line 785 "./parse.y" { yyval.node = method_declarator (yyvsp[-3].node, yyvsp[-1].node); ; break;} case 145: -#line 795 "./parse.y" +#line 793 "./parse.y" { BLOCK_EXPR_BODY (yyvsp[0].node) = size_zero_node; yyval.node = yyvsp[0].node; ; break;} case 146: -#line 800 "./parse.y" +#line 798 "./parse.y" { yyval.node = yyvsp[0].node; ; break;} case 147: -#line 802 "./parse.y" +#line 800 "./parse.y" { yyval.node = yyvsp[0].node; ; break;} case 148: -#line 804 "./parse.y" +#line 802 "./parse.y" { yyval.node = yyvsp[0].node; ; break;} case 149: -#line 810 "./parse.y" +#line 808 "./parse.y" { yyval.node = build_method_invocation (yyvsp[-3].node, NULL_TREE); yyval.node = build_debugable_stmt (EXPR_WFL_LINECOL (yyvsp[-3].node), yyval.node); @@ -3081,7 +3079,7 @@ case 149: ; break;} case 150: -#line 816 "./parse.y" +#line 814 "./parse.y" { yyval.node = build_method_invocation (yyvsp[-4].node, yyvsp[-2].node); yyval.node = build_debugable_stmt (EXPR_WFL_LINECOL (yyvsp[-4].node), yyval.node); @@ -3089,15 +3087,15 @@ case 150: ; break;} case 151: -#line 824 "./parse.y" +#line 822 "./parse.y" {yyval.node = parse_jdk1_1_error ("explicit constructor invocation"); ; break;} case 152: -#line 826 "./parse.y" +#line 824 "./parse.y" {yyval.node = parse_jdk1_1_error ("explicit constructor invocation"); ; break;} case 153: -#line 831 "./parse.y" +#line 829 "./parse.y" { tree wfl = build_wfl_node (this_identifier_node, input_filename, 0, 0); @@ -3106,7 +3104,7 @@ case 153: ; break;} case 154: -#line 838 "./parse.y" +#line 836 "./parse.y" { tree wfl = build_wfl_node (super_identifier_node, input_filename, 0, 0); @@ -3115,167 +3113,167 @@ case 154: ; break;} case 155: -#line 850 "./parse.y" +#line 848 "./parse.y" { create_interface (0, yyvsp[0].node, NULL_TREE); ; break;} case 156: -#line 852 "./parse.y" +#line 850 "./parse.y" { yyval.node = yyvsp[0].node; ; break;} case 157: -#line 856 "./parse.y" +#line 854 "./parse.y" { create_interface (yyvsp[-2].value, yyvsp[0].node, NULL_TREE); ; break;} case 158: -#line 858 "./parse.y" +#line 856 "./parse.y" { yyval.node = yyvsp[0].node; ; break;} case 159: -#line 862 "./parse.y" +#line 860 "./parse.y" { create_interface (0, yyvsp[-1].node, yyvsp[0].node); ; break;} case 160: -#line 864 "./parse.y" +#line 862 "./parse.y" { yyval.node = yyvsp[0].node; ; break;} case 161: -#line 868 "./parse.y" +#line 866 "./parse.y" { create_interface (yyvsp[-3].value, yyvsp[-1].node, yyvsp[0].node); ; break;} case 162: -#line 870 "./parse.y" +#line 868 "./parse.y" { yyval.node = yyvsp[0].node; ; break;} case 163: -#line 874 "./parse.y" +#line 872 "./parse.y" {yyerror ("(here)'{' expected"); RECOVER;; break;} case 164: -#line 876 "./parse.y" +#line 874 "./parse.y" {yyerror ("(there)'{' expected"); RECOVER;; break;} case 165: -#line 881 "./parse.y" +#line 879 "./parse.y" { ctxp->interface_number = 1; yyval.node = build_tree_list (yyvsp[0].node, NULL_TREE); ; break;} case 166: -#line 886 "./parse.y" +#line 884 "./parse.y" { ctxp->interface_number++; yyval.node = chainon (yyvsp[-2].node, build_tree_list (yyvsp[0].node, NULL_TREE)); ; break;} case 167: -#line 891 "./parse.y" +#line 889 "./parse.y" {yyerror ("Invalid interface type"); RECOVER;; break;} case 168: -#line 893 "./parse.y" +#line 891 "./parse.y" {yyerror ("Missing term"); RECOVER;; break;} case 169: -#line 898 "./parse.y" +#line 896 "./parse.y" { yyval.node = NULL_TREE; ; break;} case 170: -#line 900 "./parse.y" +#line 898 "./parse.y" { yyval.node = NULL_TREE; ; break;} case 175: -#line 912 "./parse.y" +#line 910 "./parse.y" { yyval.node = parse_jdk1_1_error ("inner class declaration"); ; break;} case 176: -#line 914 "./parse.y" +#line 912 "./parse.y" { yyval.node = parse_jdk1_1_error ("inner interface declaration"); ; break;} case 178: -#line 923 "./parse.y" +#line 921 "./parse.y" { check_abstract_method_header (yyvsp[-1].node); current_function_decl = NULL_TREE; /* FIXME ? */ ; break;} case 179: -#line 928 "./parse.y" +#line 926 "./parse.y" {yyerror ("';' expected"); RECOVER;; break;} case 180: -#line 934 "./parse.y" +#line 932 "./parse.y" { RULE ("ARRAY_INITIALIZER (empty)"); ; break;} case 181: -#line 938 "./parse.y" +#line 936 "./parse.y" { RULE ("ARRAY_INITIALIZER (variable)"); ; break;} case 182: -#line 942 "./parse.y" +#line 940 "./parse.y" { RULE ("ARRAY_INITIALIZER (,)"); ; break;} case 183: -#line 946 "./parse.y" +#line 944 "./parse.y" { RULE ("ARRAY_INITIALIZER (variable, ,)"); ; break;} case 186: -#line 955 "./parse.y" +#line 953 "./parse.y" {yyerror ("Missing term"); RECOVER;; break;} case 187: -#line 961 "./parse.y" +#line 959 "./parse.y" { yyval.node = size_zero_node; ; break;} case 188: -#line 963 "./parse.y" +#line 961 "./parse.y" { yyval.node = yyvsp[0].node; ; break;} case 189: -#line 968 "./parse.y" +#line 966 "./parse.y" { enter_block (); ; break;} case 190: -#line 973 "./parse.y" +#line 971 "./parse.y" { maybe_absorb_scoping_blocks (); yyval.node = exit_block (); ; break;} case 194: -#line 987 "./parse.y" +#line 985 "./parse.y" { yyval.node = java_method_add_stmt (current_function_decl, yyvsp[0].node); ; break;} case 195: -#line 989 "./parse.y" +#line 987 "./parse.y" { yyval.node = parse_jdk1_1_error ("inner class declaration"); ; break;} case 197: -#line 998 "./parse.y" +#line 996 "./parse.y" { declare_local_variables (0, yyvsp[-1].node, yyvsp[0].node); ; break;} case 198: -#line 1000 "./parse.y" +#line 998 "./parse.y" { declare_local_variables (yyvsp[-2].value, yyvsp[-1].node, yyvsp[0].node); ; break;} case 204: -#line 1010 "./parse.y" +#line 1008 "./parse.y" { /* If the for loop is unlabeled, we must return the block it was defined it. It our last chance to @@ -3285,11 +3283,11 @@ case 204: ; break;} case 221: -#line 1043 "./parse.y" +#line 1041 "./parse.y" { yyval.node = size_zero_node; ; break;} case 222: -#line 1048 "./parse.y" +#line 1046 "./parse.y" { yyval.node = build_labeled_block (EXPR_WFL_LINECOL (yyvsp[-1].node), EXPR_WFL_NODE (yyvsp[-1].node)); @@ -3299,7 +3297,7 @@ case 222: ; break;} case 223: -#line 1059 "./parse.y" +#line 1057 "./parse.y" { yyval.node = complete_labeled_statement (yyvsp[-1].node, yyvsp[0].node); pop_labeled_block (); @@ -3307,11 +3305,11 @@ case 223: ; break;} case 224: -#line 1065 "./parse.y" +#line 1063 "./parse.y" {yyerror ("':' expected"); RECOVER;; break;} case 225: -#line 1070 "./parse.y" +#line 1068 "./parse.y" { yyval.node = complete_labeled_statement (yyvsp[-1].node, yyvsp[0].node); pop_labeled_block (); @@ -3319,7 +3317,7 @@ case 225: ; break;} case 226: -#line 1081 "./parse.y" +#line 1079 "./parse.y" { /* We have a statement. Generate a WFL around it so we can debug it */ @@ -3330,7 +3328,7 @@ case 226: ; break;} case 227: -#line 1090 "./parse.y" +#line 1088 "./parse.y" { if (ctxp->prevent_ese != lineno) yyerror ("Invalid expression statement"); @@ -3338,7 +3336,7 @@ case 227: ; break;} case 228: -#line 1096 "./parse.y" +#line 1094 "./parse.y" { if (ctxp->prevent_ese != lineno) yyerror ("Invalid expression statement"); @@ -3346,7 +3344,7 @@ case 228: ; break;} case 229: -#line 1102 "./parse.y" +#line 1100 "./parse.y" { if (ctxp->prevent_ese != lineno) yyerror ("Invalid expression statement"); @@ -3354,11 +3352,11 @@ case 229: ; break;} case 230: -#line 1108 "./parse.y" +#line 1106 "./parse.y" {yyerror ("')' expected"); RECOVER;; break;} case 231: -#line 1110 "./parse.y" +#line 1108 "./parse.y" { yyerror ("Constructor invocation must be first " "thing in a constructor"); @@ -3366,11 +3364,11 @@ case 231: ; break;} case 232: -#line 1116 "./parse.y" +#line 1114 "./parse.y" {yyerror ("')' expected"); RECOVER;; break;} case 233: -#line 1118 "./parse.y" +#line 1116 "./parse.y" { yyerror ("Constructor invocation must be first " "thing in a constructor"); @@ -3378,89 +3376,89 @@ case 233: ; break;} case 234: -#line 1124 "./parse.y" +#line 1122 "./parse.y" {yyerror ("'(' expected"); RECOVER;; break;} case 235: -#line 1126 "./parse.y" +#line 1124 "./parse.y" {yyerror ("')' expected"); RECOVER;; break;} case 236: -#line 1128 "./parse.y" +#line 1126 "./parse.y" {yyerror ("')' expected"); RECOVER;; break;} case 237: -#line 1130 "./parse.y" +#line 1128 "./parse.y" {yyerror ("';' expected"); RECOVER;; break;} case 238: -#line 1132 "./parse.y" +#line 1130 "./parse.y" {yyerror ("';' expected"); RECOVER;; break;} case 246: -#line 1147 "./parse.y" +#line 1145 "./parse.y" { yyval.node = build_if_else_statement (yyvsp[-3].operator.location, yyvsp[-2].node, yyvsp[0].node, NULL_TREE); ; break;} case 247: -#line 1149 "./parse.y" +#line 1147 "./parse.y" {yyerror ("'(' expected"); RECOVER;; break;} case 248: -#line 1151 "./parse.y" +#line 1149 "./parse.y" {yyerror ("Missing term"); RECOVER;; break;} case 249: -#line 1153 "./parse.y" +#line 1151 "./parse.y" {yyerror ("')' expected"); RECOVER;; break;} case 250: -#line 1158 "./parse.y" +#line 1156 "./parse.y" { yyval.node = build_if_else_statement (yyvsp[-5].operator.location, yyvsp[-4].node, yyvsp[-2].node, yyvsp[0].node); ; break;} case 251: -#line 1163 "./parse.y" +#line 1161 "./parse.y" { yyval.node = build_if_else_statement (yyvsp[-5].operator.location, yyvsp[-4].node, yyvsp[-2].node, yyvsp[0].node); ; break;} case 252: -#line 1168 "./parse.y" +#line 1166 "./parse.y" { TREE_OPERAND (yyvsp[-1].node, 1) = yyvsp[0].node; yyval.node = build_debugable_stmt (EXPR_WFL_LINECOL (yyvsp[-1].node), yyvsp[-1].node); ; break;} case 253: -#line 1176 "./parse.y" +#line 1174 "./parse.y" { yyval.node = build (SWITCH_EXPR, NULL_TREE, yyvsp[-1].node, NULL_TREE); EXPR_WFL_LINECOL (yyval.node) = yyvsp[-2].operator.location; ; break;} case 254: -#line 1181 "./parse.y" +#line 1179 "./parse.y" {yyerror ("'(' expected"); RECOVER;; break;} case 255: -#line 1183 "./parse.y" +#line 1181 "./parse.y" {yyerror ("Missing term or ')'"); DRECOVER(switch_statement);; break;} case 256: -#line 1185 "./parse.y" +#line 1183 "./parse.y" {yyerror ("'{' expected"); RECOVER;; break;} case 257: -#line 1190 "./parse.y" +#line 1188 "./parse.y" { yyval.node = NULL_TREE; ; break;} case 258: -#line 1192 "./parse.y" +#line 1190 "./parse.y" { yyval.node = build_tree_list (yyvsp[-1].node, NULL_TREE); ; break;} case 259: -#line 1194 "./parse.y" +#line 1192 "./parse.y" { yyval.node = yyvsp[-1].node; ; break;} case 260: -#line 1196 "./parse.y" +#line 1194 "./parse.y" { /* Switch labels alone are empty switch statements */ tree sl = build_tree_list (yyvsp[-1].node, NULL_TREE); @@ -3469,18 +3467,18 @@ case 260: ; break;} case 262: -#line 1207 "./parse.y" +#line 1205 "./parse.y" { TREE_CHAIN (yyvsp[0].node) = yyvsp[-1].node; yyval.node = yyvsp[0].node; ; break;} case 263: -#line 1215 "./parse.y" +#line 1213 "./parse.y" { yyval.node = build_tree_list (yyvsp[-1].node, exit_block ()); ; break;} case 264: -#line 1220 "./parse.y" +#line 1218 "./parse.y" { /* All statements attached to this group of cases will be stored in a block */ @@ -3489,82 +3487,82 @@ case 264: ; break;} case 266: -#line 1230 "./parse.y" +#line 1228 "./parse.y" { TREE_CHAIN (yyvsp[0].node) = yyvsp[-1].node; yyval.node = yyvsp[0].node; ; break;} case 267: -#line 1238 "./parse.y" +#line 1236 "./parse.y" { yyval.node = build1 (CASE_EXPR, NULL_TREE, yyvsp[-1].node); EXPR_WFL_LINECOL (yyval.node) = yyvsp[-2].operator.location; ; break;} case 268: -#line 1243 "./parse.y" +#line 1241 "./parse.y" { yyval.node = build1 (DEFAULT_EXPR, NULL_TREE, NULL_TREE); EXPR_WFL_LINECOL (yyval.node) = yyvsp[-1].operator.location; ; break;} case 269: -#line 1248 "./parse.y" +#line 1246 "./parse.y" {yyerror ("Missing or invalid constant expression"); RECOVER;; break;} case 270: -#line 1250 "./parse.y" +#line 1248 "./parse.y" {yyerror ("':' expected"); RECOVER;; break;} case 271: -#line 1252 "./parse.y" +#line 1250 "./parse.y" {yyerror ("':' expected"); RECOVER;; break;} case 272: -#line 1257 "./parse.y" +#line 1255 "./parse.y" { tree body = build_loop_body (yyvsp[-2].operator.location, yyvsp[-1].node, 0); yyval.node = build_new_loop (body); ; break;} case 273: -#line 1265 "./parse.y" +#line 1263 "./parse.y" { yyval.node = complete_loop_body (0, NULL_TREE, yyvsp[0].node, 0); ; break;} case 274: -#line 1267 "./parse.y" +#line 1265 "./parse.y" {YYERROR_NOW; yyerror ("'(' expected"); RECOVER;; break;} case 275: -#line 1269 "./parse.y" +#line 1267 "./parse.y" {yyerror ("Missing term and ')' expected"); RECOVER;; break;} case 276: -#line 1271 "./parse.y" +#line 1269 "./parse.y" {yyerror ("')' expected"); RECOVER;; break;} case 277: -#line 1276 "./parse.y" +#line 1274 "./parse.y" { yyval.node = complete_loop_body (0, NULL_TREE, yyvsp[0].node, 0); ; break;} case 278: -#line 1281 "./parse.y" +#line 1279 "./parse.y" { tree body = build_loop_body (0, NULL_TREE, 1); yyval.node = build_new_loop (body); ; break;} case 279: -#line 1290 "./parse.y" +#line 1288 "./parse.y" { yyval.node = complete_loop_body (yyvsp[-3].operator.location, yyvsp[-2].node, yyvsp[-5].node, 1); ; break;} case 280: -#line 1295 "./parse.y" +#line 1293 "./parse.y" { yyval.node = complete_for_loop (EXPR_WFL_LINECOL (yyvsp[-4].node), yyvsp[-4].node, yyvsp[-2].node, yyvsp[0].node);; break;} case 281: -#line 1297 "./parse.y" +#line 1295 "./parse.y" { yyval.node = complete_for_loop (0, NULL_TREE, yyvsp[-2].node, yyvsp[0].node); /* We have not condition, so we get rid of the EXIT_EXPR */ @@ -3573,23 +3571,23 @@ case 281: ; break;} case 282: -#line 1304 "./parse.y" +#line 1302 "./parse.y" {yyerror ("Invalid control expression"); RECOVER;; break;} case 283: -#line 1306 "./parse.y" +#line 1304 "./parse.y" {yyerror ("Invalid update expression"); RECOVER;; break;} case 284: -#line 1308 "./parse.y" +#line 1306 "./parse.y" {yyerror ("Invalid update expression"); RECOVER;; break;} case 285: -#line 1313 "./parse.y" +#line 1311 "./parse.y" { yyval.node = complete_for_loop (EXPR_WFL_LINECOL (yyvsp[-4].node), yyvsp[-4].node, yyvsp[-2].node, yyvsp[0].node);; break;} case 286: -#line 1315 "./parse.y" +#line 1313 "./parse.y" { yyval.node = complete_for_loop (0, NULL_TREE, yyvsp[-2].node, yyvsp[0].node); /* We have not condition, so we get rid of the EXIT_EXPR */ @@ -3598,7 +3596,7 @@ case 286: ; break;} case 287: -#line 1325 "./parse.y" +#line 1323 "./parse.y" { /* This scope defined for local variable that may be defined within the scope of the for loop */ @@ -3606,15 +3604,15 @@ case 287: ; break;} case 288: -#line 1331 "./parse.y" +#line 1329 "./parse.y" {yyerror ("'(' expected"); DRECOVER(for_1);; break;} case 289: -#line 1333 "./parse.y" +#line 1331 "./parse.y" {yyerror ("Invalid init statement"); RECOVER;; break;} case 290: -#line 1338 "./parse.y" +#line 1336 "./parse.y" { /* We now declare the loop body. The loop is declared as a for loop. */ @@ -3627,11 +3625,11 @@ case 290: ; break;} case 291: -#line 1350 "./parse.y" +#line 1348 "./parse.y" { yyval.node = size_zero_node; ; break;} case 292: -#line 1352 "./parse.y" +#line 1350 "./parse.y" { /* Init statement recorded within the previously defined block scope */ @@ -3639,7 +3637,7 @@ case 292: ; break;} case 293: -#line 1358 "./parse.y" +#line 1356 "./parse.y" { /* Local variable are recorded within the previously defined block scope */ @@ -3647,94 +3645,94 @@ case 293: ; break;} case 294: -#line 1364 "./parse.y" +#line 1362 "./parse.y" {yyerror ("';' expected"); DRECOVER(for_init_1);; break;} case 295: -#line 1368 "./parse.y" +#line 1366 "./parse.y" {yyval.node = size_zero_node;; break;} case 296: -#line 1370 "./parse.y" +#line 1368 "./parse.y" { yyval.node = build_debugable_stmt (BUILD_LOCATION (), yyvsp[0].node); ; break;} case 297: -#line 1375 "./parse.y" +#line 1373 "./parse.y" { yyval.node = add_stmt_to_compound (NULL_TREE, NULL_TREE, yyvsp[0].node); ; break;} case 298: -#line 1377 "./parse.y" +#line 1375 "./parse.y" { yyval.node = add_stmt_to_compound (yyvsp[-2].node, NULL_TREE, yyvsp[0].node); ; break;} case 299: -#line 1379 "./parse.y" +#line 1377 "./parse.y" {yyerror ("Missing term"); RECOVER;; break;} case 300: -#line 1384 "./parse.y" +#line 1382 "./parse.y" { yyval.node = build_bc_statement (yyvsp[-1].operator.location, 1, NULL_TREE); ; break;} case 301: -#line 1386 "./parse.y" +#line 1384 "./parse.y" { yyval.node = build_bc_statement (yyvsp[-2].operator.location, 1, yyvsp[-1].node); ; break;} case 302: -#line 1388 "./parse.y" +#line 1386 "./parse.y" {yyerror ("Missing term"); RECOVER;; break;} case 303: -#line 1390 "./parse.y" +#line 1388 "./parse.y" {yyerror ("';' expected"); RECOVER;; break;} case 304: -#line 1395 "./parse.y" +#line 1393 "./parse.y" { yyval.node = build_bc_statement (yyvsp[-1].operator.location, 0, NULL_TREE); ; break;} case 305: -#line 1397 "./parse.y" +#line 1395 "./parse.y" { yyval.node = build_bc_statement (yyvsp[-2].operator.location, 0, yyvsp[-1].node); ; break;} case 306: -#line 1399 "./parse.y" +#line 1397 "./parse.y" {yyerror ("Missing term"); RECOVER;; break;} case 307: -#line 1401 "./parse.y" +#line 1399 "./parse.y" {yyerror ("';' expected"); RECOVER;; break;} case 308: -#line 1406 "./parse.y" +#line 1404 "./parse.y" { yyval.node = build_return (yyvsp[-1].operator.location, NULL_TREE); ; break;} case 309: -#line 1408 "./parse.y" +#line 1406 "./parse.y" { yyval.node = build_return (yyvsp[-2].operator.location, yyvsp[-1].node); ; break;} case 310: -#line 1410 "./parse.y" +#line 1408 "./parse.y" {yyerror ("Missing term"); RECOVER;; break;} case 311: -#line 1412 "./parse.y" +#line 1410 "./parse.y" {yyerror ("';' expected"); RECOVER;; break;} case 312: -#line 1417 "./parse.y" +#line 1415 "./parse.y" { yyval.node = build1 (THROW_EXPR, NULL_TREE, yyvsp[-1].node); EXPR_WFL_LINECOL (yyval.node) = yyvsp[-2].operator.location; ; break;} case 313: -#line 1422 "./parse.y" +#line 1420 "./parse.y" {yyerror ("Missing term"); RECOVER;; break;} case 314: -#line 1424 "./parse.y" +#line 1422 "./parse.y" {yyerror ("';' expected"); RECOVER;; break;} case 315: -#line 1429 "./parse.y" +#line 1427 "./parse.y" { yyval.node = build (SYNCHRONIZED_EXPR, NULL_TREE, yyvsp[-2].node, yyvsp[0].node); EXPR_WFL_LINECOL (yyval.node) = @@ -3742,53 +3740,53 @@ case 315: ; break;} case 316: -#line 1435 "./parse.y" +#line 1433 "./parse.y" {yyerror ("'{' expected"); RECOVER;; break;} case 317: -#line 1437 "./parse.y" +#line 1435 "./parse.y" {yyerror ("'(' expected"); RECOVER;; break;} case 318: -#line 1439 "./parse.y" +#line 1437 "./parse.y" {yyerror ("Missing term"); RECOVER;; break;} case 319: -#line 1441 "./parse.y" +#line 1439 "./parse.y" {yyerror ("Missing term"); RECOVER;; break;} case 320: -#line 1446 "./parse.y" +#line 1444 "./parse.y" { if ((1 << yyvsp[0].value) != ACC_SYNCHRONIZED) fatal ("synchronized was '%d' - yyparse", (1 << yyvsp[0].value)); ; break;} case 321: -#line 1454 "./parse.y" +#line 1452 "./parse.y" { yyval.node = build_try_statement (yyvsp[-2].operator.location, yyvsp[-1].node, yyvsp[0].node, NULL_TREE); ; break;} case 322: -#line 1456 "./parse.y" +#line 1454 "./parse.y" { yyval.node = build_try_statement (yyvsp[-2].operator.location, yyvsp[-1].node, NULL_TREE, yyvsp[0].node); ; break;} case 323: -#line 1458 "./parse.y" +#line 1456 "./parse.y" { yyval.node = build_try_statement (yyvsp[-3].operator.location, yyvsp[-2].node, yyvsp[-1].node, yyvsp[0].node); ; break;} case 324: -#line 1460 "./parse.y" +#line 1458 "./parse.y" {yyerror ("'{' expected"); DRECOVER (try_statement);; break;} case 326: -#line 1466 "./parse.y" +#line 1464 "./parse.y" { TREE_CHAIN (yyvsp[0].node) = yyvsp[-1].node; yyval.node = yyvsp[0].node; ; break;} case 327: -#line 1474 "./parse.y" +#line 1472 "./parse.y" { java_method_add_stmt (current_function_decl, yyvsp[0].node); exit_block (); @@ -3796,7 +3794,7 @@ case 327: ; break;} case 328: -#line 1482 "./parse.y" +#line 1480 "./parse.y" { /* We add a block to define a scope for formal_parameter (CCBP). The formal parameter is @@ -3814,179 +3812,179 @@ case 328: ; break;} case 329: -#line 1498 "./parse.y" +#line 1496 "./parse.y" {yyerror ("'(' expected"); RECOVER;; break;} case 330: -#line 1500 "./parse.y" +#line 1498 "./parse.y" {yyerror ("Missing term or ')' expected"); DRECOVER (2);; break;} case 331: -#line 1502 "./parse.y" +#line 1500 "./parse.y" {yyerror ("')' expected"); DRECOVER (1);; break;} case 332: -#line 1507 "./parse.y" +#line 1505 "./parse.y" { yyval.node = build (FINALLY_EXPR, NULL_TREE, create_label_decl (generate_name ()), yyvsp[0].node); ; break;} case 333: -#line 1512 "./parse.y" +#line 1510 "./parse.y" {yyerror ("'{' expected"); RECOVER; ; break;} case 337: -#line 1524 "./parse.y" +#line 1522 "./parse.y" { yyval.node = build_this (yyvsp[0].operator.location); ; break;} case 338: -#line 1526 "./parse.y" +#line 1524 "./parse.y" {yyval.node = yyvsp[-1].node;; break;} case 343: -#line 1535 "./parse.y" +#line 1533 "./parse.y" { yyval.node = parse_jdk1_1_error ("class literals"); ; break;} case 344: -#line 1537 "./parse.y" +#line 1535 "./parse.y" { yyval.node = parse_jdk1_1_error ("class literals"); ; break;} case 345: -#line 1539 "./parse.y" +#line 1537 "./parse.y" { yyval.node = parse_jdk1_1_error ("class literals"); ; break;} case 346: -#line 1544 "./parse.y" +#line 1542 "./parse.y" { yyval.node = parse_jdk1_1_error ("class literals"); ; break;} case 347: -#line 1546 "./parse.y" +#line 1544 "./parse.y" {yyerror ("')' expected"); RECOVER;; break;} case 348: -#line 1548 "./parse.y" +#line 1546 "./parse.y" {yyerror ("'class' or 'this' expected" ); RECOVER;; break;} case 349: -#line 1550 "./parse.y" +#line 1548 "./parse.y" {yyerror ("'class' expected" ); RECOVER;; break;} case 350: -#line 1552 "./parse.y" +#line 1550 "./parse.y" {yyerror ("'class' expected" ); RECOVER;; break;} case 351: -#line 1557 "./parse.y" +#line 1555 "./parse.y" { yyval.node = build_new_invocation (yyvsp[-3].node, yyvsp[-1].node); ; break;} case 352: -#line 1559 "./parse.y" +#line 1557 "./parse.y" { yyval.node = build_new_invocation (yyvsp[-2].node, NULL_TREE); ; break;} case 353: -#line 1564 "./parse.y" +#line 1562 "./parse.y" { yyval.node = parse_jdk1_1_error ("inner class instance creation"); ; break;} case 354: -#line 1566 "./parse.y" +#line 1564 "./parse.y" { yyval.node = parse_jdk1_1_error ("inner class instance creation"); ; break;} case 359: -#line 1575 "./parse.y" +#line 1573 "./parse.y" {yyerror ("'(' expected"); DRECOVER(new_1);; break;} case 360: -#line 1577 "./parse.y" +#line 1575 "./parse.y" {yyerror ("'(' expected"); RECOVER;; break;} case 361: -#line 1579 "./parse.y" +#line 1577 "./parse.y" {yyerror ("')' or term expected"); RECOVER;; break;} case 362: -#line 1581 "./parse.y" +#line 1579 "./parse.y" {yyerror ("')' expected"); RECOVER;; break;} case 363: -#line 1583 "./parse.y" +#line 1581 "./parse.y" {YYERROR_NOW; yyerror ("Identifier expected"); RECOVER;; break;} case 364: -#line 1585 "./parse.y" +#line 1583 "./parse.y" {yyerror ("'(' expected"); RECOVER;; break;} case 367: -#line 1595 "./parse.y" +#line 1593 "./parse.y" { yyval.node = tree_cons (NULL_TREE, yyvsp[0].node, NULL_TREE); ctxp->formal_parameter_number = 1; ; break;} case 368: -#line 1600 "./parse.y" +#line 1598 "./parse.y" { ctxp->formal_parameter_number += 1; yyval.node = tree_cons (NULL_TREE, yyvsp[0].node, yyvsp[-2].node); ; break;} case 369: -#line 1605 "./parse.y" +#line 1603 "./parse.y" {yyerror ("Missing term"); RECOVER;; break;} case 370: -#line 1610 "./parse.y" +#line 1608 "./parse.y" { yyval.node = build_newarray_node (yyvsp[-1].node, yyvsp[0].node, 0); ; break;} case 371: -#line 1612 "./parse.y" +#line 1610 "./parse.y" { yyval.node = build_newarray_node (yyvsp[-1].node, yyvsp[0].node, 0); ; break;} case 372: -#line 1614 "./parse.y" +#line 1612 "./parse.y" { yyval.node = build_newarray_node (yyvsp[-2].node, yyvsp[-1].node, ctxp->osb_number); ; break;} case 373: -#line 1616 "./parse.y" +#line 1614 "./parse.y" { yyval.node = build_newarray_node (yyvsp[-2].node, yyvsp[-1].node, ctxp->osb_number); ; break;} case 374: -#line 1620 "./parse.y" +#line 1618 "./parse.y" { yyval.node = parse_jdk1_1_error ("anonymous array"); ; break;} case 375: -#line 1622 "./parse.y" +#line 1620 "./parse.y" { yyval.node = parse_jdk1_1_error ("anonymous array"); ; break;} case 376: -#line 1624 "./parse.y" +#line 1622 "./parse.y" {yyerror ("'[' expected"); DRECOVER ("]");; break;} case 377: -#line 1626 "./parse.y" +#line 1624 "./parse.y" {yyerror ("']' expected"); RECOVER;; break;} case 378: -#line 1631 "./parse.y" +#line 1629 "./parse.y" { yyval.node = build_tree_list (NULL_TREE, yyvsp[0].node); ; break;} case 379: -#line 1633 "./parse.y" +#line 1631 "./parse.y" { yyval.node = tree_cons (NULL_TREE, yyvsp[0].node, yyval.node); ; break;} case 380: -#line 1638 "./parse.y" +#line 1636 "./parse.y" { EXPR_WFL_LINECOL (yyvsp[-1].node) = yyvsp[-2].operator.location; yyval.node = yyvsp[-1].node; ; break;} case 381: -#line 1643 "./parse.y" +#line 1641 "./parse.y" {yyerror ("']' expected"); RECOVER;; break;} case 382: -#line 1645 "./parse.y" +#line 1643 "./parse.y" { yyerror ("Missing term"); yyerror ("']' expected"); @@ -3994,23 +3992,23 @@ case 382: ; break;} case 383: -#line 1654 "./parse.y" +#line 1652 "./parse.y" { ctxp->osb_number = 1; ; break;} case 384: -#line 1656 "./parse.y" +#line 1654 "./parse.y" { ctxp->osb_number++; ; break;} case 385: -#line 1658 "./parse.y" +#line 1656 "./parse.y" { yyerror ("']' expected"); RECOVER;; break;} case 386: -#line 1663 "./parse.y" +#line 1661 "./parse.y" { yyval.node = make_qualified_primary (yyvsp[-2].node, yyvsp[0].node, yyvsp[-1].operator.location); ; break;} case 387: -#line 1665 "./parse.y" +#line 1663 "./parse.y" { tree super_wfl = build_wfl_node (super_identifier_node, @@ -4020,19 +4018,19 @@ case 387: ; break;} case 388: -#line 1673 "./parse.y" +#line 1671 "./parse.y" {yyerror ("Field expected"); DRECOVER (super_field_acces);; break;} case 389: -#line 1678 "./parse.y" +#line 1676 "./parse.y" { yyval.node = build_method_invocation (yyvsp[-2].node, NULL_TREE); ; break;} case 390: -#line 1680 "./parse.y" +#line 1678 "./parse.y" { yyval.node = build_method_invocation (yyvsp[-3].node, yyvsp[-1].node); ; break;} case 391: -#line 1682 "./parse.y" +#line 1680 "./parse.y" { if (TREE_CODE (yyvsp[-4].node) == THIS_EXPR) yyval.node = build_this_super_qualified_invocation @@ -4045,7 +4043,7 @@ case 391: ; break;} case 392: -#line 1693 "./parse.y" +#line 1691 "./parse.y" { if (TREE_CODE (yyvsp[-5].node) == THIS_EXPR) yyval.node = build_this_super_qualified_invocation @@ -4058,121 +4056,121 @@ case 392: ; break;} case 393: -#line 1704 "./parse.y" +#line 1702 "./parse.y" { yyval.node = build_this_super_qualified_invocation (0, yyvsp[-2].node, NULL_TREE, yyvsp[-4].operator.location, yyvsp[-3].operator.location); ; break;} case 394: -#line 1709 "./parse.y" +#line 1707 "./parse.y" { yyval.node = build_this_super_qualified_invocation (0, yyvsp[-3].node, yyvsp[-1].node, yyvsp[-5].operator.location, yyvsp[-4].operator.location); ; break;} case 395: -#line 1718 "./parse.y" +#line 1716 "./parse.y" { yyerror ("'(' expected"); DRECOVER (method_invocation); ; break;} case 396: -#line 1720 "./parse.y" +#line 1718 "./parse.y" { yyerror ("'(' expected"); DRECOVER (method_invocation); ; break;} case 397: -#line 1725 "./parse.y" +#line 1723 "./parse.y" { yyval.node = build_array_ref (yyvsp[-2].operator.location, yyvsp[-3].node, yyvsp[-1].node); ; break;} case 398: -#line 1727 "./parse.y" +#line 1725 "./parse.y" { yyval.node = build_array_ref (yyvsp[-2].operator.location, yyvsp[-3].node, yyvsp[-1].node); ; break;} case 399: -#line 1729 "./parse.y" +#line 1727 "./parse.y" { yyerror ("Missing term and ']' expected"); DRECOVER(array_access); ; break;} case 400: -#line 1734 "./parse.y" +#line 1732 "./parse.y" { yyerror ("']' expected"); DRECOVER(array_access); ; break;} case 401: -#line 1739 "./parse.y" +#line 1737 "./parse.y" { yyerror ("Missing term and ']' expected"); DRECOVER(array_access); ; break;} case 402: -#line 1744 "./parse.y" +#line 1742 "./parse.y" { yyerror ("']' expected"); DRECOVER(array_access); ; break;} case 407: -#line 1759 "./parse.y" +#line 1757 "./parse.y" { yyval.node = build_incdec (yyvsp[0].operator.token, yyvsp[0].operator.location, yyvsp[-1].node, 1); ; break;} case 408: -#line 1764 "./parse.y" +#line 1762 "./parse.y" { yyval.node = build_incdec (yyvsp[0].operator.token, yyvsp[0].operator.location, yyvsp[-1].node, 1); ; break;} case 411: -#line 1771 "./parse.y" +#line 1769 "./parse.y" {yyval.node = build_unaryop (yyvsp[-1].operator.token, yyvsp[-1].operator.location, yyvsp[0].node); ; break;} case 412: -#line 1773 "./parse.y" +#line 1771 "./parse.y" {yyval.node = build_unaryop (yyvsp[-1].operator.token, yyvsp[-1].operator.location, yyvsp[0].node); ; break;} case 414: -#line 1776 "./parse.y" +#line 1774 "./parse.y" {yyerror ("Missing term"); RECOVER; break;} case 415: -#line 1778 "./parse.y" +#line 1776 "./parse.y" {yyerror ("Missing term"); RECOVER; break;} case 416: -#line 1783 "./parse.y" +#line 1781 "./parse.y" {yyval.node = build_incdec (yyvsp[-1].operator.token, yyvsp[-1].operator.location, yyvsp[0].node, 0); ; break;} case 417: -#line 1785 "./parse.y" +#line 1783 "./parse.y" {yyerror ("Missing term"); RECOVER; break;} case 418: -#line 1790 "./parse.y" +#line 1788 "./parse.y" {yyval.node = build_incdec (yyvsp[-1].operator.token, yyvsp[-1].operator.location, yyvsp[0].node, 0); ; break;} case 419: -#line 1792 "./parse.y" +#line 1790 "./parse.y" {yyerror ("Missing term"); RECOVER; break;} case 421: -#line 1798 "./parse.y" +#line 1796 "./parse.y" {yyval.node = build_unaryop (yyvsp[-1].operator.token, yyvsp[-1].operator.location, yyvsp[0].node); ; break;} case 422: -#line 1800 "./parse.y" +#line 1798 "./parse.y" {yyval.node = build_unaryop (yyvsp[-1].operator.token, yyvsp[-1].operator.location, yyvsp[0].node); ; break;} case 424: -#line 1803 "./parse.y" +#line 1801 "./parse.y" {yyerror ("Missing term"); RECOVER; break;} case 425: -#line 1805 "./parse.y" +#line 1803 "./parse.y" {yyerror ("Missing term"); RECOVER; break;} case 426: -#line 1810 "./parse.y" +#line 1808 "./parse.y" { tree type = yyvsp[-3].node; while (ctxp->osb_number--) @@ -4181,15 +4179,15 @@ case 426: ; break;} case 427: -#line 1817 "./parse.y" +#line 1815 "./parse.y" { yyval.node = build_cast (yyvsp[-3].operator.location, yyvsp[-2].node, yyvsp[0].node); ; break;} case 428: -#line 1819 "./parse.y" +#line 1817 "./parse.y" { yyval.node = build_cast (yyvsp[-3].operator.location, yyvsp[-2].node, yyvsp[0].node); ; break;} case 429: -#line 1821 "./parse.y" +#line 1819 "./parse.y" { char *ptr; while (ctxp->osb_number--) @@ -4203,11 +4201,11 @@ case 429: ; break;} case 430: -#line 1833 "./parse.y" +#line 1831 "./parse.y" {yyerror ("']' expected, invalid type expression");; break;} case 431: -#line 1835 "./parse.y" +#line 1833 "./parse.y" { if (ctxp->prevent_ese != lineno) yyerror ("Invalid type expression"); RECOVER; @@ -4215,239 +4213,243 @@ case 431: ; break;} case 432: -#line 1841 "./parse.y" +#line 1839 "./parse.y" {yyerror ("Missing term"); RECOVER;; break;} case 433: -#line 1843 "./parse.y" +#line 1841 "./parse.y" {yyerror ("Missing term"); RECOVER;; break;} case 434: -#line 1845 "./parse.y" +#line 1843 "./parse.y" {yyerror ("Missing term"); RECOVER;; break;} case 436: -#line 1851 "./parse.y" +#line 1849 "./parse.y" { yyval.node = build_binop (BINOP_LOOKUP (yyvsp[-1].operator.token), yyvsp[-1].operator.location, yyvsp[-2].node, yyvsp[0].node); ; break;} case 437: -#line 1856 "./parse.y" +#line 1854 "./parse.y" { yyval.node = build_binop (BINOP_LOOKUP (yyvsp[-1].operator.token), yyvsp[-1].operator.location, yyvsp[-2].node, yyvsp[0].node); ; break;} case 438: -#line 1861 "./parse.y" +#line 1859 "./parse.y" { yyval.node = build_binop (BINOP_LOOKUP (yyvsp[-1].operator.token), yyvsp[-1].operator.location, yyvsp[-2].node, yyvsp[0].node); ; break;} case 439: -#line 1866 "./parse.y" +#line 1864 "./parse.y" {yyerror ("Missing term"); RECOVER;; break;} case 440: -#line 1868 "./parse.y" +#line 1866 "./parse.y" {yyerror ("Missing term"); RECOVER;; break;} case 441: -#line 1870 "./parse.y" +#line 1868 "./parse.y" {yyerror ("Missing term"); RECOVER;; break;} case 443: -#line 1876 "./parse.y" +#line 1874 "./parse.y" { yyval.node = build_binop (BINOP_LOOKUP (yyvsp[-1].operator.token), yyvsp[-1].operator.location, yyvsp[-2].node, yyvsp[0].node); ; break;} case 444: -#line 1881 "./parse.y" +#line 1879 "./parse.y" { yyval.node = build_binop (BINOP_LOOKUP (yyvsp[-1].operator.token), yyvsp[-1].operator.location, yyvsp[-2].node, yyvsp[0].node); ; break;} case 445: -#line 1886 "./parse.y" +#line 1884 "./parse.y" {yyerror ("Missing term"); RECOVER;; break;} case 446: -#line 1888 "./parse.y" +#line 1886 "./parse.y" {yyerror ("Missing term"); RECOVER;; break;} case 448: -#line 1894 "./parse.y" +#line 1892 "./parse.y" { yyval.node = build_binop (BINOP_LOOKUP (yyvsp[-1].operator.token), yyvsp[-1].operator.location, yyvsp[-2].node, yyvsp[0].node); ; break;} case 449: -#line 1899 "./parse.y" +#line 1897 "./parse.y" { yyval.node = build_binop (BINOP_LOOKUP (yyvsp[-1].operator.token), yyvsp[-1].operator.location, yyvsp[-2].node, yyvsp[0].node); ; break;} case 450: -#line 1904 "./parse.y" +#line 1902 "./parse.y" { yyval.node = build_binop (BINOP_LOOKUP (yyvsp[-1].operator.token), yyvsp[-1].operator.location, yyvsp[-2].node, yyvsp[0].node); ; break;} case 451: -#line 1909 "./parse.y" +#line 1907 "./parse.y" {yyerror ("Missing term"); RECOVER;; break;} case 452: -#line 1911 "./parse.y" +#line 1909 "./parse.y" {yyerror ("Missing term"); RECOVER;; break;} case 453: -#line 1913 "./parse.y" +#line 1911 "./parse.y" {yyerror ("Missing term"); RECOVER;; break;} case 455: -#line 1919 "./parse.y" +#line 1917 "./parse.y" { yyval.node = build_binop (BINOP_LOOKUP (yyvsp[-1].operator.token), yyvsp[-1].operator.location, yyvsp[-2].node, yyvsp[0].node); ; break;} case 456: -#line 1924 "./parse.y" +#line 1922 "./parse.y" { yyval.node = build_binop (BINOP_LOOKUP (yyvsp[-1].operator.token), yyvsp[-1].operator.location, yyvsp[-2].node, yyvsp[0].node); ; break;} case 457: -#line 1929 "./parse.y" +#line 1927 "./parse.y" { yyval.node = build_binop (BINOP_LOOKUP (yyvsp[-1].operator.token), yyvsp[-1].operator.location, yyvsp[-2].node, yyvsp[0].node); ; break;} case 458: -#line 1934 "./parse.y" +#line 1932 "./parse.y" { yyval.node = build_binop (BINOP_LOOKUP (yyvsp[-1].operator.token), yyvsp[-1].operator.location, yyvsp[-2].node, yyvsp[0].node); ; break;} +case 459: +#line 1937 "./parse.y" +{ yyval.node = build_binop (INSTANCEOF_EXPR, yyvsp[-1].operator.location, yyvsp[-2].node, yyvsp[0].node); ; + break;} case 460: -#line 1940 "./parse.y" +#line 1939 "./parse.y" {yyerror ("Missing term"); RECOVER;; break;} case 461: -#line 1942 "./parse.y" +#line 1941 "./parse.y" {yyerror ("Missing term"); RECOVER;; break;} case 462: -#line 1944 "./parse.y" +#line 1943 "./parse.y" {yyerror ("Missing term"); RECOVER;; break;} case 463: -#line 1946 "./parse.y" +#line 1945 "./parse.y" {yyerror ("Missing term"); RECOVER;; break;} case 464: -#line 1948 "./parse.y" +#line 1947 "./parse.y" {yyerror ("Invalid reference type"); RECOVER;; break;} case 466: -#line 1954 "./parse.y" +#line 1953 "./parse.y" { yyval.node = build_binop (BINOP_LOOKUP (yyvsp[-1].operator.token), yyvsp[-1].operator.location, yyvsp[-2].node, yyvsp[0].node); ; break;} case 467: -#line 1959 "./parse.y" +#line 1958 "./parse.y" { yyval.node = build_binop (BINOP_LOOKUP (yyvsp[-1].operator.token), yyvsp[-1].operator.location, yyvsp[-2].node, yyvsp[0].node); ; break;} case 468: -#line 1964 "./parse.y" +#line 1963 "./parse.y" {yyerror ("Missing term"); RECOVER;; break;} case 469: -#line 1966 "./parse.y" +#line 1965 "./parse.y" {yyerror ("Missing term"); RECOVER;; break;} case 471: -#line 1972 "./parse.y" +#line 1971 "./parse.y" { yyval.node = build_binop (BINOP_LOOKUP (yyvsp[-1].operator.token), yyvsp[-1].operator.location, yyvsp[-2].node, yyvsp[0].node); ; break;} case 472: -#line 1977 "./parse.y" +#line 1976 "./parse.y" {yyerror ("Missing term"); RECOVER;; break;} case 474: -#line 1983 "./parse.y" +#line 1982 "./parse.y" { yyval.node = build_binop (BINOP_LOOKUP (yyvsp[-1].operator.token), yyvsp[-1].operator.location, yyvsp[-2].node, yyvsp[0].node); ; break;} case 475: -#line 1988 "./parse.y" +#line 1987 "./parse.y" {yyerror ("Missing term"); RECOVER;; break;} case 477: -#line 1994 "./parse.y" +#line 1993 "./parse.y" { yyval.node = build_binop (BINOP_LOOKUP (yyvsp[-1].operator.token), yyvsp[-1].operator.location, yyvsp[-2].node, yyvsp[0].node); ; break;} case 478: -#line 1999 "./parse.y" +#line 1998 "./parse.y" {yyerror ("Missing term"); RECOVER;; break;} case 480: -#line 2005 "./parse.y" +#line 2004 "./parse.y" { yyval.node = build_binop (BINOP_LOOKUP (yyvsp[-1].operator.token), yyvsp[-1].operator.location, yyvsp[-2].node, yyvsp[0].node); ; break;} case 481: -#line 2010 "./parse.y" +#line 2009 "./parse.y" {yyerror ("Missing term"); RECOVER;; break;} case 483: -#line 2016 "./parse.y" +#line 2015 "./parse.y" { yyval.node = build_binop (BINOP_LOOKUP (yyvsp[-1].operator.token), yyvsp[-1].operator.location, yyvsp[-2].node, yyvsp[0].node); ; break;} case 484: -#line 2021 "./parse.y" +#line 2020 "./parse.y" {yyerror ("Missing term"); RECOVER;; break;} case 486: -#line 2027 "./parse.y" +#line 2026 "./parse.y" { yyval.node = build (CONDITIONAL_EXPR, NULL_TREE, yyvsp[-4].node, yyvsp[-2].node, yyvsp[0].node); EXPR_WFL_LINECOL (yyval.node) = yyvsp[-3].operator.location; ; break;} case 487: -#line 2032 "./parse.y" +#line 2031 "./parse.y" { YYERROR_NOW; yyerror ("Missing term"); @@ -4455,19 +4457,19 @@ case 487: ; break;} case 488: -#line 2038 "./parse.y" +#line 2037 "./parse.y" {yyerror ("Missing term"); DRECOVER (2);; break;} case 489: -#line 2040 "./parse.y" +#line 2039 "./parse.y" {yyerror ("Missing term"); DRECOVER (3);; break;} case 492: -#line 2050 "./parse.y" +#line 2049 "./parse.y" { yyval.node = build_assignment (yyvsp[-1].operator.token, yyvsp[-1].operator.location, yyvsp[-2].node, yyvsp[0].node); ; break;} case 493: -#line 2052 "./parse.y" +#line 2051 "./parse.y" { if (ctxp->prevent_ese != lineno) yyerror ("Missing term"); @@ -4672,7 +4674,7 @@ yyerrhandle: yystate = yyn; goto yynewstate; } -#line 2078 "./parse.y" +#line 2077 "./parse.y" @@ -4696,7 +4698,10 @@ java_push_parser_context () new->next = ctxp; ctxp = new; if (ctxp->next) - ctxp->incomplete_class = ctxp->next->incomplete_class; + { + ctxp->incomplete_class = ctxp->next->incomplete_class; + ctxp->gclass_list = ctxp->next->gclass_list; + } } /* If the first file of a file list was a class file, no context @@ -4740,12 +4745,17 @@ java_pop_parser_context (generate) int generate; { tree current; - struct parser_ctxt *toFree = ctxp; - struct parser_ctxt *next = ctxp->next; + struct parser_ctxt *toFree, *next; + if (!ctxp) + return; + + toFree = ctxp; + next = ctxp->next; if (next) { next->incomplete_class = ctxp->incomplete_class; + next->gclass_list = ctxp->gclass_list; lineno = ctxp->lineno; finput = ctxp->finput; current_class = ctxp->current_class; @@ -4857,6 +4867,24 @@ parse_error (msg) java_error (msg); } +static void +issue_warning_error_from_context (cl, msg) + tree cl; + char *msg; +{ + char *saved; + + ctxp->elc.line = EXPR_WFL_LINENO (cl); + ctxp->elc.col = (EXPR_WFL_COLNO (cl) == 0xfff ? -1 : EXPR_WFL_COLNO (cl)); + + /* We have a CL, that's a good reason for using it if it contains data */ + saved = ctxp->filename; + if (TREE_CODE (cl) == EXPR_WITH_FILE_LOCATION && EXPR_WFL_FILENAME_NODE (cl)) + ctxp->filename = EXPR_WFL_FILENAME (cl); + parse_error (msg); + ctxp->filename = saved; +} + /* Issue an error message at a current source line CL */ static void @@ -4877,10 +4905,7 @@ parse_error_context VPROTO ((tree cl, char *msg, ...)) vsprintf (buffer, msg, ap); force_error = 1; - ctxp->elc.line = EXPR_WFL_LINENO (cl); - ctxp->elc.col = (EXPR_WFL_COLNO (cl) == 0xfff ? -1 : EXPR_WFL_COLNO (cl)); - - parse_error (buffer); + issue_warning_error_from_context (cl, buffer); force_error = 0; } @@ -4904,10 +4929,7 @@ parse_warning_context VPROTO ((tree cl, char *msg, ...)) vsprintf (buffer, msg, ap); force_error = do_warning = 1; - ctxp->elc.line = EXPR_WFL_LINENO (cl); - ctxp->elc.col = (EXPR_WFL_COLNO (cl) == 0xfff ? -1 : EXPR_WFL_COLNO (cl)); - - parse_error (buffer); + issue_warning_error_from_context (cl, buffer); do_warning = force_error = 0; } @@ -5160,9 +5182,7 @@ static tree maybe_create_class_interface_decl (decl, qualified_name, cl) tree decl, qualified_name, cl; { - if (decl) - DECL_ARTIFICIAL (decl) = 1; /* FIXME */ - else + if (!decl) decl = push_class (make_class (), qualified_name); /* Take care of the file and line business */ @@ -5177,6 +5197,10 @@ maybe_create_class_interface_decl (decl, qualified_name, cl) /* Link the declaration to the already seen ones */ TREE_CHAIN (decl) = ctxp->class_list; ctxp->class_list = decl; + + /* Create a new node in the global list */ + ctxp->gclass_list = tree_cons (NULL_TREE, decl, ctxp->gclass_list); + /* Install a new dependency list element */ create_jdep_list (ctxp); @@ -5199,11 +5223,12 @@ add_superinterfaces (decl, interface_list) defined. */ for (node = interface_list; node; node = TREE_CHAIN (node)) { - tree current = TREE_PURPOSE (node), interface_decl; - if ((interface_decl = IDENTIFIER_CLASS_VALUE (EXPR_WFL_NODE (current)))) + tree current = TREE_PURPOSE (node); + tree idecl = IDENTIFIER_CLASS_VALUE (EXPR_WFL_NODE (current)); + if (idecl && CLASS_LOADED_P (TREE_TYPE (idecl))) { - if (!parser_check_super_interface (interface_decl, decl, current)) - parser_add_interface (decl, interface_decl, current); + if (!parser_check_super_interface (idecl, decl, current)) + parser_add_interface (decl, idecl, current); } else register_incomplete_type (JDEP_INTERFACE, @@ -5271,6 +5296,7 @@ create_class (flags, id, super, interfaces) class_id = parser_qualified_classname (id); decl = IDENTIFIER_CLASS_VALUE (class_id); + ctxp->current_parsed_class_un = EXPR_WFL_NODE (id); EXPR_WFL_NODE (id) = class_id; /* Basic check: scope, redefinition, modifiers */ @@ -5323,6 +5349,9 @@ create_class (flags, id, super, interfaces) CLASS_COMPLETE_P (decl) = 1; add_superinterfaces (decl, interfaces); + /* Eventually sets the @deprecated tag flag */ + CHECK_DEPRECATED (decl); + return decl; } @@ -5452,9 +5481,10 @@ register_fields (flags, type, variable_list) } /* Set lineno to the line the field was found and create a - declaration for it */ + declaration for it. Eventually sets the @deprecated tag flag. */ lineno = EXPR_WFL_LINENO (cl); field_decl = add_field (class_type, current_name, type, flags); + CHECK_DEPRECATED (field_decl); /* Check if we must chain. */ if (must_chain) @@ -5471,12 +5501,16 @@ register_fields (flags, type, variable_list) /* The field is declared static */ if (flags & ACC_STATIC) { - /* FIXME */ if (flags & ACC_FINAL) - ; - /* Otherwise, the field should be initialized in - . This field is remembered so we can - generate later. */ + { + if (DECL_LANG_SPECIFIC (field_decl) == NULL) + DECL_LANG_SPECIFIC (field_decl) = (struct lang_decl *) + permalloc (sizeof (struct lang_decl_var)); + DECL_LOCAL_STATIC_VALUE (field_decl) = + TREE_OPERAND (init, 1); + } + /* Otherwise, the field should be initialized in . + This field is remembered so we can generate later */ else { INITIALIZED_P (field_decl) = 1; @@ -5484,10 +5518,9 @@ register_fields (flags, type, variable_list) ctxp->static_initialized = init; } } - /* A non-static field declared with an immediate - initialization is to be initialized in , if - any. This field is remembered to be processed at the - time of the generation of . */ + /* A non-static field declared with an immediate initialization is + to be initialized in , if any. This field is remembered + to be processed at the time of the generation of . */ else { INITIALIZED_P (field_decl) = 1; @@ -5584,7 +5617,7 @@ method_header (flags, type, mdecl, throws) tree meth = TREE_VALUE (mdecl); tree id = TREE_PURPOSE (mdecl); tree this_class = TREE_TYPE (ctxp->current_parsed_class); - tree meth_name, returned_type, current; + tree meth_name, returned_type, current, orig_arg; int saved_lineno; int constructor_ok = 0; @@ -5612,7 +5645,7 @@ method_header (flags, type, mdecl, throws) int ec = java_error_count; /* 8.6: Constructor declarations: we might be trying to define a method without specifying a return type. */ - if (EXPR_WFL_NODE (id) != DECL_NAME (ctxp->current_parsed_class)) + if (EXPR_WFL_NODE (id) != ctxp->current_parsed_class_un) parse_error_context (id, "Invalid method declaration, return type required"); /* 8.6.3: Constructor modifiers */ @@ -5674,8 +5707,12 @@ method_header (flags, type, mdecl, throws) register_incomplete_type (patch_stage, type, id, NULL_TREE); } } - else - TREE_TYPE (meth) = type; + else + { + if (TREE_CODE (type) == RECORD_TYPE) + type = promote_type (type); + TREE_TYPE (meth) = type; + } saved_lineno = lineno; /* When defining an abstract or interface method, the curly @@ -5684,6 +5721,9 @@ method_header (flags, type, mdecl, throws) lineno = (ctxp->first_ccb_indent1 ? ctxp->first_ccb_indent1 : EXPR_WFL_LINENO (id)); + /* Remember the original argument list */ + orig_arg = TYPE_ARG_TYPES (meth); + if (patch_stage) /* includes ret type and/or all args */ { jdep *jdep; @@ -5699,28 +5739,15 @@ method_header (flags, type, mdecl, throws) register_incomplete_type (JDEP_METHOD_END, NULL_TREE, meth, NULL_TREE); } else - { - tree signature = build_java_signature (meth); - tree arg, orig_arg; - /* Save original argument list, including argument's names */ - orig_arg = TYPE_ARG_TYPES (meth); - /* Add the method to its class */ - meth = add_method (this_class, flags, meth_name, signature); - /* Fix the method argument list so we have the argument name - information */ - arg = TYPE_ARG_TYPES (TREE_TYPE (meth)); - if (TREE_CODE (TREE_TYPE (meth)) == METHOD_TYPE) - { - TREE_PURPOSE (arg) = this_identifier_node; - arg = TREE_CHAIN (arg); - } - while (orig_arg) - { - TREE_PURPOSE (arg) = TREE_PURPOSE (orig_arg); - orig_arg = TREE_CHAIN (orig_arg); - arg = TREE_CHAIN (arg); - } - } + meth = add_method (this_class, flags, meth_name, + build_java_signature (meth)); + + /* Fix the method argument list so we have the argument name + information */ + fix_method_argument_names (orig_arg, meth); + + /* Register the parameter number and re-install the current line + number */ DECL_MAX_LOCALS (meth) = ctxp->formal_parameter_number+1; lineno = saved_lineno; @@ -5755,9 +5782,30 @@ method_header (flags, type, mdecl, throws) if (constructor_ok) DECL_CONSTRUCTOR_P (meth) = 1; + /* Eventually set the @deprecated tag flag */ + CHECK_DEPRECATED (meth); + return meth; } +static void +fix_method_argument_names (orig_arg, meth) + tree orig_arg, meth; +{ + tree arg = TYPE_ARG_TYPES (TREE_TYPE (meth)); + if (TREE_CODE (TREE_TYPE (meth)) == METHOD_TYPE) + { + TREE_PURPOSE (arg) = this_identifier_node; + arg = TREE_CHAIN (arg); + } + while (orig_arg) + { + TREE_PURPOSE (arg) = TREE_PURPOSE (orig_arg); + orig_arg = TREE_CHAIN (orig_arg); + arg = TREE_CHAIN (arg); + } +} + /* Complete the method declaration with METHOD_BODY. */ static void @@ -5903,6 +5951,9 @@ method_declarator (id, list) type = build_array_from_name (type, type_wfl, name, &name); EXPR_WFL_NODE (wfl_name) = name; + if (TREE_CODE (type) == RECORD_TYPE) + type = promote_type (type); + /* Check redefinition */ for (already = arg_types; already; already = TREE_CHAIN (already)) if (TREE_PURPOSE (already) == name) @@ -6165,11 +6216,16 @@ safe_layout_class (class) tree save_current_class = current_class; char *save_input_filename = input_filename; int save_lineno = lineno; - + push_obstacks (&permanent_obstack, &permanent_obstack); + + if (!CLASS_METHOD_CHECKED_P (class)) + CHECK_METHODS (TYPE_NAME (class)); + CLASS_METHOD_CHECKED_P (class) = 1; + layout_class (class); pop_obstacks (); - + current_class = save_current_class; input_filename = save_input_filename; lineno = save_lineno; @@ -6253,6 +6309,8 @@ java_complete_class () field_type = promote_type (field_type); pop_obstacks (); TREE_TYPE (field_decl) = field_type; + DECL_ALIGN (field_decl) = 0; + layout_decl (field_decl, 0); SOURCE_FRONTEND_DEBUG (("Completed field/var decl `%s' with `%s'", IDENTIFIER_POINTER (DECL_NAME (field_decl)), @@ -6415,7 +6473,6 @@ do_resolve_class (class_type, decl, cl) /* 2- And check for the type in the current compilation unit. If it fails, try with a name qualified with the package name if appropriate. */ - if ((new_class_decl = IDENTIFIER_CLASS_VALUE (TYPE_NAME (class_type)))) { if (!CLASS_LOADED_P (TREE_TYPE (new_class_decl)) && @@ -6428,6 +6485,8 @@ do_resolve_class (class_type, decl, cl) if (!QUALIFIED_P (TYPE_NAME (class_type)) && ctxp->package) TYPE_NAME (class_type) = merge_qualified_name (ctxp->package, TYPE_NAME (class_type)); + if (!(new_class_decl = IDENTIFIER_CLASS_VALUE (TYPE_NAME (class_type)))) + load_class (TYPE_NAME (class_type), 0); if ((new_class_decl = IDENTIFIER_CLASS_VALUE (TYPE_NAME (class_type)))) { if (!CLASS_LOADED_P (TREE_TYPE (new_class_decl)) && @@ -6582,9 +6641,7 @@ get_printable_method_name (decl) if (DECL_CONSTRUCTOR_P (decl)) { name = DECL_NAME (decl); - DECL_NAME (decl) = - DECL_NAME (ctxp->current_parsed_class ? - ctxp->current_parsed_class : current_class); + DECL_NAME (decl) = DECL_NAME (TYPE_NAME (DECL_CONTEXT (decl))); } to_return = lang_printable_name (decl, 0); @@ -6594,6 +6651,28 @@ get_printable_method_name (decl) return to_return; } +/* Reinstall the proper DECL_NAME on METHOD. Return 0 if the method + nevertheless needs to be verfied, 1 otherwise. */ + +static int +reset_method_name (method) + tree method; +{ + if (DECL_NAME (method) != clinit_identifier_node + && DECL_NAME (method) != finit_identifier_node) + { + /* NAME is just the plain name when Object is being defined */ + if (DECL_CONTEXT (method) != object_type_node) + DECL_NAME (method) = + (DECL_CONSTRUCTOR_P (method) ? init_identifier_node : + (TREE_CODE (DECL_NAME (method)) == EXPR_WITH_FILE_LOCATION ? + EXPR_WFL_NODE (DECL_NAME (method)) : DECL_NAME (method))); + return 0; + } + else + return 1; +} + /* Track method being redefined inside the same class. As a side effect, set DECL_NAME to an IDENTIFIER (prior entering this function it's a FWL, so we can track errors more accurately */ @@ -6607,19 +6686,14 @@ check_method_redefinition (class, method) tree sig = TYPE_LANG_SPECIFIC (TREE_TYPE (method))->signature; /* decl name of artificial and doesn't need to be fixed and checked */ - if (DECL_NAME (method) != clinit_identifier_node - && DECL_NAME (method) != finit_identifier_node) - { - /* NAME is just the plain name when Object is being defined */ - if (class != object_type_node) - name = DECL_NAME (method) = (DECL_CONSTRUCTOR_P (method) ? - init_identifier_node : - EXPR_WFL_NODE (DECL_NAME (method))); - else - name = DECL_NAME (method); - } - else + + /* Reset the method name before running the check. If it returns 1, + the method doesn't need to be verified with respect to method + redeclaration and we return 0 */ + if (reset_method_name (method)) return 0; + + name = DECL_NAME (method); for (redef = TYPE_METHODS (class); redef; redef = TREE_CHAIN (redef)) { @@ -6647,20 +6721,26 @@ static void java_check_regular_methods (class_decl) tree class_decl; { + int saw_constructor = 0; tree method; tree class = CLASS_TO_HANDLE_TYPE (TREE_TYPE (class_decl)); tree super_class = CLASSTYPE_SUPER (class); - int saw_constructor = 0; + tree saved_found_wfl = NULL_TREE, found = NULL_TREE; TYPE_METHODS (class) = nreverse (TYPE_METHODS (class)); /* Should take interfaces into account. FIXME */ for (method = TYPE_METHODS (class); method; method = TREE_CHAIN (method)) { - tree found, sig; + tree sig; tree method_wfl = DECL_NAME (method); int aflags; + /* If we previously found something and its name was saved, + reinstall it now */ + if (found && saved_found_wfl) + DECL_NAME (found) = saved_found_wfl; + /* Check for redefinitions */ if (check_method_redefinition (class, method)) continue; @@ -6675,12 +6755,17 @@ java_check_regular_methods (class_decl) } sig = build_java_argument_signature (TREE_TYPE (method)); - found = lookup_argument_method (super_class, DECL_NAME (method), sig); - /* Nothing overrides or it's a private method */ + /* Nothing overrides or it's a private method. */ if (!found || (found && METHOD_PRIVATE (found))) - continue; + continue; + + /* If found wasn't verified, it's DECL_NAME won't be set properly. + We set it temporarily for the sake of the error report. */ + saved_found_wfl = DECL_NAME (found); + reset_method_name (found); + /* Can't override a method with the same name and different return types. */ if (TREE_TYPE (TREE_TYPE (found)) != TREE_TYPE (TREE_TYPE (method))) @@ -6724,19 +6809,27 @@ java_check_regular_methods (class_decl) (DECL_NAME (TYPE_NAME (DECL_CONTEXT (found))))); continue; } - /* Overriding/hiding public must be public or - overriding/hiding protected must be protected or public */ - if ((METHOD_PUBLIC (found) && !METHOD_PUBLIC (method)) || - (METHOD_PROTECTED (found) - && !(METHOD_PUBLIC (method) || METHOD_PROTECTED (method)))) + + aflags = get_access_flags_from_decl (found); + /* - Overriding/hiding public must be public + - Overriding/hiding protected must be protected or public + - If the overriden or hidden method has default (package) + access, then the overriding or hiding method must not be + private; otherwise, a compile-time error occurs */ + if ((METHOD_PUBLIC (found) && !METHOD_PUBLIC (method)) + || (METHOD_PROTECTED (found) + && !(METHOD_PUBLIC (method) || METHOD_PROTECTED (method))) + || (!(aflags & (ACC_PUBLIC | ACC_PRIVATE | ACC_STATIC)) + && METHOD_PRIVATE (method))) { parse_error_context (method_wfl, "Methods can't be overridden to be more private. Method `%s' is " - "%s in class `%s'", lang_printable_name (found, 0), - (METHOD_PUBLIC (found) ? "public" : "protected"), - IDENTIFIER_POINTER - (DECL_NAME (TYPE_NAME (DECL_CONTEXT (found))))); + "not %s in class `%s'", lang_printable_name (method, 0), + (METHOD_PUBLIC (method) ? "public" : + (METHOD_PRIVATE (method) ? "private" : "protected")), + IDENTIFIER_POINTER (DECL_NAME + (TYPE_NAME (DECL_CONTEXT (found))))); continue; } @@ -6746,9 +6839,10 @@ java_check_regular_methods (class_decl) /* If the method has default access in an other package, then issue a warning that the current method doesn't override the - one that was found elsewhere */ - aflags = get_access_flags_from_decl (found); - if ((!aflags || (aflags > ACC_PROTECTED)) + one that was found elsewhere. Do not issue this warning when + the match was found in java.lang.Object. */ + if (DECL_CONTEXT (found) != object_type_node + && (!aflags || (aflags > ACC_PROTECTED)) && !class_in_current_package (DECL_CONTEXT (found))) parse_warning_context (method_wfl, "Method `%s' in class `%s' does not " @@ -6758,10 +6852,16 @@ java_check_regular_methods (class_decl) IDENTIFIER_POINTER (DECL_NAME (class_decl)), IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (DECL_CONTEXT (found))))); - /* Check on (default) package access. FIXME. */ /* Inheriting multiple methods with the same signature. FIXME */ } + /* Don't forget eventual pending found and saved_found_wfl. Take + into account that we might have exited because we saw an + aritifical method as the last entry. */ + + if (found && !DECL_ARTIFICIAL (found) && saved_found_wfl) + DECL_NAME (found) = saved_found_wfl; + TYPE_METHODS (class) = nreverse (TYPE_METHODS (class)); if (!saw_constructor) @@ -6818,11 +6918,12 @@ check_throws_clauses (method, method_wfl, found) /* Check abstract method of interface INTERFACE */ static void -java_check_abstract_methods (interface) - tree interface; +java_check_abstract_methods (interface_decl) + tree interface_decl; { int i, n; tree method, basetype_vec, found; + tree interface = TREE_TYPE (interface_decl); for (method = TYPE_METHODS (interface); method; method = TREE_CHAIN (method)) { @@ -6837,16 +6938,20 @@ java_check_abstract_methods (interface) found = lookup_java_interface_method2 (interface, method); if (found) { - char *t = strdup (lang_printable_name (TREE_TYPE (TREE_TYPE (found)), - 0)); + char *t; + tree saved_found_wfl = DECL_NAME (found); + reset_method_name (found); + t = strdup (lang_printable_name (TREE_TYPE (TREE_TYPE (found)), 0)); 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 (DECL_NAME (TYPE_NAME (DECL_CONTEXT (found))))); free (t); continue; + + DECL_NAME (found) = saved_found_wfl; } } @@ -6868,37 +6973,39 @@ java_check_abstract_methods (interface) found = lookup_java_interface_method2 (interface, sub_interface_method); if (found && (found != sub_interface_method)) - 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 (DECL_CONTEXT (sub_interface_method)))), - IDENTIFIER_POINTER - (DECL_NAME (TYPE_NAME (DECL_CONTEXT (found))))); + { + tree saved_found_wfl = DECL_NAME (found); + reset_method_name (found); + 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 + (DECL_CONTEXT (sub_interface_method)))), + IDENTIFIER_POINTER + (DECL_NAME (TYPE_NAME (DECL_CONTEXT (found))))); + DECL_NAME (found) = saved_found_wfl; + } } } } -/* Check the method on all the defined classes. Should be done to the - classes declared in the compilation unit only. FIXME */ +/* Check the method on all the defined classes. Process all the + classes that we compiled from source code for this CU. */ void java_check_methods () { tree current; - for (current = ctxp->class_list; current; current = TREE_CHAIN (current)) - if (CLASS_FROM_SOURCE_P (TREE_TYPE (current))) + for (current = ctxp->gclass_list; current; current = TREE_CHAIN (current)) + if (CLASS_FROM_SOURCE_P (TREE_TYPE (TREE_VALUE (current)))) { - tree class = CLASS_TO_HANDLE_TYPE (TREE_TYPE (current)); - - if (CLASS_INTERFACE (TYPE_NAME (class))) - java_check_abstract_methods (class); - else - java_check_regular_methods (current); + CHECK_METHODS (TREE_VALUE (current)); + CLASS_METHOD_CHECKED_P (TREE_TYPE (TREE_VALUE (current))) = 1; } } @@ -6943,9 +7050,12 @@ lookup_java_method2 (clas, method_decl, do_interface) tree clas, method_decl; int do_interface; { - tree method, method_signature, method_name, method_type; + tree method, method_signature, method_name, method_type, name; + method_signature = build_java_argument_signature (TREE_TYPE (method_decl)); - method_name = DECL_NAME (method_decl); + name = DECL_NAME (method_decl); + method_name = (TREE_CODE (name) == EXPR_WITH_FILE_LOCATION ? + EXPR_WFL_NODE (name) : name); method_type = TREE_TYPE (TREE_TYPE (method_decl)); while (clas != NULL_TREE) @@ -6954,12 +7064,12 @@ lookup_java_method2 (clas, method_decl, do_interface) method != NULL_TREE; method = TREE_CHAIN (method)) { tree method_sig = build_java_argument_signature (TREE_TYPE (method)); - if (DECL_NAME (method) == method_name + tree name = DECL_NAME (method); + if ((TREE_CODE (name) == EXPR_WITH_FILE_LOCATION ? + EXPR_WFL_NODE (name) : name) == method_name && method_sig == method_signature && TREE_TYPE (TREE_TYPE (method)) != method_type) - { - return method; - } + return method; } clas = (do_interface ? NULL_TREE : CLASSTYPE_SUPER (clas)); } @@ -7048,8 +7158,6 @@ find_in_imports (class_type) { TYPE_NAME (class_type) = EXPR_WFL_NODE (TREE_PURPOSE (import)); QUALIFIED_P (TYPE_NAME (class_type)) = 1; - return check_pkg_class_access (TYPE_NAME (class_type), - TREE_PURPOSE (import)); } return 0; } @@ -7273,6 +7381,49 @@ find_in_imports_on_demand (class_type) return (seen_once < 0 ? 0 : seen_once); /* It's ok not to have found */ } +static tree +resolve_package (pkg, next) + tree pkg, *next; +{ + tree type_name = NULL_TREE; + char *name = IDENTIFIER_POINTER (EXPR_WFL_NODE (pkg)); + + /* 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); + } + else + return NULL_TREE; /* FIXME, search all imported packages. */ + + return type_name; +} + +static tree +lookup_package_type (name, from) + char *name; + int from; +{ + char subname [128]; + char *sub = &name[from+1]; + while (*sub != '.' && *sub) + sub++; + strncpy (subname, name, sub-name); + subname [sub-name] = '\0'; + return get_identifier (subname); +} + /* Check that CLASS_NAME refers to a PUBLIC class. Return 0 if no access violations were found, 1 otherwise. */ @@ -7619,16 +7770,21 @@ add_stmt_to_compound (existing, type, stmt) /* Hold THIS for the scope of the current public method decl. */ static tree current_this; -/* Layout all class found during parsing. Also fixes the order of - several field related lists. */ +/* Layout all class found during parsing. Also fixes the order of some + lists. */ void java_layout_classes () { tree current; - for (current = ctxp->class_list; current; current = TREE_CHAIN (current)) + + java_check_methods (); + /* Error reported by the caller */ + if (java_error_count) + return; + for (current = ctxp->gclass_list; current; current = TREE_CHAIN (current)) { - current_class = TREE_TYPE (current); + current_class = TREE_TYPE (TREE_VALUE (current)); /* Reverse the fields if it's necessary (they've already reversed if the dummy field has been inserted at the @@ -7640,6 +7796,10 @@ java_layout_classes () /* Do a layout if necessary */ if (!TYPE_SIZE (current_class) || (current_class == object_type_node)) safe_layout_class (current_class); + + /* Error reported by the caller */ + if (java_error_count) + return; } } @@ -7678,7 +7838,9 @@ java_complete_expand_methods () restore_line_number_status (0); } } - else + else if (METHOD_ABSTRACT (decl) || METHOD_NATIVE (decl)) + continue; + else java_complete_expand_method (decl); } @@ -7733,6 +7895,7 @@ java_complete_expand_method (mdecl) if (BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (mdecl))) java_complete_tree (BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (mdecl))); + /* Don't go any further if we've found error(s) during the expansion */ if (!java_error_count) @@ -7892,6 +8055,13 @@ java_expand_finals () void java_expand_classes () { + ctxp = ctxp_for_generation; + /* If we found error earlier, we don't want to report then twice. */ + if (java_error_count || !ctxp) + return; + java_layout_classes (); + java_parse_abort_on_error (); + for (; ctxp_for_generation; ctxp_for_generation = ctxp_for_generation->next) { ctxp = ctxp_for_generation; @@ -8023,8 +8193,9 @@ cut_identifier_in_qualified (wfl) /* Resolve the expression name NAME. Return its decl. */ static tree -resolve_expression_name (id) +resolve_expression_name (id, orig) tree id; + tree *orig; { tree name = EXPR_WFL_NODE (id); tree decl; @@ -8043,6 +8214,7 @@ resolve_expression_name (id) decl = lookup_field_wrapper (current_class, name); if (decl) { + tree value = NULL_TREE; int fs = FIELD_STATIC (decl); /* Instance variable (8.3.1.1) can't appear within static method, static initializer or initializer for @@ -8066,9 +8238,20 @@ resolve_expression_name (id) "constructor has been called", IDENTIFIER_POINTER (name)); return error_mark_node; } + /* The field is final. We may use its value instead */ + if (fs && FIELD_FINAL (decl)) + value = java_complete_tree (DECL_LOCAL_STATIC_VALUE (decl)); + + /* Otherwise build what it takes to access the field */ decl = build_field_ref ((fs ? NULL_TREE : current_this), current_class, name); - return (fs ? build_class_init (current_class, decl) : decl); + if (fs && !flag_emit_class_files) + decl = build_class_init (current_class, decl); + /* We may be asked to save the real field access node */ + if (orig) + *orig = decl; + /* And we return what we got */ + return (value ? value : decl); } /* Fall down to error report on undefined variable */ } @@ -8076,6 +8259,8 @@ resolve_expression_name (id) /* 6.5.5.2 Qualified Expression Names */ else { + if (orig) + *orig = NULL_TREE; qualify_ambiguous_name (id); /* 15.10.1 Field Access Using a Primary and/or Expression Name */ /* 15.10.2: Accessing Superclass Members using super */ @@ -8121,12 +8306,24 @@ resolve_field_access (qual_wfl, field_decl, field_type) field_ref = decl; else if (DECL_P (decl)) { + int static_final_found = 0; + if (!type_found) + type_found = DECL_CONTEXT (decl); is_static = DECL_P (decl) && FIELD_STATIC (decl); - field_ref = build_field_ref ((is_static ? NULL_TREE : where_found), - type_found, DECL_NAME (decl)); + if (FIELD_FINAL (decl) + && JPRIMITIVE_TYPE_P (TREE_TYPE (decl)) + && DECL_LANG_SPECIFIC (decl) + && DECL_LOCAL_STATIC_VALUE (decl)) + { + field_ref = java_complete_tree (DECL_LOCAL_STATIC_VALUE (decl)); + static_final_found = 1; + } + else + field_ref = build_field_ref ((is_static ? NULL_TREE : where_found), + type_found, DECL_NAME (decl)); if (field_ref == error_mark_node) return error_mark_node; - if (is_static) + if (is_static && !static_final_found) { field_ref = build_class_init (type_found, field_ref); /* If the static field was identified by an expression that @@ -8169,7 +8366,6 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found) tree qual_wfl = QUAL_WFL (q); /* 15.10.1 Field Access Using a Primary */ - switch (TREE_CODE (qual_wfl)) { case CALL_EXPR: @@ -8217,6 +8413,7 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found) continue; case CONDITIONAL_EXPR: + case STRING_CST: *where_found = decl = java_complete_tree (qual_wfl); if (decl == error_mark_node) return 1; @@ -8258,7 +8455,7 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found) } /* We have to generate code for intermediate acess */ *where_found = decl = current_this; - type = QUAL_DECL_TYPE (decl); + *type_found = type = QUAL_DECL_TYPE (decl); continue; } @@ -8290,17 +8487,33 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found) assume a variable/class name was meant. */ if (RESOLVE_PACKAGE_NAME_P (qual_wfl)) { - if (from_super || from_cast) - parse_error_context - ((from_cast ? qual_wfl : wfl), - "No variable `%s' defined in class `%s'", - IDENTIFIER_POINTER (EXPR_WFL_NODE (qual_wfl)), - lang_printable_name (type, 0)); + tree name = resolve_package (wfl, &q); + if (name) + { + *where_found = decl = resolve_no_layout (name, qual_wfl); + /* We wan't to be absolutely that the class is laid + out. We're going to search something inside it. */ + *type_found = type = TREE_TYPE (decl); + layout_class (type); + from_type = 1; + /* Should be a list, really. FIXME */ + RESOLVE_EXPRESSION_NAME_P (QUAL_WFL (TREE_CHAIN (q))) = 1; + RESOLVE_PACKAGE_NAME_P (QUAL_WFL (TREE_CHAIN (q))) = 0; + } else - parse_error_context - (qual_wfl, "Undefined variable or class name: `%s'", - IDENTIFIER_POINTER (EXPR_WFL_NODE (qual_wfl))); - return 1; + { + if (from_super || from_cast) + parse_error_context + ((from_cast ? qual_wfl : wfl), + "No variable `%s' defined in class `%s'", + IDENTIFIER_POINTER (EXPR_WFL_NODE (qual_wfl)), + lang_printable_name (type, 0)); + else + parse_error_context + (qual_wfl, "Undefined variable or class name: `%s'", + IDENTIFIER_POINTER (EXPR_WFL_NODE (qual_wfl))); + return 1; + } } /* We have a type name. It's been already resolved when the @@ -8320,6 +8533,7 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found) IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (current_class)))); return 1; } + check_deprecation (qual_wfl, decl); type = TREE_TYPE (decl); from_type = 1; @@ -8336,18 +8550,24 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found) if (!from_super && QUAL_RESOLUTION (q)) { decl = QUAL_RESOLUTION (q); - *type_found = type; + if (!type && !FIELD_STATIC (decl)) + { + *where_found = current_this; + *type_found = type; + } } /* We have to search for a field, knowing the type of its container. The flag FROM_TYPE indicates that we resolved the last member of the expression as a type name, which - means that for the resolution of this field, will check - on other errors than if the it was resolved as a member - of an other field. */ + means that for the resolution of this field, we'll look + for other errors than if it was resolved as a member of + an other field. */ else { int is_static; + tree field_decl_type; /* For layout */ + if (!from_type && !JREFERENCE_TYPE_P (type)) { parse_error_context @@ -8367,6 +8587,17 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found) IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)))); return 1; } + + /* Layout the type of field_decl, since we may need + it. Don't do primitive types or loaded classes */ + if (TREE_CODE (TREE_TYPE (field_decl)) == POINTER_TYPE) + field_decl_type = TREE_TYPE (TREE_TYPE (field_decl)); + else + field_decl_type = TREE_TYPE (field_decl); + if (!JPRIMITIVE_TYPE_P (field_decl_type) + && !CLASS_LOADED_P (field_decl_type)) + resolve_and_layout (DECL_NAME (TYPE_NAME (field_decl_type)), + NULL_TREE); /* Check on accessibility here */ if (not_accessible_p (type, field_decl, from_super)) @@ -8382,6 +8613,7 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found) (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 @@ -8400,8 +8632,9 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found) } from_cast = from_super = 0; - /* If we need to generate something to get a proper handle - on what this field is accessed from, do it now. */ + /* If we need to generate something to get a proper + handle on what this field is accessed from, do it + now. */ if (!is_static) { decl = maybe_access_field (decl, *where_found, *type_found); @@ -8487,6 +8720,40 @@ int not_accessible_p (reference, member, from_super) return 0; } +/* Test deprecated decl access. */ +static void +check_deprecation (wfl, decl) + tree wfl, decl; +{ + char *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) + && !IS_A_COMMAND_LINE_FILENAME_P (get_identifier (file))) + { + char the [20]; + switch (TREE_CODE (decl)) + { + case FUNCTION_DECL: + strcpy (the, "method"); + break; + case FIELD_DECL: + strcpy (the, "field"); + break; + case TYPE_DECL: + strcpy (the, "class"); + break; + default: + fatal ("unexpected DECL code - check_deprecation"); + } + 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 int @@ -8531,10 +8798,8 @@ static tree maybe_access_field (decl, where, type) tree decl, where, type; { - if (DECL_P (decl) && decl != current_this - && (!(TREE_CODE (decl) != PARM_DECL - && FIELD_STATIC (decl))) - && !IDENTIFIER_LOCAL_VALUE (DECL_NAME (decl))) + if (TREE_CODE (decl) == FIELD_DECL && decl != current_this + && !FIELD_STATIC (decl)) decl = build_field_ref (where ? where : current_this, (type ? type : DECL_CONTEXT (decl)), DECL_NAME (decl)); @@ -8555,7 +8820,7 @@ patch_method_invocation_stmt (patch, primary, where, is_static, ret_decl, super) tree wfl = TREE_OPERAND (patch, 0); tree args = TREE_OPERAND (patch, 1); tree name = EXPR_WFL_NODE (wfl); - tree list, class_type; + tree list; int is_static_flag = 0; /* Should be overriden if everything goes well. Otherwise, if @@ -8626,6 +8891,7 @@ patch_method_invocation_stmt (patch, primary, where, is_static, ret_decl, super) free (fct_name); PATCH_METHOD_RETURN_ERROR (); } + args = nreverse (args); } /* We're resolving an expression name */ else @@ -8651,9 +8917,7 @@ patch_method_invocation_stmt (patch, primary, where, is_static, ret_decl, super) args = tree_cons (NULL_TREE, field, nreverse (args)); } - /* CLASS_TYPE is used during the call to not_accessible_p and - IDENTIFIER_WFL will be used to report any problem further */ - class_type = TREE_TYPE (class_decl); + /* IDENTIFIER_WFL will be used to report any problem further */ wfl = identifier_wfl; } /* Resolution of simple names, names generated after a primary: or @@ -8697,8 +8961,11 @@ patch_method_invocation_stmt (patch, primary, where, is_static, ret_decl, super) PATCH_METHOD_RETURN_ERROR (); } - /* Can't instantiate an abstract class */ - if (CLASS_ABSTRACT (class_to_search)) + /* 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) + && TREE_CODE (patch) == NEW_CLASS_EXPR) { parse_error_context (wfl, "Class `%s' is an abstract class. It can't be " @@ -8741,8 +9008,6 @@ patch_method_invocation_stmt (patch, primary, where, is_static, ret_decl, super) args = nreverse (args); if (!METHOD_STATIC (list) && TREE_CODE (patch) != NEW_CLASS_EXPR) args = tree_cons (NULL_TREE, primary ? primary : current_this, args); - - class_type = class_to_search; } /* Merge point of all resolution schemes. If we have nothing, this @@ -8752,18 +9017,19 @@ patch_method_invocation_stmt (patch, primary, where, is_static, ret_decl, super) /* Check accessibility, position the is_static flag, build and return the call */ - if (not_accessible_p (class_type, list, 0)) + if (not_accessible_p (DECL_CONTEXT (list), list, 0)) { char *fct_name = strdup (lang_printable_name (list, 0)); parse_error_context (wfl, "Can't access %s method `%s %s.%s' from `%s'", java_accstring_lookup (get_access_flags_from_decl (list)), lang_printable_name (TREE_TYPE (TREE_TYPE (list)), 0), - IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (class_type))), fct_name, - IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (current_class)))); + IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (DECL_CONTEXT (list)))), + fct_name, IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (current_class)))); free (fct_name); PATCH_METHOD_RETURN_ERROR (); } + check_deprecation (wfl, list); is_static_flag = METHOD_STATIC (list); @@ -8821,9 +9087,14 @@ patch_invoke (patch, method, args, from_super) tree signature = build_java_signature (TREE_TYPE (method)); tree original_call, t, ta; - /* Last step for args: convert build-in types. */ - for (t = TYPE_ARG_TYPES (TREE_TYPE (method)), ta = args; - t && ta; t = TREE_CHAIN (t), ta = TREE_CHAIN (ta)) + /* Last step for args: convert build-in types. If we're dealing with + a new TYPE() type call, the first argument to the constructor + isn't found in the incomming argument list, but delivered by + `new' */ + t = TYPE_ARG_TYPES (TREE_TYPE (method)); + if (TREE_CODE (patch) == NEW_CLASS_EXPR) + t = TREE_CHAIN (t); + for (ta = args; t && 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)) TREE_VALUE (ta) = convert (TREE_VALUE (t), TREE_VALUE (ta)); @@ -8841,6 +9112,11 @@ patch_invoke (patch, method, args, from_super) DECL_CONTEXT (method), signature, args); break; + case INVOKE_INTERFACE: + dtable = invoke_build_dtable (1, args); + func = build_invokeinterface (dtable, DECL_NAME (method), signature); + break; + default: fatal ("Unknown invocation mode `%d' - build_invoke", im); return NULL_TREE; @@ -8916,34 +9192,24 @@ lookup_method_invoke (lc, cl, class, name, arg_list) tree class, name, arg_list; { tree method = make_node (FUNCTION_TYPE); - tree arg_type_list = NULL_TREE; + tree atl = NULL_TREE; /* Arg Type List */ tree signature, list, node; char *candidates; /* Used for error report */ + /* Fix the arguments */ for (node = arg_list; node; node = TREE_CHAIN (node)) { tree current_arg = TREE_TYPE (TREE_VALUE (node)); if (TREE_CODE (current_arg) == RECORD_TYPE) current_arg = promote_type (current_arg); - arg_type_list = tree_cons (NULL_TREE, current_arg, arg_type_list); - } - TYPE_ARG_TYPES (method) = arg_type_list; - - if (!lc) - { - list = find_applicable_accessible_methods_list (class, name, - arg_type_list); - list = find_most_specific_methods_list (list); - } - else - { - TREE_TYPE (method) = void_type_node; - signature = build_java_signature (method); - list = lookup_java_constructor (class, signature); + atl = tree_cons (NULL_TREE, current_arg, atl); } + TYPE_ARG_TYPES (method) = atl; - if (lc && list) - return list; + /* Find all candidates and then refine the list, searching for the + most specific method. */ + list = find_applicable_accessible_methods_list (lc, class, name, atl); + list = find_most_specific_methods_list (list); if (list && !TREE_CHAIN (list)) return TREE_VALUE (list); @@ -8984,10 +9250,12 @@ lookup_method_invoke (lc, cl, class, name, arg_list) return NULL_TREE; } -/* 15.11.2.1: Find Methods that are Applicable and Accessible */ +/* 15.11.2.1: Find Methods that are Applicable and Accessible. LC is 1 + when we're looking for a constructor. */ static tree -find_applicable_accessible_methods_list (class, name, arglist) +find_applicable_accessible_methods_list (lc, class, name, arglist) + int lc; tree class, name, arglist; { tree method; @@ -8998,10 +9266,12 @@ find_applicable_accessible_methods_list (class, name, arglist) for (method = TYPE_METHODS (class); method != NULL_TREE; method = TREE_CHAIN (method)) { - /* Names have to match and we're not looking for constructor */ - if (DECL_NAME (method) != name || DECL_CONSTRUCTOR_P (method)) + if (lc && !DECL_CONSTRUCTOR_P (method)) continue; - + else if (!lc && (DECL_CONSTRUCTOR_P (method) + || DECL_NAME (method) != name)) + continue; + if (argument_types_convertible (method, arglist)) { /* Retain accessible methods only */ @@ -9012,7 +9282,9 @@ find_applicable_accessible_methods_list (class, name, arglist) all_list = tree_cons (NULL_TREE, method, list); } } - class = CLASSTYPE_SUPER (class); + /* When dealing with constructor, stop here, otherwise search + other classes */ + class = (lc ? NULL_TREE : CLASSTYPE_SUPER (class)); } /* Either return the list obtained or all selected (but inaccessible) methods for better error report. */ @@ -9196,8 +9468,9 @@ qualify_ambiguous_name (id) /* Do one more interation to set things up */ super_found = again = 1; } - /* Loop one more time if we're dealing with ?: up front */ - if (TREE_CODE (qual_wfl) == CONDITIONAL_EXPR) + /* Loop one more time if we're dealing with ?: or a string constant */ + if (TREE_CODE (qual_wfl) == CONDITIONAL_EXPR + || TREE_CODE (qual_wfl) == STRING_CST) { qual = TREE_CHAIN (qual); qual_wfl = QUAL_WFL (qual); @@ -9307,8 +9580,10 @@ not_initialized_as_it_should_p (decl) { if (DECL_P (decl)) { - if (TREE_CODE (decl) == FIELD_DECL - && METHOD_STATIC (current_function_decl)) + if (FIELD_FINAL (decl)) + return 0; + if (TREE_CODE (decl) == FIELD_DECL + && (METHOD_STATIC (current_function_decl))) return 0; return DECL_P (decl) && !INITIALIZED_P (decl); } @@ -9458,7 +9733,7 @@ java_complete_tree (node) case EXPR_WITH_FILE_LOCATION: if (!EXPR_WFL_NODE (node) /* Or a PRIMARY flag ? */ || TREE_CODE (EXPR_WFL_NODE (node)) == IDENTIFIER_NODE) - return resolve_expression_name (node); + return resolve_expression_name (node, NULL); else { EXPR_WFL_NODE (node) = java_complete_tree (EXPR_WFL_NODE (node)); @@ -9556,7 +9831,8 @@ java_complete_tree (node) an error during the assignment. In any cases, the assignment operation fails. */ if (TREE_CODE (TREE_OPERAND (node, 1)) != EXPR_WITH_FILE_LOCATION - && TREE_TYPE (TREE_OPERAND (node, 1)) != error_mark_node) + && TREE_TYPE (TREE_OPERAND (node, 1)) != error_mark_node + && TREE_TYPE (TREE_OPERAND (node, 1))) patch_assignment (node, wfl_op1, wfl_op2); /* Now, we still mark the lhs as initialized */ @@ -9613,6 +9889,11 @@ java_complete_tree (node) } return patch_binop (node, wfl_op1, wfl_op2); + case INSTANCEOF_EXPR: + wfl_op1 = TREE_OPERAND (node, 0); + COMPLETE_CHECK_OP_0 (node); + return patch_binop (node, wfl_op1, TREE_OPERAND (node, 1)); + case UNARY_PLUS_EXPR: case NEGATE_EXPR: case TRUTH_NOT_EXPR: @@ -9706,8 +9987,10 @@ complete_function_arguments (node) `+' operator. Build `parm.toString()' and expand it. */ if ((temp = patch_string (parm))) parm = temp; - TREE_VALUE (cn) = parm; + /* Inline PRIMTYPE.TYPE read access */ + parm = maybe_build_primttype_type_ref (parm, wfl); + TREE_VALUE (cn) = parm; if (not_initialized_as_it_should_p (parm)) { ERROR_VARIABLE_NOT_INITIALIZED (wfl, EXPR_WFL_NODE (wfl)); @@ -9948,6 +10231,47 @@ print_int_node (node) return buffer; } +/* Return 1 if you an assignment of a FINAL is attempted */ + +static int +check_final_assignment (lvalue, wfl) + tree lvalue, wfl; +{ + if (DECL_P (lvalue) && FIELD_FINAL (lvalue)) + { + parse_error_context + (wfl, "Can't assign a value to the final variable `%s'", + IDENTIFIER_POINTER (EXPR_WFL_NODE (wfl))); + return 1; + } + return 0; +} + +/* Inline references to java.lang.PRIMTYPE.TYPE when accessed in + read. This is needed to avoid circularities in the implementation + of these fields in libjava. */ + +static tree +maybe_build_primttype_type_ref (rhs, wfl) + tree rhs, wfl; +{ + tree to_return = NULL_TREE; + tree rhs_type = TREE_TYPE (rhs); + if (TREE_CODE (rhs) == COMPOUND_EXPR) + { + tree n = TREE_OPERAND (rhs, 1); + if (TREE_CODE (n) == VAR_DECL + && DECL_NAME (n) == TYPE_identifier_node + && rhs_type == class_ptr_type) + { + char *self_name = IDENTIFIER_POINTER (EXPR_WFL_NODE (wfl)); + if (!strncmp (self_name, "java.lang.", 10)) + to_return = build_primtype_type_ref (self_name); + } + } + return (to_return ? to_return : rhs ); +} + /* 15.25 Assignment operators. */ static tree @@ -9957,19 +10281,14 @@ patch_assignment (node, wfl_op1, wfl_op2) tree wfl_op2; { tree rhs = TREE_OPERAND (node, 1); - tree lvalue = TREE_OPERAND (node, 0); + tree lvalue = TREE_OPERAND (node, 0), llvalue; tree lhs_type, rhs_type, new_rhs = NULL_TREE; int error_found = 0; int lvalue_from_array = 0; /* Can't assign to a final. */ - if (DECL_P (lvalue) && FIELD_FINAL (lvalue)) - { - parse_error_context - (wfl_op1, "Can't assign a value to the final variable `%s'", - IDENTIFIER_POINTER (EXPR_WFL_NODE (wfl_op1))); - error_found = 1; - } + if (check_final_assignment (lvalue, wfl_op1)) + error_found = 1; EXPR_WFL_LINECOL (wfl_operator) = EXPR_WFL_LINECOL (node); @@ -9992,8 +10311,18 @@ patch_assignment (node, wfl_op1, wfl_op2) /* Or a function return slot */ else if (TREE_CODE (lvalue) == RESULT_DECL) lhs_type = TREE_TYPE (lvalue); - /* Otherwise, this is an error */ - else + /* Otherwise, we might want to try to write into an optimized static + final, this is an of a different nature, reported further on. */ + else if (TREE_CODE (wfl_op1) == EXPR_WITH_FILE_LOCATION + && resolve_expression_name (wfl_op1, &llvalue) + && check_final_assignment (llvalue, wfl_op1)) + { + error_found = 1; + /* What we should do instead is resetting the all the flags + previously set, exchange lvalue for llvalue and continue. */ + return error_mark_node; + } + else { parse_error_context (wfl_op1, "Invalid left hand side of assignment"); error_found = 1; @@ -10060,6 +10389,22 @@ patch_assignment (node, wfl_op1, wfl_op2) INITIALIZED_P (rhs) = 1; } + /* Inline read access to java.lang.PRIMTYPE.TYPE */ + rhs = maybe_build_primttype_type_ref (rhs, wfl_op2); + + if (TREE_CODE (rhs) == COMPOUND_EXPR) + { + tree n = TREE_OPERAND (rhs, 1); + if (TREE_CODE (n) == VAR_DECL + && DECL_NAME (n) == TYPE_identifier_node + && rhs_type == class_ptr_type) + { + char *self_name = IDENTIFIER_POINTER (EXPR_WFL_NODE (wfl_op2)); + if (!strncmp (self_name, "java.lang.", 10)) + rhs = build_primtype_type_ref (self_name); + } + } + if (error_found) return error_mark_node; @@ -10113,9 +10458,15 @@ try_builtin_assignconv (wfl_op1, lhs_type, rhs) tree new_rhs = NULL_TREE; tree rhs_type = TREE_TYPE (rhs); + /* Zero accepted everywhere */ + 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 */ - if (valid_builtin_assignconv_identity_widening_p (lhs_type, rhs_type)) + 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): @@ -10150,20 +10501,32 @@ static int valid_builtin_assignconv_identity_widening_p (lhs_type, rhs_type) tree lhs_type, rhs_type; { - int all_primitive = + int all_primitive; + + if (lhs_type == rhs_type) + return 1; + + all_primitive = JPRIMITIVE_TYPE_P (lhs_type) && JPRIMITIVE_TYPE_P (rhs_type); if (!all_primitive) return 0; - if (lhs_type == rhs_type) - return 1; - /* byte, even if it's smaller than a char can't be converted into a char. Short can't too, but the < test below takes care of that */ if (lhs_type == char_type_node && rhs_type == byte_type_node) return 0; + /* Accept all promoted type here. Note, we can't use <= in the test + below, because we still need to bounce out assignments of short + to char and the likes */ + if (lhs_type == int_type_node + && (rhs_type == promoted_byte_type_node + || rhs_type == promoted_short_type_node + || rhs_type == promoted_char_type_node + || rhs_type == promoted_boolean_type_node)) + return 1; + if (JINTEGRAL_TYPE_P (rhs_type) && ((TYPE_PRECISION (rhs_type) < TYPE_PRECISION (lhs_type)) || (JFLOAT_TYPE_P (lhs_type) && @@ -10188,6 +10551,8 @@ valid_ref_assignconv_cast_p (source, dest, cast) tree dest; int cast; { + if (JNULLP_TYPE_P (source)) + return 1; if (TREE_CODE (source) == POINTER_TYPE) source = TREE_TYPE (source); if (TREE_CODE (dest) == POINTER_TYPE) @@ -10313,8 +10678,8 @@ valid_method_invocation_conversion_p (dest, source) return ((JPRIMITIVE_TYPE_P (source) && JPRIMITIVE_TYPE_P (dest) && valid_builtin_assignconv_identity_widening_p (dest, source)) - || (JREFERENCE_TYPE_P (source) - && JREFERENCE_TYPE_P (dest) + || ((JREFERENCE_TYPE_P (source) || JNULLP_TYPE_P (source)) + && (JREFERENCE_TYPE_P (dest) || JNULLP_TYPE_P (dest)) && valid_ref_assignconv_cast_p (source, dest, 0))); } @@ -10326,9 +10691,7 @@ build_binop (op, op_location, op1, op2) int op_location; tree op1, op2; { - tree binop; - - binop = build (op, NULL_TREE, op1, op2); + tree binop = build (op, NULL_TREE, op1, op2); TREE_SIDE_EFFECTS (binop) = 1; /* Store the location of the operator, for better error report. The string of the operator will be rebuild based on the OP value. */ @@ -10533,7 +10896,63 @@ patch_binop (node, wfl_op1, wfl_op2) TREE_SET_CODE (node, RSHIFT_EXPR); } break; + + /* 15.19.1 Type Comparison Operator instaceof */ + case INSTANCEOF_EXPR: + + TREE_TYPE (node) = boolean_type_node; + + if (!(op2_type = resolve_type_during_patch (op2))) + return error_mark_node; + + /* The first operand must be a reference type or the null type */ + if (!JREFERENCE_TYPE_P (op1_type) && op1 != null_pointer_node) + error_found = 1; /* Error reported further below */ + + /* The second operand must be a reference type */ + if (!JREFERENCE_TYPE_P (op2_type)) + { + SET_WFL_OPERATOR (wfl_operator, node, wfl_op2); + parse_error_context + (wfl_operator, "Invalid argument `%s' for `instanceof'", + lang_printable_name (op2_type, 0)); + error_found = 1; + } + + if (!error_found && valid_ref_assignconv_cast_p (op1_type, op2_type, 1)) + { + /* If the first operand is null, the result is always false */ + if (op1 == null_pointer_node) + return boolean_false_node; + /* Otherwise we have to invoke instance of to figure it out */ + else + { + tree call = + build (CALL_EXPR, boolean_type_node, + build_address_of (soft_instanceof_node), + tree_cons + (NULL_TREE, op1, + build_tree_list (NULL_TREE, + build_class_ref (op2_type))), + NULL_TREE); + TREE_SIDE_EFFECTS (call) = 1; + return call; + } + } + /* There is no way the expression operand can be an instance of + the type operand. This is a compile time error. */ + else + { + char *t1 = strdup (lang_printable_name (op1_type, 0)); + SET_WFL_OPERATOR (wfl_operator, node, wfl_op1); + 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 */ case BIT_AND_EXPR: @@ -10609,7 +11028,7 @@ patch_binop (node, wfl_op1, wfl_op2) case NE_EXPR: /* 15.20.1 Numerical Equality Operators == and != */ /* Binary numeric promotion is performed on the operands */ - if (JPRIMITIVE_TYPE_P (op1_type) && JPRIMITIVE_TYPE_P (op2_type)) + 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 != */ @@ -10618,10 +11037,14 @@ patch_binop (node, wfl_op1, wfl_op2) ; /* Nothing to do here */ /* 15.20.3 Reference Equality Operators == and != */ - /* Types have to be either references or the null type */ + /* 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 || (JREFERENCE_TYPE_P (op1_type) && JREFERENCE_TYPE_P (op2_type) - && ((op1_type == op2_type)))) + && (valid_ref_assignconv_cast_p (op1_type, op2_type, 1) + || 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 @@ -10942,22 +11365,25 @@ patch_unaryop (node, wfl_op) case PREINCREMENT_EXPR: /* 15.14.2 Prefix Decrement Operator -- */ case PREDECREMENT_EXPR: - if (!DECL_P (op) && !(TREE_CODE (op) == INDIRECT_REF + if (!DECL_P (op) && !((TREE_CODE (op) == INDIRECT_REF + || TREE_CODE (op) == COMPONENT_REF) && JPRIMITIVE_TYPE_P (TREE_TYPE (op)))) { - parse_error_context (wfl_operator, "Invalid argument to `%s'", - operator_string (node)); - TREE_TYPE (node) = error_mark_node; - error_found = 1; - } - else if (DECL_P (op) && FIELD_FINAL (op)) - { - parse_error_context - (wfl_op, "Can't assign a value to the final variable `%s'", - IDENTIFIER_POINTER (EXPR_WFL_NODE (wfl_op))); + tree lvalue; + /* Before screaming, check that we're not in fact trying to + increment a optimized static final access, in which case + we issue an different error message. */ + if (!(TREE_CODE (wfl_op) == EXPR_WITH_FILE_LOCATION + && resolve_expression_name (wfl_op, &lvalue) + && check_final_assignment (lvalue, wfl_op))) + parse_error_context (wfl_operator, "Invalid argument to `%s'", + operator_string (node)); TREE_TYPE (node) = error_mark_node; error_found = 1; } + else if (check_final_assignment (op, wfl_op)) + 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. */ @@ -11078,7 +11504,10 @@ resolve_type_during_patch (type) return NULL_TREE; } else - return TREE_TYPE (type_decl); + { + CLASS_LOADED_P (TREE_TYPE (type_decl)) = 1; + return TREE_TYPE (type_decl); + } } return type; } @@ -11113,6 +11542,10 @@ patch_cast (node, wfl_operator) return convert (cast_type, op); } + /* null can be casted to references */ + if (op == null_pointer_node && JREFERENCE_TYPE_P (cast_type)) + return build_null_of_type (cast_type); + /* 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) @@ -11142,6 +11575,17 @@ patch_cast (node, wfl_operator) return error_mark_node; } +/* Build a null constant and give it the type TYPE. */ + +static tree +build_null_of_type (type) + tree type; +{ + tree node = build_int_2 (0, 0); + TREE_TYPE (node) = promote_type (type); + return node; +} + /* Build an ARRAY_REF incomplete tree node. Note that operand 1 isn't a list of indices. */ static tree @@ -11215,8 +11659,11 @@ patch_array_ref (node, wfl_array, wfl_index) return error_mark_node; index = convert (promoted_index_type, index); - if (TREE_CODE (array_type) == RECORD_TYPE) - array_type = promote_type (TYPE_ARRAY_ELEMENT (array_type)); + array_type = TYPE_ARRAY_ELEMENT (array_type); + if (TREE_CODE (array_type) == RECORD_TYPE + && !JPRIMITIVE_TYPE_P (TREE_TYPE (array_type))) + array_type = promote_type (array_type); + if (flag_emit_class_files) { TREE_OPERAND (node, 0)= array; @@ -11402,7 +11849,6 @@ patch_return (node) tree return_exp = TREE_OPERAND (node, 0); tree meth = current_function_decl; tree mtype = TREE_TYPE (TREE_TYPE (current_function_decl)); - tree modify; int error_found = 0; TREE_TYPE (node) = error_mark_node; @@ -11436,12 +11882,33 @@ patch_return (node) return error_mark_node; } - /* If we have a return_exp, build a modify expression and expand it */ + /* If we have a return_exp, build a modify expression and expand + it. Note: at that point, the assignment is declared valid, but we + may want to carry some more hacks */ if (return_exp) { - modify = build (MODIFY_EXPR, NULL_TREE, DECL_RESULT (meth), return_exp); + tree exp = java_complete_tree (return_exp); + tree modify, patched; + + /* If the function returned value and EXP are booleans, EXP has + to be converted into the type of DECL_RESULT, which is integer + (see complete_start_java_method) */ + if (TREE_TYPE (exp) == boolean_type_node && + TREE_TYPE (TREE_TYPE (meth)) == boolean_type_node) + exp = convert_to_integer (TREE_TYPE (DECL_RESULT (meth)), exp); + + /* `null' can be assigned to a function returning a reference */ + if (JREFERENCE_TYPE_P (TREE_TYPE (TREE_TYPE (meth))) && + exp == null_pointer_node) + exp = build_null_of_type (TREE_TYPE (TREE_TYPE (meth))); + + 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); + if (modify != error_mark_node) { TREE_SIDE_EFFECTS (modify) = 1; diff --git a/gcc/java/parse.h b/gcc/java/parse.h index bb9477a..7f783dc 100644 --- a/gcc/java/parse.h +++ b/gcc/java/parse.h @@ -47,7 +47,7 @@ extern tree stabilize_reference PROTO ((tree)); #define RULE( rule ) #endif -#ifdef SOURCE_FRONTEND_DEBUG +#ifdef VERBOSE_SKELETON #undef SOURCE_FRONTEND_DEBUG #define SOURCE_FRONTEND_DEBUG(X) \ {if (!quiet_flag) {printf ("* "); printf X; putchar ('\n');} } @@ -182,6 +182,8 @@ extern tree stabilize_reference PROTO ((tree)); || (TREE_CODE (TYPE) == POINTER_TYPE \ && TREE_CODE (TREE_TYPE (TYPE)) == \ RECORD_TYPE))) +#define JNULLP_TYPE_P(TYPE) ((TYPE) && (TREE_CODE (TYPE) == POINTER_TYPE) \ + && (TYPE) == TREE_TYPE (null_pointer_node)) /* Other predicate */ #define DECL_P(NODE) (NODE && (TREE_CODE (NODE) == PARM_DECL \ @@ -523,6 +525,32 @@ static jdeplist *reverse_jdep_list (); *ret_decl = NULL_TREE; \ return error_mark_node; \ } + +/* Convenient macro to check. Assumes that CLASS is a CLASS_DECL. */ +#define CHECK_METHODS(CLASS) \ + { \ + if (CLASS_INTERFACE ((CLASS))) \ + java_check_abstract_methods ((CLASS)); \ + else \ + java_check_regular_methods ((CLASS)); \ + } + +/* Using and reseting the @deprecated tag flag */ +#define CHECK_DEPRECATED(DECL) \ + { \ + if (ctxp->deprecated) \ + DECL_DEPRECATED (DECL) = 1; \ + ctxp->deprecated = 0; \ + } + +/* Register an impor */ +#define REGISTER_IMPORT(WHOLE, NAME) \ +{ \ + IS_A_SINGLE_IMPORT_CLASSFILE_NAME_P ((NAME)) = 1; \ + node = build_tree_list ((WHOLE), (NAME)); \ + TREE_CHAIN (node) = ctxp->import_list; \ + ctxp->import_list = node; \ +} /* Parser context data structure. */ struct parser_ctxt { @@ -542,6 +570,7 @@ struct parser_ctxt { int minus_seen; /* Integral literal overflow */ int lineno; /* Current lineno */ int java_error_flag; /* Report error when true */ + int deprecated; /* @deprecated tag seen */ /* This section is defined only if we compile jc1 */ #ifndef JC1_LITE @@ -561,7 +590,9 @@ struct parser_ctxt { tree incomplete_class; /* List of non-complete classes */ tree current_parsed_class; /* Class currently parsed */ + tree current_parsed_class_un; /* Curr. parsed class unqualified name */ tree class_list; /* List of classes in a CU */ + tree gclass_list; /* All classes seen so far. */ jdeplist *classd_list; /* Classe dependencies in a CU */ tree non_static_initialized; /* List of non static initialized fields */ @@ -604,9 +635,11 @@ static void check_modifiers_consistency PROTO ((int)); static tree lookup_cl PROTO ((tree)); static tree lookup_java_method2 PROTO ((tree, tree, int)); static tree method_header PROTO ((int, tree, tree, tree)); +static void fix_method_argument_names PROTO ((tree ,tree)); static tree method_declarator PROTO ((tree, tree)); static void parse_error_context VPROTO ((tree cl, char *msg, ...)); static void parse_warning_context VPROTO ((tree cl, char *msg, ...)); +static void issue_warning_error_from_context PROTO ((tree, char *msg)); static tree parse_jdk1_1_error PROTO ((char *)); static void complete_class_report_errors PROTO ((jdep *)); static int process_imports PROTO ((void)); @@ -614,6 +647,8 @@ static void read_import_dir PROTO ((tree)); static int find_in_imports_on_demand PROTO ((tree)); static int find_in_imports PROTO ((tree)); static int check_pkg_class_access PROTO ((tree, tree)); +static tree resolve_package PROTO ((tree, tree *)); +static tree lookup_package_type PROTO ((char *, int)); static tree resolve_class PROTO ((tree, tree, tree)); static tree do_resolve_class PROTO ((tree, tree, tree)); static void declare_local_variables PROTO ((int, tree, tree)); @@ -623,7 +658,7 @@ static void expand_start_java_method PROTO ((tree)); static tree find_name_in_single_imports PROTO ((tree)); static void check_abstract_method_header PROTO ((tree)); static tree lookup_java_interface_method2 PROTO ((tree, tree)); -static tree resolve_expression_name PROTO ((tree)); +static tree resolve_expression_name PROTO ((tree, tree *)); static tree maybe_create_class_interface_decl PROTO ((tree, tree, tree)); static int check_class_interface_creation PROTO ((int, int, tree, tree, tree, tree)); @@ -633,7 +668,8 @@ static int breakdown_qualified PROTO ((tree *, tree *, tree)); static tree resolve_and_layout PROTO ((tree, tree)); static tree resolve_no_layout PROTO ((tree, tree)); static int invocation_mode PROTO ((tree, int)); -static tree find_applicable_accessible_methods_list PROTO ((tree, tree, tree)); +static tree find_applicable_accessible_methods_list PROTO ((int, tree, + tree, tree)); static tree find_most_specific_methods_list PROTO ((tree)); static int argument_types_convertible PROTO ((tree, tree)); static tree patch_invoke PROTO ((tree, tree, tree, int)); @@ -654,12 +690,14 @@ static tree build_method_invocation PROTO ((tree, tree)); static tree build_new_invocation PROTO ((tree, tree)); static tree build_assignment PROTO ((int, int, tree, tree)); static tree build_binop PROTO ((enum tree_code, int, tree, tree)); +static int check_final_assignment PROTO ((tree ,tree)); static tree patch_assignment PROTO ((tree, tree, tree )); static tree patch_binop PROTO ((tree, tree, tree)); static tree build_unaryop PROTO ((int, int, tree)); static tree build_incdec PROTO ((int, int, tree, int)); static tree patch_unaryop PROTO ((tree, tree)); static tree build_cast PROTO ((int, tree, tree)); +static tree build_null_of_type PROTO ((tree)); static tree patch_cast PROTO ((tree, tree)); static int valid_ref_assignconv_cast_p PROTO ((tree, tree, int)); static int valid_builtin_assignconv_identity_widening_p PROTO ((tree, tree)); @@ -689,6 +727,7 @@ static tree maybe_access_field PROTO ((tree, tree, tree)); static int complete_function_arguments PROTO ((tree)); static int check_for_static_method_reference PROTO ((tree, tree, tree, tree, tree)); static int not_accessible_p PROTO ((tree, tree, int)); +static void check_deprecation PROTO ((tree, tree)); static int class_in_current_package PROTO ((tree)); static tree build_if_else_statement PROTO ((int, tree, tree, tree)); static tree patch_if_else_statement PROTO ((tree)); @@ -735,6 +774,11 @@ static tree create_artificial_method PROTO ((tree, int, tree, tree, tree)); static void start_artificial_method_body PROTO ((tree)); static void end_artificial_method_body PROTO ((tree)); static tree generate_field_initialization_code PROTO ((tree)); +static int check_method_redefinition PROTO ((tree, tree)); +static int reset_method_name PROTO ((tree)); +static void java_check_regular_methods PROTO ((tree)); +static void java_check_abstract_methods PROTO ((tree)); +static tree maybe_build_primttype_type_ref PROTO ((tree, tree)); void safe_layout_class PROTO ((tree)); void java_complete_class PROTO ((void)); diff --git a/gcc/java/parse.y b/gcc/java/parse.y index c71178f..8d7c676 100644 --- a/gcc/java/parse.y +++ b/gcc/java/parse.y @@ -67,6 +67,7 @@ definitions and other extensions. */ #include "lex.h" #include "parse.h" #include "zipfile.h" +#include "convert.h" /* Number of error found so far. */ int java_error_count; @@ -248,7 +249,7 @@ static tree wfl_to_string = NULL_TREE; %token BOOL_AND_TK AND_TK BOOL_OR_TK OR_TK INCR_TK PLUS_TK %token DECR_TK MINUS_TK MULT_TK DIV_TK XOR_TK REM_TK NEQ_TK %token NEG_TK REL_QM_TK REL_CL_TK NOT_TK LT_TK -%token OP_TK OSB_TK DOT_TK THROW_TK +%token OP_TK OSB_TK DOT_TK THROW_TK INSTANCEOF_TK %type THIS_TK SUPER_TK RETURN_TK BREAK_TK CONTINUE_TK %type CASE_TK DEFAULT_TK TRY_TK CATCH_TK SYNCHRONIZED_TK @@ -409,14 +410,11 @@ single_type_import_declaration: ($2, "Ambiguous class: `%s' and `%s'", IDENTIFIER_POINTER (name), IDENTIFIER_POINTER (err)); + else + REGISTER_IMPORT ($2, last_name) } else - { - IS_A_SINGLE_IMPORT_CLASSFILE_NAME_P (last_name) = 1; - node = build_tree_list ($2, last_name); - TREE_CHAIN (node) = ctxp->import_list; - ctxp->import_list = node; - } + REGISTER_IMPORT ($2, last_name); } | IMPORT_TK error {yyerror ("Missing name"); RECOVER;} @@ -1936,6 +1934,7 @@ relational_expression: $1, $3); } | relational_expression INSTANCEOF_TK reference_type + { $$ = build_binop (INSTANCEOF_EXPR, $2.location, $1, $3); } | relational_expression LT_TK error {yyerror ("Missing term"); RECOVER;} | relational_expression GT_TK error @@ -2098,7 +2097,10 @@ java_push_parser_context () new->next = ctxp; ctxp = new; if (ctxp->next) - ctxp->incomplete_class = ctxp->next->incomplete_class; + { + ctxp->incomplete_class = ctxp->next->incomplete_class; + ctxp->gclass_list = ctxp->next->gclass_list; + } } /* If the first file of a file list was a class file, no context @@ -2142,12 +2144,17 @@ java_pop_parser_context (generate) int generate; { tree current; - struct parser_ctxt *toFree = ctxp; - struct parser_ctxt *next = ctxp->next; + struct parser_ctxt *toFree, *next; + if (!ctxp) + return; + + toFree = ctxp; + next = ctxp->next; if (next) { next->incomplete_class = ctxp->incomplete_class; + next->gclass_list = ctxp->gclass_list; lineno = ctxp->lineno; finput = ctxp->finput; current_class = ctxp->current_class; @@ -2259,6 +2266,24 @@ parse_error (msg) java_error (msg); } +static void +issue_warning_error_from_context (cl, msg) + tree cl; + char *msg; +{ + char *saved; + + ctxp->elc.line = EXPR_WFL_LINENO (cl); + ctxp->elc.col = (EXPR_WFL_COLNO (cl) == 0xfff ? -1 : EXPR_WFL_COLNO (cl)); + + /* We have a CL, that's a good reason for using it if it contains data */ + saved = ctxp->filename; + if (TREE_CODE (cl) == EXPR_WITH_FILE_LOCATION && EXPR_WFL_FILENAME_NODE (cl)) + ctxp->filename = EXPR_WFL_FILENAME (cl); + parse_error (msg); + ctxp->filename = saved; +} + /* Issue an error message at a current source line CL */ static void @@ -2269,6 +2294,7 @@ parse_error_context VPROTO ((tree cl, char *msg, ...)) char *msg; #endif char buffer [4096]; + char *saved; va_list ap; VA_START (ap, msg); @@ -2279,10 +2305,7 @@ parse_error_context VPROTO ((tree cl, char *msg, ...)) vsprintf (buffer, msg, ap); force_error = 1; - ctxp->elc.line = EXPR_WFL_LINENO (cl); - ctxp->elc.col = (EXPR_WFL_COLNO (cl) == 0xfff ? -1 : EXPR_WFL_COLNO (cl)); - - parse_error (buffer); + issue_warning_error_from_context (cl, buffer); force_error = 0; } @@ -2296,6 +2319,7 @@ parse_warning_context VPROTO ((tree cl, char *msg, ...)) char *msg; #endif char buffer [4096]; + char *saved; va_list ap; VA_START (ap, msg); @@ -2306,10 +2330,7 @@ parse_warning_context VPROTO ((tree cl, char *msg, ...)) vsprintf (buffer, msg, ap); force_error = do_warning = 1; - ctxp->elc.line = EXPR_WFL_LINENO (cl); - ctxp->elc.col = (EXPR_WFL_COLNO (cl) == 0xfff ? -1 : EXPR_WFL_COLNO (cl)); - - parse_error (buffer); + issue_warning_error_from_context (cl, buffer); do_warning = force_error = 0; } @@ -2562,9 +2583,7 @@ static tree maybe_create_class_interface_decl (decl, qualified_name, cl) tree decl, qualified_name, cl; { - if (decl) - DECL_ARTIFICIAL (decl) = 1; /* FIXME */ - else + if (!decl) decl = push_class (make_class (), qualified_name); /* Take care of the file and line business */ @@ -2579,6 +2598,10 @@ maybe_create_class_interface_decl (decl, qualified_name, cl) /* Link the declaration to the already seen ones */ TREE_CHAIN (decl) = ctxp->class_list; ctxp->class_list = decl; + + /* Create a new node in the global list */ + ctxp->gclass_list = tree_cons (NULL_TREE, decl, ctxp->gclass_list); + /* Install a new dependency list element */ create_jdep_list (ctxp); @@ -2602,10 +2625,11 @@ add_superinterfaces (decl, interface_list) for (node = interface_list; node; node = TREE_CHAIN (node)) { tree current = TREE_PURPOSE (node), interface_decl; - if ((interface_decl = IDENTIFIER_CLASS_VALUE (EXPR_WFL_NODE (current)))) + tree idecl = IDENTIFIER_CLASS_VALUE (EXPR_WFL_NODE (current)); + if (idecl && CLASS_LOADED_P (TREE_TYPE (idecl))) { - if (!parser_check_super_interface (interface_decl, decl, current)) - parser_add_interface (decl, interface_decl, current); + if (!parser_check_super_interface (idecl, decl, current)) + parser_add_interface (decl, idecl, current); } else register_incomplete_type (JDEP_INTERFACE, @@ -2673,6 +2697,7 @@ create_class (flags, id, super, interfaces) class_id = parser_qualified_classname (id); decl = IDENTIFIER_CLASS_VALUE (class_id); + ctxp->current_parsed_class_un = EXPR_WFL_NODE (id); EXPR_WFL_NODE (id) = class_id; /* Basic check: scope, redefinition, modifiers */ @@ -2725,6 +2750,9 @@ create_class (flags, id, super, interfaces) CLASS_COMPLETE_P (decl) = 1; add_superinterfaces (decl, interfaces); + /* Eventually sets the @deprecated tag flag */ + CHECK_DEPRECATED (decl); + return decl; } @@ -2854,9 +2882,10 @@ register_fields (flags, type, variable_list) } /* Set lineno to the line the field was found and create a - declaration for it */ + declaration for it. Eventually sets the @deprecated tag flag. */ lineno = EXPR_WFL_LINENO (cl); field_decl = add_field (class_type, current_name, type, flags); + CHECK_DEPRECATED (field_decl); /* Check if we must chain. */ if (must_chain) @@ -2873,12 +2902,16 @@ register_fields (flags, type, variable_list) /* The field is declared static */ if (flags & ACC_STATIC) { - /* FIXME */ if (flags & ACC_FINAL) - ; - /* Otherwise, the field should be initialized in - . This field is remembered so we can - generate later. */ + { + if (DECL_LANG_SPECIFIC (field_decl) == NULL) + DECL_LANG_SPECIFIC (field_decl) = (struct lang_decl *) + permalloc (sizeof (struct lang_decl_var)); + DECL_LOCAL_STATIC_VALUE (field_decl) = + TREE_OPERAND (init, 1); + } + /* Otherwise, the field should be initialized in . + This field is remembered so we can generate later */ else { INITIALIZED_P (field_decl) = 1; @@ -2886,10 +2919,9 @@ register_fields (flags, type, variable_list) ctxp->static_initialized = init; } } - /* A non-static field declared with an immediate - initialization is to be initialized in , if - any. This field is remembered to be processed at the - time of the generation of . */ + /* A non-static field declared with an immediate initialization is + to be initialized in , if any. This field is remembered + to be processed at the time of the generation of . */ else { INITIALIZED_P (field_decl) = 1; @@ -2986,7 +3018,7 @@ method_header (flags, type, mdecl, throws) tree meth = TREE_VALUE (mdecl); tree id = TREE_PURPOSE (mdecl); tree this_class = TREE_TYPE (ctxp->current_parsed_class); - tree meth_name, returned_type, current; + tree meth_name, returned_type, current, orig_arg; int saved_lineno; int constructor_ok = 0; @@ -3014,7 +3046,7 @@ method_header (flags, type, mdecl, throws) int ec = java_error_count; /* 8.6: Constructor declarations: we might be trying to define a method without specifying a return type. */ - if (EXPR_WFL_NODE (id) != DECL_NAME (ctxp->current_parsed_class)) + if (EXPR_WFL_NODE (id) != ctxp->current_parsed_class_un) parse_error_context (id, "Invalid method declaration, return type required"); /* 8.6.3: Constructor modifiers */ @@ -3077,7 +3109,11 @@ method_header (flags, type, mdecl, throws) } } else - TREE_TYPE (meth) = type; + { + if (TREE_CODE (type) == RECORD_TYPE) + type = promote_type (type); + TREE_TYPE (meth) = type; + } saved_lineno = lineno; /* When defining an abstract or interface method, the curly @@ -3086,6 +3122,9 @@ method_header (flags, type, mdecl, throws) lineno = (ctxp->first_ccb_indent1 ? ctxp->first_ccb_indent1 : EXPR_WFL_LINENO (id)); + /* Remember the original argument list */ + orig_arg = TYPE_ARG_TYPES (meth); + if (patch_stage) /* includes ret type and/or all args */ { jdep *jdep; @@ -3101,28 +3140,15 @@ method_header (flags, type, mdecl, throws) register_incomplete_type (JDEP_METHOD_END, NULL_TREE, meth, NULL_TREE); } else - { - tree signature = build_java_signature (meth); - tree arg, orig_arg; - /* Save original argument list, including argument's names */ - orig_arg = TYPE_ARG_TYPES (meth); - /* Add the method to its class */ - meth = add_method (this_class, flags, meth_name, signature); - /* Fix the method argument list so we have the argument name - information */ - arg = TYPE_ARG_TYPES (TREE_TYPE (meth)); - if (TREE_CODE (TREE_TYPE (meth)) == METHOD_TYPE) - { - TREE_PURPOSE (arg) = this_identifier_node; - arg = TREE_CHAIN (arg); - } - while (orig_arg) - { - TREE_PURPOSE (arg) = TREE_PURPOSE (orig_arg); - orig_arg = TREE_CHAIN (orig_arg); - arg = TREE_CHAIN (arg); - } - } + meth = add_method (this_class, flags, meth_name, + build_java_signature (meth)); + + /* Fix the method argument list so we have the argument name + information */ + fix_method_argument_names (orig_arg, meth); + + /* Register the parameter number and re-install the current line + number */ DECL_MAX_LOCALS (meth) = ctxp->formal_parameter_number+1; lineno = saved_lineno; @@ -3157,9 +3183,30 @@ method_header (flags, type, mdecl, throws) if (constructor_ok) DECL_CONSTRUCTOR_P (meth) = 1; + /* Eventually set the @deprecated tag flag */ + CHECK_DEPRECATED (meth); + return meth; } +static void +fix_method_argument_names (orig_arg, meth) + tree orig_arg, meth; +{ + tree arg = TYPE_ARG_TYPES (TREE_TYPE (meth)); + if (TREE_CODE (TREE_TYPE (meth)) == METHOD_TYPE) + { + TREE_PURPOSE (arg) = this_identifier_node; + arg = TREE_CHAIN (arg); + } + while (orig_arg) + { + TREE_PURPOSE (arg) = TREE_PURPOSE (orig_arg); + orig_arg = TREE_CHAIN (orig_arg); + arg = TREE_CHAIN (arg); + } +} + /* Complete the method declaration with METHOD_BODY. */ static void @@ -3305,6 +3352,9 @@ method_declarator (id, list) type = build_array_from_name (type, type_wfl, name, &name); EXPR_WFL_NODE (wfl_name) = name; + if (TREE_CODE (type) == RECORD_TYPE) + type = promote_type (type); + /* Check redefinition */ for (already = arg_types; already; already = TREE_CHAIN (already)) if (TREE_PURPOSE (already) == name) @@ -3564,14 +3614,20 @@ void safe_layout_class (class) tree class; { + tree list; tree save_current_class = current_class; char *save_input_filename = input_filename; int save_lineno = lineno; - + push_obstacks (&permanent_obstack, &permanent_obstack); + + if (!CLASS_METHOD_CHECKED_P (class)) + CHECK_METHODS (TYPE_NAME (class)); + CLASS_METHOD_CHECKED_P (class) = 1; + layout_class (class); pop_obstacks (); - + current_class = save_current_class; input_filename = save_input_filename; lineno = save_lineno; @@ -3655,6 +3711,8 @@ java_complete_class () field_type = promote_type (field_type); pop_obstacks (); TREE_TYPE (field_decl) = field_type; + DECL_ALIGN (field_decl) = 0; + layout_decl (field_decl, 0); SOURCE_FRONTEND_DEBUG (("Completed field/var decl `%s' with `%s'", IDENTIFIER_POINTER (DECL_NAME (field_decl)), @@ -3817,7 +3875,6 @@ do_resolve_class (class_type, decl, cl) /* 2- And check for the type in the current compilation unit. If it fails, try with a name qualified with the package name if appropriate. */ - if ((new_class_decl = IDENTIFIER_CLASS_VALUE (TYPE_NAME (class_type)))) { if (!CLASS_LOADED_P (TREE_TYPE (new_class_decl)) && @@ -3830,6 +3887,8 @@ do_resolve_class (class_type, decl, cl) if (!QUALIFIED_P (TYPE_NAME (class_type)) && ctxp->package) TYPE_NAME (class_type) = merge_qualified_name (ctxp->package, TYPE_NAME (class_type)); + if (!(new_class_decl = IDENTIFIER_CLASS_VALUE (TYPE_NAME (class_type)))) + load_class (TYPE_NAME (class_type), 0); if ((new_class_decl = IDENTIFIER_CLASS_VALUE (TYPE_NAME (class_type)))) { if (!CLASS_LOADED_P (TREE_TYPE (new_class_decl)) && @@ -3984,9 +4043,7 @@ get_printable_method_name (decl) if (DECL_CONSTRUCTOR_P (decl)) { name = DECL_NAME (decl); - DECL_NAME (decl) = - DECL_NAME (ctxp->current_parsed_class ? - ctxp->current_parsed_class : current_class); + DECL_NAME (decl) = DECL_NAME (TYPE_NAME (DECL_CONTEXT (decl))); } to_return = lang_printable_name (decl, 0); @@ -3996,6 +4053,28 @@ get_printable_method_name (decl) return to_return; } +/* Reinstall the proper DECL_NAME on METHOD. Return 0 if the method + nevertheless needs to be verfied, 1 otherwise. */ + +static int +reset_method_name (method) + tree method; +{ + if (DECL_NAME (method) != clinit_identifier_node + && DECL_NAME (method) != finit_identifier_node) + { + /* NAME is just the plain name when Object is being defined */ + if (DECL_CONTEXT (method) != object_type_node) + DECL_NAME (method) = + (DECL_CONSTRUCTOR_P (method) ? init_identifier_node : + (TREE_CODE (DECL_NAME (method)) == EXPR_WITH_FILE_LOCATION ? + EXPR_WFL_NODE (DECL_NAME (method)) : DECL_NAME (method))); + return 0; + } + else + return 1; +} + /* Track method being redefined inside the same class. As a side effect, set DECL_NAME to an IDENTIFIER (prior entering this function it's a FWL, so we can track errors more accurately */ @@ -4009,19 +4088,14 @@ check_method_redefinition (class, method) tree sig = TYPE_LANG_SPECIFIC (TREE_TYPE (method))->signature; /* decl name of artificial and doesn't need to be fixed and checked */ - if (DECL_NAME (method) != clinit_identifier_node - && DECL_NAME (method) != finit_identifier_node) - { - /* NAME is just the plain name when Object is being defined */ - if (class != object_type_node) - name = DECL_NAME (method) = (DECL_CONSTRUCTOR_P (method) ? - init_identifier_node : - EXPR_WFL_NODE (DECL_NAME (method))); - else - name = DECL_NAME (method); - } - else + + /* Reset the method name before running the check. If it returns 1, + the method doesn't need to be verified with respect to method + redeclaration and we return 0 */ + if (reset_method_name (method)) return 0; + + name = DECL_NAME (method); for (redef = TYPE_METHODS (class); redef; redef = TREE_CHAIN (redef)) { @@ -4049,20 +4123,26 @@ static void java_check_regular_methods (class_decl) tree class_decl; { + int saw_constructor = 0; tree method; tree class = CLASS_TO_HANDLE_TYPE (TREE_TYPE (class_decl)); tree super_class = CLASSTYPE_SUPER (class); - int saw_constructor = 0; + tree saved_found_wfl = NULL_TREE, found = NULL_TREE; TYPE_METHODS (class) = nreverse (TYPE_METHODS (class)); /* Should take interfaces into account. FIXME */ for (method = TYPE_METHODS (class); method; method = TREE_CHAIN (method)) { - tree found, sig; + tree sig; tree method_wfl = DECL_NAME (method); int aflags; + /* If we previously found something and its name was saved, + reinstall it now */ + if (found && saved_found_wfl) + DECL_NAME (found) = saved_found_wfl; + /* Check for redefinitions */ if (check_method_redefinition (class, method)) continue; @@ -4077,12 +4157,17 @@ java_check_regular_methods (class_decl) } sig = build_java_argument_signature (TREE_TYPE (method)); - found = lookup_argument_method (super_class, DECL_NAME (method), sig); - /* Nothing overrides or it's a private method */ + /* Nothing overrides or it's a private method. */ if (!found || (found && METHOD_PRIVATE (found))) - continue; + continue; + + /* If found wasn't verified, it's DECL_NAME won't be set properly. + We set it temporarily for the sake of the error report. */ + saved_found_wfl = DECL_NAME (found); + reset_method_name (found); + /* Can't override a method with the same name and different return types. */ if (TREE_TYPE (TREE_TYPE (found)) != TREE_TYPE (TREE_TYPE (method))) @@ -4126,19 +4211,27 @@ java_check_regular_methods (class_decl) (DECL_NAME (TYPE_NAME (DECL_CONTEXT (found))))); continue; } - /* Overriding/hiding public must be public or - overriding/hiding protected must be protected or public */ - if ((METHOD_PUBLIC (found) && !METHOD_PUBLIC (method)) || - (METHOD_PROTECTED (found) - && !(METHOD_PUBLIC (method) || METHOD_PROTECTED (method)))) + + aflags = get_access_flags_from_decl (found); + /* - Overriding/hiding public must be public + - Overriding/hiding protected must be protected or public + - If the overriden or hidden method has default (package) + access, then the overriding or hiding method must not be + private; otherwise, a compile-time error occurs */ + if ((METHOD_PUBLIC (found) && !METHOD_PUBLIC (method)) + || (METHOD_PROTECTED (found) + && !(METHOD_PUBLIC (method) || METHOD_PROTECTED (method))) + || (!(aflags & (ACC_PUBLIC | ACC_PRIVATE | ACC_STATIC)) + && METHOD_PRIVATE (method))) { parse_error_context (method_wfl, "Methods can't be overridden to be more private. Method `%s' is " - "%s in class `%s'", lang_printable_name (found, 0), - (METHOD_PUBLIC (found) ? "public" : "protected"), - IDENTIFIER_POINTER - (DECL_NAME (TYPE_NAME (DECL_CONTEXT (found))))); + "not %s in class `%s'", lang_printable_name (method, 0), + (METHOD_PUBLIC (method) ? "public" : + (METHOD_PRIVATE (method) ? "private" : "protected")), + IDENTIFIER_POINTER (DECL_NAME + (TYPE_NAME (DECL_CONTEXT (found))))); continue; } @@ -4148,9 +4241,10 @@ java_check_regular_methods (class_decl) /* If the method has default access in an other package, then issue a warning that the current method doesn't override the - one that was found elsewhere */ - aflags = get_access_flags_from_decl (found); - if ((!aflags || (aflags > ACC_PROTECTED)) + one that was found elsewhere. Do not issue this warning when + the match was found in java.lang.Object. */ + if (DECL_CONTEXT (found) != object_type_node + && (!aflags || (aflags > ACC_PROTECTED)) && !class_in_current_package (DECL_CONTEXT (found))) parse_warning_context (method_wfl, "Method `%s' in class `%s' does not " @@ -4160,10 +4254,16 @@ java_check_regular_methods (class_decl) IDENTIFIER_POINTER (DECL_NAME (class_decl)), IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (DECL_CONTEXT (found))))); - /* Check on (default) package access. FIXME. */ /* Inheriting multiple methods with the same signature. FIXME */ } + /* Don't forget eventual pending found and saved_found_wfl. Take + into account that we might have exited because we saw an + aritifical method as the last entry. */ + + if (found && !DECL_ARTIFICIAL (found) && saved_found_wfl) + DECL_NAME (found) = saved_found_wfl; + TYPE_METHODS (class) = nreverse (TYPE_METHODS (class)); if (!saw_constructor) @@ -4220,11 +4320,12 @@ check_throws_clauses (method, method_wfl, found) /* Check abstract method of interface INTERFACE */ static void -java_check_abstract_methods (interface) - tree interface; +java_check_abstract_methods (interface_decl) + tree interface_decl; { int i, n; tree method, basetype_vec, found; + tree interface = TREE_TYPE (interface_decl); for (method = TYPE_METHODS (interface); method; method = TREE_CHAIN (method)) { @@ -4239,16 +4340,20 @@ java_check_abstract_methods (interface) found = lookup_java_interface_method2 (interface, method); if (found) { - char *t = strdup (lang_printable_name (TREE_TYPE (TREE_TYPE (found)), - 0)); + char *t; + tree saved_found_wfl = DECL_NAME (found); + reset_method_name (found); + t = strdup (lang_printable_name (TREE_TYPE (TREE_TYPE (found)), 0)); 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 (DECL_NAME (TYPE_NAME (DECL_CONTEXT (found))))); free (t); continue; + + DECL_NAME (found) = saved_found_wfl; } } @@ -4270,37 +4375,39 @@ java_check_abstract_methods (interface) found = lookup_java_interface_method2 (interface, sub_interface_method); if (found && (found != sub_interface_method)) - 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 (DECL_CONTEXT (sub_interface_method)))), - IDENTIFIER_POINTER - (DECL_NAME (TYPE_NAME (DECL_CONTEXT (found))))); + { + tree saved_found_wfl = DECL_NAME (found); + reset_method_name (found); + 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 + (DECL_CONTEXT (sub_interface_method)))), + IDENTIFIER_POINTER + (DECL_NAME (TYPE_NAME (DECL_CONTEXT (found))))); + DECL_NAME (found) = saved_found_wfl; + } } } } -/* Check the method on all the defined classes. Should be done to the - classes declared in the compilation unit only. FIXME */ +/* Check the method on all the defined classes. Process all the + classes that we compiled from source code for this CU. */ void java_check_methods () { tree current; - for (current = ctxp->class_list; current; current = TREE_CHAIN (current)) - if (CLASS_FROM_SOURCE_P (TREE_TYPE (current))) + for (current = ctxp->gclass_list; current; current = TREE_CHAIN (current)) + if (CLASS_FROM_SOURCE_P (TREE_TYPE (TREE_VALUE (current)))) { - tree class = CLASS_TO_HANDLE_TYPE (TREE_TYPE (current)); - - if (CLASS_INTERFACE (TYPE_NAME (class))) - java_check_abstract_methods (class); - else - java_check_regular_methods (current); + CHECK_METHODS (TREE_VALUE (current)); + CLASS_METHOD_CHECKED_P (TREE_TYPE (TREE_VALUE (current))) = 1; } } @@ -4345,9 +4452,12 @@ lookup_java_method2 (clas, method_decl, do_interface) tree clas, method_decl; int do_interface; { - tree method, method_signature, method_name, method_type; + tree method, method_signature, method_name, method_type, name; + method_signature = build_java_argument_signature (TREE_TYPE (method_decl)); - method_name = DECL_NAME (method_decl); + name = DECL_NAME (method_decl); + method_name = (TREE_CODE (name) == EXPR_WITH_FILE_LOCATION ? + EXPR_WFL_NODE (name) : name); method_type = TREE_TYPE (TREE_TYPE (method_decl)); while (clas != NULL_TREE) @@ -4356,12 +4466,12 @@ lookup_java_method2 (clas, method_decl, do_interface) method != NULL_TREE; method = TREE_CHAIN (method)) { tree method_sig = build_java_argument_signature (TREE_TYPE (method)); - if (DECL_NAME (method) == method_name + tree name = DECL_NAME (method); + if ((TREE_CODE (name) == EXPR_WITH_FILE_LOCATION ? + EXPR_WFL_NODE (name) : name) == method_name && method_sig == method_signature && TREE_TYPE (TREE_TYPE (method)) != method_type) - { - return method; - } + return method; } clas = (do_interface ? NULL_TREE : CLASSTYPE_SUPER (clas)); } @@ -4450,8 +4560,6 @@ find_in_imports (class_type) { TYPE_NAME (class_type) = EXPR_WFL_NODE (TREE_PURPOSE (import)); QUALIFIED_P (TYPE_NAME (class_type)) = 1; - return check_pkg_class_access (TYPE_NAME (class_type), - TREE_PURPOSE (import)); } return 0; } @@ -4675,6 +4783,50 @@ find_in_imports_on_demand (class_type) return (seen_once < 0 ? 0 : seen_once); /* It's ok not to have found */ } +static tree +resolve_package (pkg, next) + tree pkg, *next; +{ + tree type_name = NULL_TREE; + char *name = IDENTIFIER_POINTER (EXPR_WFL_NODE (pkg)); + int length = IDENTIFIER_LENGTH (EXPR_WFL_NODE (pkg)); + + /* 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); + } + else + return NULL_TREE; /* FIXME, search all imported packages. */ + + return type_name; +} + +static tree +lookup_package_type (name, from) + char *name; + int from; +{ + char subname [128]; + char *sub = &name[from+1]; + while (*sub != '.' && *sub) + sub++; + strncpy (subname, name, sub-name); + subname [sub-name] = '\0'; + return get_identifier (subname); +} + /* Check that CLASS_NAME refers to a PUBLIC class. Return 0 if no access violations were found, 1 otherwise. */ @@ -5021,16 +5173,21 @@ add_stmt_to_compound (existing, type, stmt) /* Hold THIS for the scope of the current public method decl. */ static tree current_this; -/* Layout all class found during parsing. Also fixes the order of - several field related lists. */ +/* Layout all class found during parsing. Also fixes the order of some + lists. */ void java_layout_classes () { tree current; - for (current = ctxp->class_list; current; current = TREE_CHAIN (current)) + + java_check_methods (); + /* Error reported by the caller */ + if (java_error_count) + return; + for (current = ctxp->gclass_list; current; current = TREE_CHAIN (current)) { - current_class = TREE_TYPE (current); + current_class = TREE_TYPE (TREE_VALUE (current)); /* Reverse the fields if it's necessary (they've already reversed if the dummy field has been inserted at the @@ -5042,6 +5199,10 @@ java_layout_classes () /* Do a layout if necessary */ if (!TYPE_SIZE (current_class) || (current_class == object_type_node)) safe_layout_class (current_class); + + /* Error reported by the caller */ + if (java_error_count) + return; } } @@ -5080,7 +5241,9 @@ java_complete_expand_methods () restore_line_number_status (0); } } - else + else if (METHOD_ABSTRACT (decl) || METHOD_NATIVE (decl)) + continue; + else java_complete_expand_method (decl); } @@ -5135,6 +5298,7 @@ java_complete_expand_method (mdecl) if (BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (mdecl))) java_complete_tree (BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (mdecl))); + /* Don't go any further if we've found error(s) during the expansion */ if (!java_error_count) @@ -5294,6 +5458,13 @@ java_expand_finals () void java_expand_classes () { + ctxp = ctxp_for_generation; + /* If we found error earlier, we don't want to report then twice. */ + if (java_error_count || !ctxp) + return; + java_layout_classes (); + java_parse_abort_on_error (); + for (; ctxp_for_generation; ctxp_for_generation = ctxp_for_generation->next) { ctxp = ctxp_for_generation; @@ -5425,8 +5596,9 @@ cut_identifier_in_qualified (wfl) /* Resolve the expression name NAME. Return its decl. */ static tree -resolve_expression_name (id) +resolve_expression_name (id, orig) tree id; + tree *orig; { tree name = EXPR_WFL_NODE (id); tree decl; @@ -5445,6 +5617,7 @@ resolve_expression_name (id) decl = lookup_field_wrapper (current_class, name); if (decl) { + tree value = NULL_TREE; int fs = FIELD_STATIC (decl); /* Instance variable (8.3.1.1) can't appear within static method, static initializer or initializer for @@ -5468,9 +5641,20 @@ resolve_expression_name (id) "constructor has been called", IDENTIFIER_POINTER (name)); return error_mark_node; } + /* The field is final. We may use its value instead */ + if (fs && FIELD_FINAL (decl)) + value = java_complete_tree (DECL_LOCAL_STATIC_VALUE (decl)); + + /* Otherwise build what it takes to access the field */ decl = build_field_ref ((fs ? NULL_TREE : current_this), current_class, name); - return (fs ? build_class_init (current_class, decl) : decl); + if (fs && !flag_emit_class_files) + decl = build_class_init (current_class, decl); + /* We may be asked to save the real field access node */ + if (orig) + *orig = decl; + /* And we return what we got */ + return (value ? value : decl); } /* Fall down to error report on undefined variable */ } @@ -5478,6 +5662,8 @@ resolve_expression_name (id) /* 6.5.5.2 Qualified Expression Names */ else { + if (orig) + *orig = NULL_TREE; qualify_ambiguous_name (id); /* 15.10.1 Field Access Using a Primary and/or Expression Name */ /* 15.10.2: Accessing Superclass Members using super */ @@ -5523,12 +5709,24 @@ resolve_field_access (qual_wfl, field_decl, field_type) field_ref = decl; else if (DECL_P (decl)) { + int static_final_found = 0; + if (!type_found) + type_found = DECL_CONTEXT (decl); is_static = DECL_P (decl) && FIELD_STATIC (decl); - field_ref = build_field_ref ((is_static ? NULL_TREE : where_found), - type_found, DECL_NAME (decl)); + if (FIELD_FINAL (decl) + && JPRIMITIVE_TYPE_P (TREE_TYPE (decl)) + && DECL_LANG_SPECIFIC (decl) + && DECL_LOCAL_STATIC_VALUE (decl)) + { + field_ref = java_complete_tree (DECL_LOCAL_STATIC_VALUE (decl)); + static_final_found = 1; + } + else + field_ref = build_field_ref ((is_static ? NULL_TREE : where_found), + type_found, DECL_NAME (decl)); if (field_ref == error_mark_node) return error_mark_node; - if (is_static) + if (is_static && !static_final_found) { field_ref = build_class_init (type_found, field_ref); /* If the static field was identified by an expression that @@ -5571,7 +5769,6 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found) tree qual_wfl = QUAL_WFL (q); /* 15.10.1 Field Access Using a Primary */ - switch (TREE_CODE (qual_wfl)) { case CALL_EXPR: @@ -5619,6 +5816,7 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found) continue; case CONDITIONAL_EXPR: + case STRING_CST: *where_found = decl = java_complete_tree (qual_wfl); if (decl == error_mark_node) return 1; @@ -5660,7 +5858,7 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found) } /* We have to generate code for intermediate acess */ *where_found = decl = current_this; - type = QUAL_DECL_TYPE (decl); + *type_found = type = QUAL_DECL_TYPE (decl); continue; } @@ -5692,17 +5890,33 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found) assume a variable/class name was meant. */ if (RESOLVE_PACKAGE_NAME_P (qual_wfl)) { - if (from_super || from_cast) - parse_error_context - ((from_cast ? qual_wfl : wfl), - "No variable `%s' defined in class `%s'", - IDENTIFIER_POINTER (EXPR_WFL_NODE (qual_wfl)), - lang_printable_name (type, 0)); + tree name = resolve_package (wfl, &q); + if (name) + { + *where_found = decl = resolve_no_layout (name, qual_wfl); + /* We wan't to be absolutely that the class is laid + out. We're going to search something inside it. */ + *type_found = type = TREE_TYPE (decl); + layout_class (type); + from_type = 1; + /* Should be a list, really. FIXME */ + RESOLVE_EXPRESSION_NAME_P (QUAL_WFL (TREE_CHAIN (q))) = 1; + RESOLVE_PACKAGE_NAME_P (QUAL_WFL (TREE_CHAIN (q))) = 0; + } else - parse_error_context - (qual_wfl, "Undefined variable or class name: `%s'", - IDENTIFIER_POINTER (EXPR_WFL_NODE (qual_wfl))); - return 1; + { + if (from_super || from_cast) + parse_error_context + ((from_cast ? qual_wfl : wfl), + "No variable `%s' defined in class `%s'", + IDENTIFIER_POINTER (EXPR_WFL_NODE (qual_wfl)), + lang_printable_name (type, 0)); + else + parse_error_context + (qual_wfl, "Undefined variable or class name: `%s'", + IDENTIFIER_POINTER (EXPR_WFL_NODE (qual_wfl))); + return 1; + } } /* We have a type name. It's been already resolved when the @@ -5722,6 +5936,7 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found) IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (current_class)))); return 1; } + check_deprecation (qual_wfl, decl); type = TREE_TYPE (decl); from_type = 1; @@ -5738,18 +5953,24 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found) if (!from_super && QUAL_RESOLUTION (q)) { decl = QUAL_RESOLUTION (q); - *type_found = type; + if (!type && !FIELD_STATIC (decl)) + { + *where_found = current_this; + *type_found = type; + } } /* We have to search for a field, knowing the type of its container. The flag FROM_TYPE indicates that we resolved the last member of the expression as a type name, which - means that for the resolution of this field, will check - on other errors than if the it was resolved as a member - of an other field. */ + means that for the resolution of this field, we'll look + for other errors than if it was resolved as a member of + an other field. */ else { int is_static; + tree field_decl_type; /* For layout */ + if (!from_type && !JREFERENCE_TYPE_P (type)) { parse_error_context @@ -5769,6 +5990,17 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found) IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)))); return 1; } + + /* Layout the type of field_decl, since we may need + it. Don't do primitive types or loaded classes */ + if (TREE_CODE (TREE_TYPE (field_decl)) == POINTER_TYPE) + field_decl_type = TREE_TYPE (TREE_TYPE (field_decl)); + else + field_decl_type = TREE_TYPE (field_decl); + if (!JPRIMITIVE_TYPE_P (field_decl_type) + && !CLASS_LOADED_P (field_decl_type)) + resolve_and_layout (DECL_NAME (TYPE_NAME (field_decl_type)), + NULL_TREE); /* Check on accessibility here */ if (not_accessible_p (type, field_decl, from_super)) @@ -5784,6 +6016,7 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found) (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 @@ -5802,8 +6035,9 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found) } from_cast = from_super = 0; - /* If we need to generate something to get a proper handle - on what this field is accessed from, do it now. */ + /* If we need to generate something to get a proper + handle on what this field is accessed from, do it + now. */ if (!is_static) { decl = maybe_access_field (decl, *where_found, *type_found); @@ -5889,6 +6123,38 @@ int not_accessible_p (reference, member, from_super) return 0; } +/* Test deprecated decl access. */ +static void +check_deprecation (wfl, decl) + tree wfl, decl; +{ + char *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) + && !IS_A_COMMAND_LINE_FILENAME_P (get_identifier (file))) + { + char the [20]; + switch (TREE_CODE (decl)) + { + case FUNCTION_DECL: + strcpy (the, "method"); + break; + case FIELD_DECL: + strcpy (the, "field"); + break; + case TYPE_DECL: + strcpy (the, "class"); + break; + } + 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 int @@ -5933,10 +6199,8 @@ static tree maybe_access_field (decl, where, type) tree decl, where, type; { - if (DECL_P (decl) && decl != current_this - && (!(TREE_CODE (decl) != PARM_DECL - && FIELD_STATIC (decl))) - && !IDENTIFIER_LOCAL_VALUE (DECL_NAME (decl))) + if (TREE_CODE (decl) == FIELD_DECL && decl != current_this + && !FIELD_STATIC (decl)) decl = build_field_ref (where ? where : current_this, (type ? type : DECL_CONTEXT (decl)), DECL_NAME (decl)); @@ -5957,7 +6221,7 @@ patch_method_invocation_stmt (patch, primary, where, is_static, ret_decl, super) tree wfl = TREE_OPERAND (patch, 0); tree args = TREE_OPERAND (patch, 1); tree name = EXPR_WFL_NODE (wfl); - tree list, class_type; + tree list; int is_static_flag = 0; /* Should be overriden if everything goes well. Otherwise, if @@ -6028,6 +6292,7 @@ patch_method_invocation_stmt (patch, primary, where, is_static, ret_decl, super) free (fct_name); PATCH_METHOD_RETURN_ERROR (); } + args = nreverse (args); } /* We're resolving an expression name */ else @@ -6053,9 +6318,7 @@ patch_method_invocation_stmt (patch, primary, where, is_static, ret_decl, super) args = tree_cons (NULL_TREE, field, nreverse (args)); } - /* CLASS_TYPE is used during the call to not_accessible_p and - IDENTIFIER_WFL will be used to report any problem further */ - class_type = TREE_TYPE (class_decl); + /* IDENTIFIER_WFL will be used to report any problem further */ wfl = identifier_wfl; } /* Resolution of simple names, names generated after a primary: or @@ -6099,8 +6362,11 @@ patch_method_invocation_stmt (patch, primary, where, is_static, ret_decl, super) PATCH_METHOD_RETURN_ERROR (); } - /* Can't instantiate an abstract class */ - if (CLASS_ABSTRACT (class_to_search)) + /* 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) + && TREE_CODE (patch) == NEW_CLASS_EXPR) { parse_error_context (wfl, "Class `%s' is an abstract class. It can't be " @@ -6143,8 +6409,6 @@ patch_method_invocation_stmt (patch, primary, where, is_static, ret_decl, super) args = nreverse (args); if (!METHOD_STATIC (list) && TREE_CODE (patch) != NEW_CLASS_EXPR) args = tree_cons (NULL_TREE, primary ? primary : current_this, args); - - class_type = class_to_search; } /* Merge point of all resolution schemes. If we have nothing, this @@ -6154,18 +6418,19 @@ patch_method_invocation_stmt (patch, primary, where, is_static, ret_decl, super) /* Check accessibility, position the is_static flag, build and return the call */ - if (not_accessible_p (class_type, list, 0)) + if (not_accessible_p (DECL_CONTEXT (list), list, 0)) { char *fct_name = strdup (lang_printable_name (list, 0)); parse_error_context (wfl, "Can't access %s method `%s %s.%s' from `%s'", java_accstring_lookup (get_access_flags_from_decl (list)), lang_printable_name (TREE_TYPE (TREE_TYPE (list)), 0), - IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (class_type))), fct_name, - IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (current_class)))); + IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (DECL_CONTEXT (list)))), + fct_name, IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (current_class)))); free (fct_name); PATCH_METHOD_RETURN_ERROR (); } + check_deprecation (wfl, list); is_static_flag = METHOD_STATIC (list); @@ -6223,9 +6488,14 @@ patch_invoke (patch, method, args, from_super) tree signature = build_java_signature (TREE_TYPE (method)); tree original_call, t, ta; - /* Last step for args: convert build-in types. */ - for (t = TYPE_ARG_TYPES (TREE_TYPE (method)), ta = args; - t && ta; t = TREE_CHAIN (t), ta = TREE_CHAIN (ta)) + /* Last step for args: convert build-in types. If we're dealing with + a new TYPE() type call, the first argument to the constructor + isn't found in the incomming argument list, but delivered by + `new' */ + t = TYPE_ARG_TYPES (TREE_TYPE (method)); + if (TREE_CODE (patch) == NEW_CLASS_EXPR) + t = TREE_CHAIN (t); + for (ta = args; t && 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)) TREE_VALUE (ta) = convert (TREE_VALUE (t), TREE_VALUE (ta)); @@ -6243,6 +6513,11 @@ patch_invoke (patch, method, args, from_super) DECL_CONTEXT (method), signature, args); break; + case INVOKE_INTERFACE: + dtable = invoke_build_dtable (1, args); + func = build_invokeinterface (dtable, DECL_NAME (method), signature); + break; + default: fatal ("Unknown invocation mode `%d' - build_invoke", im); return NULL_TREE; @@ -6318,34 +6593,24 @@ lookup_method_invoke (lc, cl, class, name, arg_list) tree class, name, arg_list; { tree method = make_node (FUNCTION_TYPE); - tree arg_type_list = NULL_TREE; + tree atl = NULL_TREE; /* Arg Type List */ tree signature, list, node; char *candidates; /* Used for error report */ + /* Fix the arguments */ for (node = arg_list; node; node = TREE_CHAIN (node)) { tree current_arg = TREE_TYPE (TREE_VALUE (node)); if (TREE_CODE (current_arg) == RECORD_TYPE) current_arg = promote_type (current_arg); - arg_type_list = tree_cons (NULL_TREE, current_arg, arg_type_list); + atl = tree_cons (NULL_TREE, current_arg, atl); } - TYPE_ARG_TYPES (method) = arg_type_list; + TYPE_ARG_TYPES (method) = atl; - if (!lc) - { - list = find_applicable_accessible_methods_list (class, name, - arg_type_list); - list = find_most_specific_methods_list (list); - } - else - { - TREE_TYPE (method) = void_type_node; - signature = build_java_signature (method); - list = lookup_java_constructor (class, signature); - } - - if (lc && list) - return list; + /* Find all candidates and then refine the list, searching for the + most specific method. */ + list = find_applicable_accessible_methods_list (lc, class, name, atl); + list = find_most_specific_methods_list (list); if (list && !TREE_CHAIN (list)) return TREE_VALUE (list); @@ -6386,10 +6651,12 @@ lookup_method_invoke (lc, cl, class, name, arg_list) return NULL_TREE; } -/* 15.11.2.1: Find Methods that are Applicable and Accessible */ +/* 15.11.2.1: Find Methods that are Applicable and Accessible. LC is 1 + when we're looking for a constructor. */ static tree -find_applicable_accessible_methods_list (class, name, arglist) +find_applicable_accessible_methods_list (lc, class, name, arglist) + int lc; tree class, name, arglist; { tree method; @@ -6400,10 +6667,12 @@ find_applicable_accessible_methods_list (class, name, arglist) for (method = TYPE_METHODS (class); method != NULL_TREE; method = TREE_CHAIN (method)) { - /* Names have to match and we're not looking for constructor */ - if (DECL_NAME (method) != name || DECL_CONSTRUCTOR_P (method)) + if (lc && !DECL_CONSTRUCTOR_P (method)) continue; - + else if (!lc && (DECL_CONSTRUCTOR_P (method) + || DECL_NAME (method) != name)) + continue; + if (argument_types_convertible (method, arglist)) { /* Retain accessible methods only */ @@ -6414,7 +6683,9 @@ find_applicable_accessible_methods_list (class, name, arglist) all_list = tree_cons (NULL_TREE, method, list); } } - class = CLASSTYPE_SUPER (class); + /* When dealing with constructor, stop here, otherwise search + other classes */ + class = (lc ? NULL_TREE : CLASSTYPE_SUPER (class)); } /* Either return the list obtained or all selected (but inaccessible) methods for better error report. */ @@ -6598,8 +6869,9 @@ qualify_ambiguous_name (id) /* Do one more interation to set things up */ super_found = again = 1; } - /* Loop one more time if we're dealing with ?: up front */ - if (TREE_CODE (qual_wfl) == CONDITIONAL_EXPR) + /* Loop one more time if we're dealing with ?: or a string constant */ + if (TREE_CODE (qual_wfl) == CONDITIONAL_EXPR + || TREE_CODE (qual_wfl) == STRING_CST) { qual = TREE_CHAIN (qual); qual_wfl = QUAL_WFL (qual); @@ -6709,8 +6981,10 @@ not_initialized_as_it_should_p (decl) { if (DECL_P (decl)) { - if (TREE_CODE (decl) == FIELD_DECL - && METHOD_STATIC (current_function_decl)) + if (FIELD_FINAL (decl)) + return 0; + if (TREE_CODE (decl) == FIELD_DECL + && (METHOD_STATIC (current_function_decl))) return 0; return DECL_P (decl) && !INITIALIZED_P (decl); } @@ -6860,7 +7134,7 @@ java_complete_tree (node) case EXPR_WITH_FILE_LOCATION: if (!EXPR_WFL_NODE (node) /* Or a PRIMARY flag ? */ || TREE_CODE (EXPR_WFL_NODE (node)) == IDENTIFIER_NODE) - return resolve_expression_name (node); + return resolve_expression_name (node, NULL); else { EXPR_WFL_NODE (node) = java_complete_tree (EXPR_WFL_NODE (node)); @@ -6958,7 +7232,8 @@ java_complete_tree (node) an error during the assignment. In any cases, the assignment operation fails. */ if (TREE_CODE (TREE_OPERAND (node, 1)) != EXPR_WITH_FILE_LOCATION - && TREE_TYPE (TREE_OPERAND (node, 1)) != error_mark_node) + && TREE_TYPE (TREE_OPERAND (node, 1)) != error_mark_node + && TREE_TYPE (TREE_OPERAND (node, 1))) patch_assignment (node, wfl_op1, wfl_op2); /* Now, we still mark the lhs as initialized */ @@ -7015,6 +7290,11 @@ java_complete_tree (node) } return patch_binop (node, wfl_op1, wfl_op2); + case INSTANCEOF_EXPR: + wfl_op1 = TREE_OPERAND (node, 0); + COMPLETE_CHECK_OP_0 (node); + return patch_binop (node, wfl_op1, TREE_OPERAND (node, 1)); + case UNARY_PLUS_EXPR: case NEGATE_EXPR: case TRUTH_NOT_EXPR: @@ -7108,8 +7388,10 @@ complete_function_arguments (node) `+' operator. Build `parm.toString()' and expand it. */ if ((temp = patch_string (parm))) parm = temp; - TREE_VALUE (cn) = parm; + /* Inline PRIMTYPE.TYPE read access */ + parm = maybe_build_primttype_type_ref (parm, wfl); + TREE_VALUE (cn) = parm; if (not_initialized_as_it_should_p (parm)) { ERROR_VARIABLE_NOT_INITIALIZED (wfl, EXPR_WFL_NODE (wfl)); @@ -7350,6 +7632,47 @@ print_int_node (node) return buffer; } +/* Return 1 if you an assignment of a FINAL is attempted */ + +static int +check_final_assignment (lvalue, wfl) + tree lvalue, wfl; +{ + if (DECL_P (lvalue) && FIELD_FINAL (lvalue)) + { + parse_error_context + (wfl, "Can't assign a value to the final variable `%s'", + IDENTIFIER_POINTER (EXPR_WFL_NODE (wfl))); + return 1; + } + return 0; +} + +/* Inline references to java.lang.PRIMTYPE.TYPE when accessed in + read. This is needed to avoid circularities in the implementation + of these fields in libjava. */ + +static tree +maybe_build_primttype_type_ref (rhs, wfl) + tree rhs, wfl; +{ + tree to_return = NULL_TREE; + tree rhs_type = TREE_TYPE (rhs); + if (TREE_CODE (rhs) == COMPOUND_EXPR) + { + tree n = TREE_OPERAND (rhs, 1); + if (TREE_CODE (n) == VAR_DECL + && DECL_NAME (n) == TYPE_identifier_node + && rhs_type == class_ptr_type) + { + char *self_name = IDENTIFIER_POINTER (EXPR_WFL_NODE (wfl)); + if (!strncmp (self_name, "java.lang.", 10)) + to_return = build_primtype_type_ref (self_name); + } + } + return (to_return ? to_return : rhs ); +} + /* 15.25 Assignment operators. */ static tree @@ -7359,19 +7682,14 @@ patch_assignment (node, wfl_op1, wfl_op2) tree wfl_op2; { tree rhs = TREE_OPERAND (node, 1); - tree lvalue = TREE_OPERAND (node, 0); + tree lvalue = TREE_OPERAND (node, 0), llvalue; tree lhs_type, rhs_type, new_rhs = NULL_TREE; int error_found = 0; int lvalue_from_array = 0; /* Can't assign to a final. */ - if (DECL_P (lvalue) && FIELD_FINAL (lvalue)) - { - parse_error_context - (wfl_op1, "Can't assign a value to the final variable `%s'", - IDENTIFIER_POINTER (EXPR_WFL_NODE (wfl_op1))); - error_found = 1; - } + if (check_final_assignment (lvalue, wfl_op1)) + error_found = 1; EXPR_WFL_LINECOL (wfl_operator) = EXPR_WFL_LINECOL (node); @@ -7394,8 +7712,18 @@ patch_assignment (node, wfl_op1, wfl_op2) /* Or a function return slot */ else if (TREE_CODE (lvalue) == RESULT_DECL) lhs_type = TREE_TYPE (lvalue); - /* Otherwise, this is an error */ - else + /* Otherwise, we might want to try to write into an optimized static + final, this is an of a different nature, reported further on. */ + else if (TREE_CODE (wfl_op1) == EXPR_WITH_FILE_LOCATION + && resolve_expression_name (wfl_op1, &llvalue) + && check_final_assignment (llvalue, wfl_op1)) + { + error_found = 1; + /* What we should do instead is resetting the all the flags + previously set, exchange lvalue for llvalue and continue. */ + return error_mark_node; + } + else { parse_error_context (wfl_op1, "Invalid left hand side of assignment"); error_found = 1; @@ -7462,6 +7790,22 @@ patch_assignment (node, wfl_op1, wfl_op2) INITIALIZED_P (rhs) = 1; } + /* Inline read access to java.lang.PRIMTYPE.TYPE */ + rhs = maybe_build_primttype_type_ref (rhs, wfl_op2); + + if (TREE_CODE (rhs) == COMPOUND_EXPR) + { + tree n = TREE_OPERAND (rhs, 1); + if (TREE_CODE (n) == VAR_DECL + && DECL_NAME (n) == TYPE_identifier_node + && rhs_type == class_ptr_type) + { + char *self_name = IDENTIFIER_POINTER (EXPR_WFL_NODE (wfl_op2)); + if (!strncmp (self_name, "java.lang.", 10)) + rhs = build_primtype_type_ref (self_name); + } + } + if (error_found) return error_mark_node; @@ -7515,9 +7859,15 @@ try_builtin_assignconv (wfl_op1, lhs_type, rhs) tree new_rhs = NULL_TREE; tree rhs_type = TREE_TYPE (rhs); + /* Zero accepted everywhere */ + 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 */ - if (valid_builtin_assignconv_identity_widening_p (lhs_type, rhs_type)) + 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): @@ -7552,20 +7902,32 @@ static int valid_builtin_assignconv_identity_widening_p (lhs_type, rhs_type) tree lhs_type, rhs_type; { - int all_primitive = + int all_primitive; + + if (lhs_type == rhs_type) + return 1; + + all_primitive = JPRIMITIVE_TYPE_P (lhs_type) && JPRIMITIVE_TYPE_P (rhs_type); if (!all_primitive) return 0; - if (lhs_type == rhs_type) - return 1; - /* byte, even if it's smaller than a char can't be converted into a char. Short can't too, but the < test below takes care of that */ if (lhs_type == char_type_node && rhs_type == byte_type_node) return 0; + /* Accept all promoted type here. Note, we can't use <= in the test + below, because we still need to bounce out assignments of short + to char and the likes */ + if (lhs_type == int_type_node + && (rhs_type == promoted_byte_type_node + || rhs_type == promoted_short_type_node + || rhs_type == promoted_char_type_node + || rhs_type == promoted_boolean_type_node)) + return 1; + if (JINTEGRAL_TYPE_P (rhs_type) && ((TYPE_PRECISION (rhs_type) < TYPE_PRECISION (lhs_type)) || (JFLOAT_TYPE_P (lhs_type) && @@ -7590,6 +7952,8 @@ valid_ref_assignconv_cast_p (source, dest, cast) tree dest; int cast; { + if (JNULLP_TYPE_P (source)) + return 1; if (TREE_CODE (source) == POINTER_TYPE) source = TREE_TYPE (source); if (TREE_CODE (dest) == POINTER_TYPE) @@ -7715,8 +8079,8 @@ valid_method_invocation_conversion_p (dest, source) return ((JPRIMITIVE_TYPE_P (source) && JPRIMITIVE_TYPE_P (dest) && valid_builtin_assignconv_identity_widening_p (dest, source)) - || (JREFERENCE_TYPE_P (source) - && JREFERENCE_TYPE_P (dest) + || ((JREFERENCE_TYPE_P (source) || JNULLP_TYPE_P (source)) + && (JREFERENCE_TYPE_P (dest) || JNULLP_TYPE_P (dest)) && valid_ref_assignconv_cast_p (source, dest, 0))); } @@ -7728,9 +8092,7 @@ build_binop (op, op_location, op1, op2) int op_location; tree op1, op2; { - tree binop; - - binop = build (op, NULL_TREE, op1, op2); + tree binop = build (op, NULL_TREE, op1, op2); TREE_SIDE_EFFECTS (binop) = 1; /* Store the location of the operator, for better error report. The string of the operator will be rebuild based on the OP value. */ @@ -7935,7 +8297,63 @@ patch_binop (node, wfl_op1, wfl_op2) TREE_SET_CODE (node, RSHIFT_EXPR); } break; + + /* 15.19.1 Type Comparison Operator instaceof */ + case INSTANCEOF_EXPR: + + TREE_TYPE (node) = boolean_type_node; + + if (!(op2_type = resolve_type_during_patch (op2))) + return error_mark_node; + + /* The first operand must be a reference type or the null type */ + if (!JREFERENCE_TYPE_P (op1_type) && op1 != null_pointer_node) + error_found = 1; /* Error reported further below */ + + /* The second operand must be a reference type */ + if (!JREFERENCE_TYPE_P (op2_type)) + { + SET_WFL_OPERATOR (wfl_operator, node, wfl_op2); + parse_error_context + (wfl_operator, "Invalid argument `%s' for `instanceof'", + lang_printable_name (op2_type, 0)); + error_found = 1; + } + + if (!error_found && valid_ref_assignconv_cast_p (op1_type, op2_type, 1)) + { + /* If the first operand is null, the result is always false */ + if (op1 == null_pointer_node) + return boolean_false_node; + /* Otherwise we have to invoke instance of to figure it out */ + else + { + tree call = + build (CALL_EXPR, boolean_type_node, + build_address_of (soft_instanceof_node), + tree_cons + (NULL_TREE, op1, + build_tree_list (NULL_TREE, + build_class_ref (op2_type))), + NULL_TREE); + TREE_SIDE_EFFECTS (call) = 1; + return call; + } + } + /* There is no way the expression operand can be an instance of + the type operand. This is a compile time error. */ + else + { + char *t1 = strdup (lang_printable_name (op1_type, 0)); + SET_WFL_OPERATOR (wfl_operator, node, wfl_op1); + 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 */ case BIT_AND_EXPR: @@ -8011,7 +8429,7 @@ patch_binop (node, wfl_op1, wfl_op2) case NE_EXPR: /* 15.20.1 Numerical Equality Operators == and != */ /* Binary numeric promotion is performed on the operands */ - if (JPRIMITIVE_TYPE_P (op1_type) && JPRIMITIVE_TYPE_P (op2_type)) + 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 != */ @@ -8020,10 +8438,14 @@ patch_binop (node, wfl_op1, wfl_op2) ; /* Nothing to do here */ /* 15.20.3 Reference Equality Operators == and != */ - /* Types have to be either references or the null type */ + /* 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 || (JREFERENCE_TYPE_P (op1_type) && JREFERENCE_TYPE_P (op2_type) - && ((op1_type == op2_type)))) + && (valid_ref_assignconv_cast_p (op1_type, op2_type, 1) + || 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 @@ -8344,22 +8766,25 @@ patch_unaryop (node, wfl_op) case PREINCREMENT_EXPR: /* 15.14.2 Prefix Decrement Operator -- */ case PREDECREMENT_EXPR: - if (!DECL_P (op) && !(TREE_CODE (op) == INDIRECT_REF + if (!DECL_P (op) && !((TREE_CODE (op) == INDIRECT_REF + || TREE_CODE (op) == COMPONENT_REF) && JPRIMITIVE_TYPE_P (TREE_TYPE (op)))) { - parse_error_context (wfl_operator, "Invalid argument to `%s'", - operator_string (node)); - TREE_TYPE (node) = error_mark_node; - error_found = 1; - } - else if (DECL_P (op) && FIELD_FINAL (op)) - { - parse_error_context - (wfl_op, "Can't assign a value to the final variable `%s'", - IDENTIFIER_POINTER (EXPR_WFL_NODE (wfl_op))); + tree lvalue; + /* Before screaming, check that we're not in fact trying to + increment a optimized static final access, in which case + we issue an different error message. */ + if (!(TREE_CODE (wfl_op) == EXPR_WITH_FILE_LOCATION + && resolve_expression_name (wfl_op, &lvalue) + && check_final_assignment (lvalue, wfl_op))) + parse_error_context (wfl_operator, "Invalid argument to `%s'", + operator_string (node)); TREE_TYPE (node) = error_mark_node; error_found = 1; } + else if (check_final_assignment (op, wfl_op)) + 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. */ @@ -8480,7 +8905,10 @@ resolve_type_during_patch (type) return NULL_TREE; } else - return TREE_TYPE (type_decl); + { + CLASS_LOADED_P (TREE_TYPE (type_decl)) = 1; + return TREE_TYPE (type_decl); + } } return type; } @@ -8515,6 +8943,10 @@ patch_cast (node, wfl_operator) return convert (cast_type, op); } + /* null can be casted to references */ + if (op == null_pointer_node && JREFERENCE_TYPE_P (cast_type)) + return build_null_of_type (cast_type); + /* 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) @@ -8544,6 +8976,17 @@ patch_cast (node, wfl_operator) return error_mark_node; } +/* Build a null constant and give it the type TYPE. */ + +static tree +build_null_of_type (type) + tree type; +{ + tree node = build_int_2 (0, 0); + TREE_TYPE (node) = promote_type (type); + return node; +} + /* Build an ARRAY_REF incomplete tree node. Note that operand 1 isn't a list of indices. */ static tree @@ -8617,8 +9060,11 @@ patch_array_ref (node, wfl_array, wfl_index) return error_mark_node; index = convert (promoted_index_type, index); - if (TREE_CODE (array_type) == RECORD_TYPE) - array_type = promote_type (TYPE_ARRAY_ELEMENT (array_type)); + array_type = TYPE_ARRAY_ELEMENT (array_type); + if (TREE_CODE (array_type) == RECORD_TYPE + && !JPRIMITIVE_TYPE_P (TREE_TYPE (array_type))) + array_type = promote_type (array_type); + if (flag_emit_class_files) { TREE_OPERAND (node, 0)= array; @@ -8804,7 +9250,6 @@ patch_return (node) tree return_exp = TREE_OPERAND (node, 0); tree meth = current_function_decl; tree mtype = TREE_TYPE (TREE_TYPE (current_function_decl)); - tree modify; int error_found = 0; TREE_TYPE (node) = error_mark_node; @@ -8838,12 +9283,33 @@ patch_return (node) return error_mark_node; } - /* If we have a return_exp, build a modify expression and expand it */ + /* If we have a return_exp, build a modify expression and expand + it. Note: at that point, the assignment is declared valid, but we + may want to carry some more hacks */ if (return_exp) { - modify = build (MODIFY_EXPR, NULL_TREE, DECL_RESULT (meth), return_exp); + tree exp = java_complete_tree (return_exp); + tree modify, patched; + + /* If the function returned value and EXP are booleans, EXP has + to be converted into the type of DECL_RESULT, which is integer + (see complete_start_java_method) */ + if (TREE_TYPE (exp) == boolean_type_node && + TREE_TYPE (TREE_TYPE (meth)) == boolean_type_node) + exp = convert_to_integer (TREE_TYPE (DECL_RESULT (meth)), exp); + + /* `null' can be assigned to a function returning a reference */ + if (JREFERENCE_TYPE_P (TREE_TYPE (TREE_TYPE (meth))) && + exp == null_pointer_node) + exp = build_null_of_type (TREE_TYPE (TREE_TYPE (meth))); + + 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); + if (modify != error_mark_node) { TREE_SIDE_EFFECTS (modify) = 1; diff --git a/gcc/java/typeck.c b/gcc/java/typeck.c index 9aad0fb..154ba57 100644 --- a/gcc/java/typeck.c +++ b/gcc/java/typeck.c @@ -52,10 +52,6 @@ set_local_type (slot, type) type_map[++slot] = void_type_node; } -extern tree convert_to_integer (tree type, tree expr); -extern tree convert_to_real (tree type, tree expr); -extern tree convert_to_pointer (tree type, tree expr); - /* Create an expression whose value is that of EXPR, converted to type TYPE. The TREE_TYPE of the value is always TYPE. This function implements all reasonable @@ -663,7 +659,7 @@ lookup_argument_method (clas, method_name, method_signature) tree method_sig = build_java_argument_signature (TREE_TYPE (method)); tree name = DECL_NAME (method); if ((TREE_CODE (name) == EXPR_WITH_FILE_LOCATION ? - EXPR_WFL_NODE (DECL_NAME (method)) : name) == method_name + EXPR_WFL_NODE (name) : name) == method_name && method_sig == method_signature) return method; }