From: bothner Date: Thu, 12 Nov 1998 16:15:18 +0000 (+0000) Subject: � X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=414a3558d3680ef9066c3589e0619283be8f442b;p=platform%2Fupstream%2Flinaro-gcc.git � Extensive changes. See ChangeLog. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@23621 138bc75d-0d04-0410-961f-82ee72b054a4 --- diff --git a/gcc/java/Make-lang.in b/gcc/java/Make-lang.in index 6c37ef6..380cf50 100644 --- a/gcc/java/Make-lang.in +++ b/gcc/java/Make-lang.in @@ -191,16 +191,13 @@ java.install-info: java.mostlyclean: -rm -f java/*$(objext) $(DEMANGLER_PROG) -# CYGNUS LOCAL - Delete these files here instead of in realclean because they -# are now created in the build subdirectories. - -rm -f java/parse.c java/parse-scan.c java/parse.output java/y.tab.c java.clean: java.distclean: -rm -f java/config.status java/Makefile -rm -f java/parse.output java.extraclean: java.maintainer-clean: - + -rm -f java/parse.c java/parse-scan.c java/parse.output java/y.tab.c # Stage hooks: # The main makefile has already created stage?/java. diff --git a/gcc/java/decl.c b/gcc/java/decl.c index 38b2bad..c625075 100644 --- a/gcc/java/decl.c +++ b/gcc/java/decl.c @@ -431,6 +431,8 @@ init_decl_processing () TREE_TYPE (size_zero_node) = sizetype; size_one_node = build_int_2 (1, 0); TREE_TYPE (size_one_node) = sizetype; + /* Used by the parser to represent empty statements and blocks. */ + CAN_COMPLETE_NORMALLY (size_zero_node) = 1; byte_type_node = make_signed_type (8); pushdecl (build_decl (TYPE_DECL, get_identifier ("byte"), byte_type_node)); diff --git a/gcc/java/expr.c b/gcc/java/expr.c index 37c5122..0df6106 100644 --- a/gcc/java/expr.c +++ b/gcc/java/expr.c @@ -1337,9 +1337,7 @@ build_known_method_ref (method, method_type, self_type, method_signature, arg_li tree method, method_type, self_type, method_signature, arg_list; { tree func; - if (flag_emit_class_files) - return method; - else if (is_compiled_class (self_type)) + if (is_compiled_class (self_type)) { make_decl_rtl (method, NULL, 1); func = build1 (ADDR_EXPR, method_ptr_type_node, method); @@ -1696,6 +1694,18 @@ load_type_state (label) type_map [i] = TREE_VEC_ELT (vec, i); } +/* Do the expansion of a Java switch. With Gcc, switches are front-end + dependant things, but they rely on gcc routines. This function is + placed here because it uses things defined locally in parse.y. */ + +static tree +case_identity (t, v) + tree t __attribute__ ((__unused__)); + tree v; +{ + return v; +} + struct rtx_def * java_lang_expand_expr (exp, target, tmode, modifier) register tree exp; @@ -1716,6 +1726,7 @@ java_lang_expand_expr (exp, target, tmode, modifier) if (BLOCK_EXPR_BODY (exp)) { tree local; + tree body = BLOCK_EXPR_BODY (exp); struct rtx_def *to_return; pushlevel (2); /* 2 and above */ expand_start_bindings (0); @@ -1727,16 +1738,41 @@ java_lang_expand_expr (exp, target, tmode, modifier) expand_decl (pushdecl (local)); local = next; } - to_return = - expand_expr (BLOCK_EXPR_BODY (exp), target, tmode, modifier); + /* Avoid deep recursion for long block. */ + while (TREE_CODE (body) == COMPOUND_EXPR) + { + expand_expr (TREE_OPERAND (body, 0), const0_rtx, VOIDmode, 0); + body = TREE_OPERAND (body, 1); + } + to_return = expand_expr (body, target, tmode, modifier); poplevel (1, 1, 0); expand_end_bindings (getdecls (), 1, 0); return to_return; } break; + case CASE_EXPR: + { + tree duplicate; + if (pushcase (TREE_OPERAND (exp, 0), case_identity, + build_decl (LABEL_DECL, NULL_TREE, NULL_TREE), &duplicate) == 2) + { + EXPR_WFL_LINECOL (wfl_operator) = EXPR_WFL_LINECOL (exp); + parse_error_context + (wfl_operator, "Duplicate case label: `%s'", + print_int_node (TREE_OPERAND (exp, 0))); + } + return const0_rtx; + } + + case DEFAULT_EXPR: + pushcase (NULL_TREE, 0, build_decl (LABEL_DECL, NULL_TREE, NULL_TREE), NULL); + return const0_rtx; + case SWITCH_EXPR: - java_expand_switch (exp); + expand_start_case (0, TREE_OPERAND (exp, 0), int_type_node, "switch"); + expand_expr_stmt (TREE_OPERAND (exp, 1)); + expand_end_case (TREE_OPERAND (exp, 0)); return const0_rtx; case TRY_EXPR: diff --git a/gcc/java/parse.h b/gcc/java/parse.h index 7f783dc..dfa0560 100644 --- a/gcc/java/parse.h +++ b/gcc/java/parse.h @@ -439,6 +439,9 @@ static jdeplist *reverse_jdep_list (); #define BLOCK_EXPR_DECLS(NODE) BLOCK_VARS(NODE) #define BLOCK_EXPR_BODY(NODE) BLOCK_SUBBLOCKS(NODE) + +/* For an artificial BLOCK (created to house a local variable declaration not + at the start of an existing block), the parent block; otherwise NULL. */ #define BLOCK_EXPR_ORIGIN(NODE) BLOCK_ABSTRACT_ORIGIN(NODE) /* Merge an other line to the source line number of a decl. Used to @@ -601,7 +604,7 @@ struct parser_ctxt { tree import_list; /* List of import */ tree import_demand_list; /* List of import on demand */ - tree current_loop; /* List of the currently nested loops */ + tree current_loop; /* List of the currently nested loops/switches */ tree current_labeled_block; /* List of currently nested labeled blocks. */ @@ -618,7 +621,6 @@ struct parser_ctxt { /* Functions declarations */ #ifndef JC1_LITE static char *java_accstring_lookup PROTO ((int)); -static void parse_error PROTO ((char *)); static void classitf_redefinition_error PROTO ((char *,tree, tree, tree)); static void variable_redefinition_error PROTO ((tree, tree, tree, int)); static void check_modifiers PROTO ((char *, int, int)); @@ -637,9 +639,8 @@ 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 void issue_warning_error_from_context PROTO ((tree, char *msg, va_list)); static tree parse_jdk1_1_error PROTO ((char *)); static void complete_class_report_errors PROTO ((jdep *)); static int process_imports PROTO ((void)); @@ -662,8 +663,8 @@ 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)); -static tree patch_method_invocation_stmt PROTO ((tree, tree, tree, - int *, tree *, int)); +static tree patch_method_invocation PROTO ((tree, tree, tree, + int *, tree *, int)); static int breakdown_qualified PROTO ((tree *, tree *, tree)); static tree resolve_and_layout PROTO ((tree, tree)); static tree resolve_no_layout PROTO ((tree, tree)); diff --git a/gcc/java/parse.y b/gcc/java/parse.y index 8d7c676..3dc35f4 100644 --- a/gcc/java/parse.y +++ b/gcc/java/parse.y @@ -99,7 +99,7 @@ static enum tree_code binop_lookup[19] = /* Fake WFL used to report error message. It is initialized once if needed and reused with it's location information is overriden. */ -static tree wfl_operator = NULL_TREE; +tree wfl_operator = NULL_TREE; /* The "$L" identifier we use to create labels. */ static tree label_id = NULL_TREE; @@ -206,8 +206,6 @@ static tree wfl_to_string = NULL_TREE; variable_initializers constructor_body %type class_body block_end -%type block_statement local_variable_declaration_statement - block_statements local_variable_declaration %type statement statement_without_trailing_substatement labeled_statement if_then_statement label_decl if_then_else_statement while_statement for_statement @@ -233,11 +231,8 @@ static tree wfl_to_string = NULL_TREE; left_hand_side assignment for_header for_begin constant_expression do_statement_begin empty_statement switch_statement synchronized_statement throw_statement - try_statement switch_expression switch_block - switch_block_statement_groups switch_labels - switch_block_statement_group switch_label - group_of_labels catches catch_clause - catch_clause_parameter finally + try_statement switch_expression + catches catch_clause catch_clause_parameter finally %type return_statement break_statement continue_statement %type ASSIGN_TK MULT_ASSIGN_TK DIV_ASSIGN_TK @@ -982,9 +977,9 @@ block_statements: block_statement: local_variable_declaration_statement | statement - { $$ = java_method_add_stmt (current_function_decl, $1); } + { java_method_add_stmt (current_function_decl, $1); } | class_declaration /* Added, JDK1.1 inner classes */ - { $$ = parse_jdk1_1_error ("inner class declaration"); } + { parse_jdk1_1_error ("inner class declaration"); } ; local_variable_declaration_statement: @@ -1162,9 +1157,16 @@ if_then_else_statement_nsi: ; switch_statement: - switch_expression switch_block + switch_expression + { + enter_block (); + } + switch_block { - TREE_OPERAND ($1, 1) = $2; + /* Make into "proper list" of COMPOUND_EXPRs. + I.e. make the last statment also have its own COMPOUND_EXPR. */ + maybe_absorb_scoping_blocks (); + TREE_OPERAND ($1, 1) = exit_block (); $$ = build_debugable_stmt (EXPR_WFL_LINECOL ($1), $1); } ; @@ -1185,62 +1187,37 @@ switch_expression: switch_block: OCB_TK CCB_TK - { $$ = NULL_TREE; } | OCB_TK switch_labels CCB_TK - { $$ = build_tree_list ($2, NULL_TREE); } | OCB_TK switch_block_statement_groups CCB_TK - { $$ = $2; } | OCB_TK switch_block_statement_groups switch_labels CCB_TK - { - /* Switch labels alone are empty switch statements */ - tree sl = build_tree_list ($3, NULL_TREE); - TREE_CHAIN (sl) = $2; - $$ = sl; - } ; switch_block_statement_groups: switch_block_statement_group | switch_block_statement_groups switch_block_statement_group - { - TREE_CHAIN ($2) = $1; - $$ = $2; - } ; switch_block_statement_group: - group_of_labels block_statements - { $$ = build_tree_list ($1, exit_block ()); } + switch_labels block_statements ; -group_of_labels: - switch_labels - { - /* All statements attached to this group of cases - will be stored in a block */ - enter_block (); - $$ = $1; - } - switch_labels: switch_label | switch_labels switch_label - { - TREE_CHAIN ($2) = $1; - $$ = $2; - } ; switch_label: CASE_TK constant_expression REL_CL_TK { - $$ = build1 (CASE_EXPR, NULL_TREE, $2); - EXPR_WFL_LINECOL ($$) = $1.location; + tree lab = build1 (CASE_EXPR, NULL_TREE, $2); + EXPR_WFL_LINECOL (lab) = $1.location; + java_method_add_stmt (current_function_decl, lab); } | DEFAULT_TK REL_CL_TK { - $$ = build1 (DEFAULT_EXPR, NULL_TREE, NULL_TREE); - EXPR_WFL_LINECOL ($$) = $1.location; + tree lab = build1 (DEFAULT_EXPR, NULL_TREE, NULL_TREE); + EXPR_WFL_LINECOL (lab) = $1.location; + java_method_add_stmt (current_function_decl, lab); } | CASE_TK error {yyerror ("Missing or invalid constant expression"); RECOVER;} @@ -2259,19 +2236,15 @@ yyerror (msg) } static void -parse_error (msg) - char *msg; -{ - java_error (NULL); - java_error (msg); -} - -static void -issue_warning_error_from_context (cl, msg) +issue_warning_error_from_context (cl, msg, ap) tree cl; char *msg; + va_list ap; { char *saved; + char buffer [4096]; + 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)); @@ -2280,21 +2253,21 @@ issue_warning_error_from_context (cl, msg) 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); + java_error (NULL); + java_error (buffer); ctxp->filename = saved; + force_error = 0; } /* Issue an error message at a current source line CL */ -static void +void parse_error_context VPROTO ((tree cl, char *msg, ...)) { #ifndef __STDC__ tree cl; char *msg; #endif - char buffer [4096]; - char *saved; va_list ap; VA_START (ap, msg); @@ -2302,11 +2275,8 @@ parse_error_context VPROTO ((tree cl, char *msg, ...)) cl = va_arg (ap, tree); msg = va_arg (ap, char *); #endif - vsprintf (buffer, msg, ap); - - force_error = 1; - issue_warning_error_from_context (cl, buffer); - force_error = 0; + issue_warning_error_from_context (cl, msg, ap); + va_end (ap); } /* Issue a warning at a current source line CL */ @@ -2318,8 +2288,6 @@ parse_warning_context VPROTO ((tree cl, char *msg, ...)) tree cl; char *msg; #endif - char buffer [4096]; - char *saved; va_list ap; VA_START (ap, msg); @@ -2327,11 +2295,11 @@ parse_warning_context VPROTO ((tree cl, char *msg, ...)) cl = va_arg (ap, tree); msg = va_arg (ap, char *); #endif - vsprintf (buffer, msg, ap); - force_error = do_warning = 1; - issue_warning_error_from_context (cl, buffer); - do_warning = force_error = 0; + do_warning = 1; + issue_warning_error_from_context (cl, msg, ap); + force_error = 0; + va_end (ap); } void @@ -2624,7 +2592,7 @@ add_superinterfaces (decl, interface_list) defined. */ for (node = interface_list; node; node = TREE_CHAIN (node)) { - tree current = TREE_PURPOSE (node), interface_decl; + tree current = TREE_PURPOSE (node); tree idecl = IDENTIFIER_CLASS_VALUE (EXPR_WFL_NODE (current)); if (idecl && CLASS_LOADED_P (TREE_TYPE (idecl))) { @@ -3614,7 +3582,6 @@ 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; @@ -4789,7 +4756,6 @@ resolve_package (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 @@ -5153,21 +5119,10 @@ static tree add_stmt_to_compound (existing, type, stmt) tree existing, type, stmt; { - tree node; - - if (existing && (TREE_CODE (existing) == COMPOUND_EXPR) - && TREE_OPERAND (existing, 1) == size_zero_node) - { - TREE_OPERAND (existing, 1) = stmt; - TREE_TYPE (existing) = type; - return existing; - } - else if (existing) - node = build (COMPOUND_EXPR, type, existing, stmt); + if (existing) + return build (COMPOUND_EXPR, type, existing, stmt); else - node = build (COMPOUND_EXPR, type, stmt, size_zero_node); - - return node; + return stmt; } /* Hold THIS for the scope of the current public method decl. */ @@ -5726,7 +5681,8 @@ resolve_field_access (qual_wfl, field_decl, field_type) type_found, DECL_NAME (decl)); if (field_ref == error_mark_node) return error_mark_node; - if (is_static && !static_final_found) + if (is_static && !static_final_found + && ! flag_emit_class_files) { field_ref = build_class_init (type_found, field_ref); /* If the static field was identified by an expression that @@ -5785,8 +5741,8 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found) if (complete_function_arguments (qual_wfl)) return 1; *where_found = - patch_method_invocation_stmt (qual_wfl, decl, type, - &is_static, NULL, from_super); + patch_method_invocation (qual_wfl, decl, type, + &is_static, NULL, from_super); if (*where_found == error_mark_node) return 1; *type_found = type = QUAL_DECL_TYPE (*where_found); @@ -6147,6 +6103,8 @@ check_deprecation (wfl, decl) 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", @@ -6207,12 +6165,12 @@ maybe_access_field (decl, where, type) return decl; } -/* Build a method invocation statement, by patching PATCH. If non NULL +/* Build a method invocation, by patching PATCH. If non NULL and according to the situation, PRIMARY and WHERE may be used. IS_STATIC is set to 1 if the invoked function is static. */ static tree -patch_method_invocation_stmt (patch, primary, where, is_static, ret_decl, super) +patch_method_invocation (patch, primary, where, is_static, ret_decl, super) tree patch, primary, where; int *is_static; tree *ret_decl; @@ -6485,7 +6443,6 @@ patch_invoke (patch, method, args, from_super) { int im; tree dtable, func; - tree signature = build_java_signature (TREE_TYPE (method)); tree original_call, t, ta; /* Last step for args: convert build-in types. If we're dealing with @@ -6500,31 +6457,39 @@ patch_invoke (patch, method, args, from_super) TREE_TYPE (TREE_VALUE (ta)) != TREE_VALUE (t)) TREE_VALUE (ta) = convert (TREE_VALUE (t), TREE_VALUE (ta)); - switch ((im = invocation_mode (method, from_super))) + if (flag_emit_class_files) + func = method; + else { - case INVOKE_VIRTUAL: - dtable = invoke_build_dtable (0, args); - func = build_invokevirtual (dtable, method); - break; + tree signature = build_java_signature (TREE_TYPE (method)); + switch ((im = invocation_mode (method, from_super))) + { + case INVOKE_VIRTUAL: + dtable = invoke_build_dtable (0, args); + func = build_invokevirtual (dtable, method); + break; - case INVOKE_SUPER: - case INVOKE_STATIC: - func = build_known_method_ref (method, TREE_TYPE (method), - DECL_CONTEXT (method), signature, args); - break; + case INVOKE_SUPER: + case INVOKE_STATIC: + func = build_known_method_ref (method, TREE_TYPE (method), + DECL_CONTEXT (method), + signature, args); + break; - case INVOKE_INTERFACE: - dtable = invoke_build_dtable (1, args); - func = build_invokeinterface (dtable, DECL_NAME (method), signature); - 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; + default: + fatal ("Unknown invocation mode `%d' - build_invoke", im); + return NULL_TREE; + } + + /* Ensure self_type is initialized, (invokestatic). FIXME */ + func = build1 (NOP_EXPR, build_pointer_type (TREE_TYPE (method)), func); } - /* Ensure self_type is initialized, (invokestatic). FIXME */ - func = build1 (NOP_EXPR, build_pointer_type (TREE_TYPE (method)), func); TREE_TYPE (patch) = TREE_TYPE (TREE_TYPE (method)); TREE_OPERAND (patch, 0) = func; TREE_OPERAND (patch, 1) = args; @@ -6539,6 +6504,11 @@ patch_invoke (patch, method, args, from_super) { tree class = DECL_CONTEXT (method); tree c1, saved_new, size, new; + if (flag_emit_class_files) + { + TREE_TYPE (patch) = build_pointer_type (class); + return patch; + } if (!TYPE_SIZE (class)) safe_layout_class (class); size = size_in_bytes (class); @@ -7023,11 +6993,66 @@ java_complete_tree (node) IDENTIFIER_LOCAL_VALUE (DECL_NAME (cn)) = cn; INITIALIZED_P (cn) = 0; } - if (BLOCK_EXPR_BODY (node)) + if (BLOCK_EXPR_BODY (node) == NULL_TREE) + CAN_COMPLETE_NORMALLY (node) = 1; + else { - BLOCK_EXPR_BODY (node) = java_complete_tree (BLOCK_EXPR_BODY (node)); - if (BLOCK_EXPR_BODY (node) == error_mark_node) + tree stmt = BLOCK_EXPR_BODY (node); + tree *ptr; + int error_seen = 0; + if (TREE_CODE (stmt) == COMPOUND_EXPR) + { + /* Re-order from (((A; B); C); ...; Z) to (A; (B; (C ; (...; Z)))). + This makes it easier to scan the statements left-to-right + without using recursion (which might overflow the stack + if the block has many statements. */ + for (;;) + { + tree left = TREE_OPERAND (stmt, 0); + if (TREE_CODE (left) != COMPOUND_EXPR) + break; + TREE_OPERAND (stmt, 0) = TREE_OPERAND (left, 1); + TREE_OPERAND (left, 1) = stmt; + stmt = left; + } + BLOCK_EXPR_BODY (node) = stmt; + } + + /* Now do the actual complete, without deep recursion for long blocks. */ + ptr = &BLOCK_EXPR_BODY (node); + while (TREE_CODE (*ptr) == COMPOUND_EXPR) + { + tree cur = java_complete_tree (TREE_OPERAND (*ptr, 0)); + tree *next = &TREE_OPERAND (*ptr, 1); + TREE_OPERAND (*ptr, 0) = cur; + if (TREE_CODE (cur) == ERROR_MARK) + error_seen++; + else if (! CAN_COMPLETE_NORMALLY (cur)) + { + wfl_op2 = *next; + for (;;) + { + if (TREE_CODE (wfl_op2) == BLOCK) + wfl_op2 = BLOCK_EXPR_BODY (wfl_op2); + else if (TREE_CODE (wfl_op2) == COMPOUND_EXPR) + wfl_op2 = TREE_OPERAND (wfl_op2, 0); + else + break; + } + if (TREE_CODE (wfl_op2) != CASE_EXPR + && TREE_CODE (wfl_op2) != DEFAULT_EXPR) + { + SET_WFL_OPERATOR (wfl_operator, *ptr, wfl_op2); + parse_error_context (wfl_operator, "Unreachable statement"); + } + } + ptr = next; + } + *ptr = java_complete_tree (*ptr); + + if (TREE_CODE (*ptr) == ERROR_MARK || error_seen > 0) return error_mark_node; + CAN_COMPLETE_NORMALLY (node) = CAN_COMPLETE_NORMALLY (*ptr); } /* Turn local bindings to null */ for (cn = BLOCK_EXPR_DECLS (node); cn; cn = TREE_CHAIN (cn)) @@ -7041,6 +7066,7 @@ java_complete_tree (node) case THROW_EXPR: wfl_op1 = TREE_OPERAND (node, 0); COMPLETE_CHECK_OP_0 (node); + /* CAN_COMPLETE_NORMALLY (node) = 0; */ return patch_throw_statement (node, wfl_op1); case SYNCHRONIZED_EXPR: @@ -7058,6 +7084,8 @@ java_complete_tree (node) COMPLETE_CHECK_OP_1 (node); TREE_TYPE (node) = void_type_node; POP_LABELED_BLOCK (); + if (CAN_COMPLETE_NORMALLY (LABELED_BLOCK_BODY (node))) + CAN_COMPLETE_NORMALLY (node) = 1; return node; case EXIT_BLOCK_EXPR: @@ -7065,6 +7093,58 @@ java_complete_tree (node) the EXIT_BLOCK_EXPR which doesn't exist it Java */ return patch_bc_statement (node); + case CASE_EXPR: + cn = java_complete_tree (TREE_OPERAND (node, 0)); + if (cn == error_mark_node) + return cn; + + /* First, the case expression must be constant */ + cn = fold (cn); + + if (!TREE_CONSTANT (cn)) + { + EXPR_WFL_LINECOL (wfl_operator) = EXPR_WFL_LINECOL (node); + parse_error_context (node, "Constant expression required"); + return error_mark_node; + } + + nn = ctxp->current_loop; + + /* It must be assignable to the type of the switch expression. */ + if (!try_builtin_assignconv (NULL_TREE, TREE_TYPE (TREE_OPERAND (nn, 0)), cn)) + { + EXPR_WFL_LINECOL (wfl_operator) = EXPR_WFL_LINECOL (node); + parse_error_context + (wfl_operator, + "Incompatible type for case. Can't convert `%s' to `int'", + lang_printable_name (TREE_TYPE (cn), 0)); + return error_mark_node; + } + + cn = fold (convert (int_type_node, cn)); + + /* Multiple instance of a case label bearing the same + value is checked during code generation. The case + expression is allright so far. */ + TREE_OPERAND (node, 0) = cn; + CAN_COMPLETE_NORMALLY (node) = 1; + break; + + case DEFAULT_EXPR: + nn = ctxp->current_loop; + /* Only one default label is allowed per switch statement */ + if (SWITCH_HAS_DEFAULT (nn)) + { + EXPR_WFL_LINECOL (wfl_operator) = EXPR_WFL_LINECOL (node); + parse_error_context (wfl_operator, + "Duplicate case label: `default'"); + return error_mark_node; + } + else + SWITCH_HAS_DEFAULT (nn) = 1; + CAN_COMPLETE_NORMALLY (node) = 1; + break; + case SWITCH_EXPR: case LOOP_EXPR: PUSH_LOOP (node); @@ -7086,7 +7166,11 @@ java_complete_tree (node) /* If we returned something different, that's because we inserted a label. Pop the label too. */ if (nn != node) - POP_LABELED_BLOCK (); + { + if (CAN_COMPLETE_NORMALLY (node)) + CAN_COMPLETE_NORMALLY (nn) = 1; + POP_LABELED_BLOCK (); + } POP_LOOP (); return nn; @@ -7121,24 +7205,38 @@ java_complete_tree (node) /* 3- Expression section */ case COMPOUND_EXPR: - TREE_OPERAND (node, 0) = java_complete_tree (TREE_OPERAND (node, 0)); + wfl_op2 = TREE_OPERAND (node, 1); + TREE_OPERAND (node, 0) = nn = java_complete_tree (TREE_OPERAND (node, 0)); + if (! CAN_COMPLETE_NORMALLY (nn) && TREE_CODE (nn) != ERROR_MARK) + { + SET_WFL_OPERATOR (wfl_operator, node, wfl_op2); + parse_error_context (wfl_operator, "Unreachable statement"); + } TREE_OPERAND (node, 1) = java_complete_tree (TREE_OPERAND (node, 1)); if (TREE_OPERAND (node, 1) == error_mark_node) return error_mark_node; TREE_TYPE (node) = TREE_TYPE (TREE_OPERAND (node, 1)); + CAN_COMPLETE_NORMALLY (node) + = CAN_COMPLETE_NORMALLY (TREE_OPERAND (node, 1)); break; case RETURN_EXPR: + /* CAN_COMPLETE_NORMALLY (node) = 0; */ return patch_return (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, NULL); + { + node = resolve_expression_name (node, NULL); + CAN_COMPLETE_NORMALLY (node) = 1; + } else { - EXPR_WFL_NODE (node) = java_complete_tree (EXPR_WFL_NODE (node)); + tree body = java_complete_tree (EXPR_WFL_NODE (node)); + EXPR_WFL_NODE (node) = body; TREE_SIDE_EFFECTS (node) = 1; + CAN_COMPLETE_NORMALLY (node) = CAN_COMPLETE_NORMALLY (body); if (EXPR_WFL_NODE (node) == error_mark_node) { /* Its important for the evaluation of assignment that @@ -7148,6 +7246,7 @@ java_complete_tree (node) } else TREE_TYPE (node) = TREE_TYPE (EXPR_WFL_NODE (node)); + } break; @@ -7175,10 +7274,12 @@ java_complete_tree (node) } /* They complete the array creation expression, if no errors were found. */ + CAN_COMPLETE_NORMALLY (node) = 1; return (flag ? error_mark_node : patch_newarray (node)); case NEW_CLASS_EXPR: case CALL_EXPR: + CAN_COMPLETE_NORMALLY (node) = 1; /* Complete function's argument(s) first */ if (complete_function_arguments (node)) return error_mark_node; @@ -7187,8 +7288,8 @@ java_complete_tree (node) tree decl, wfl = TREE_OPERAND (node, 0); int in_this = CALL_THIS_CONSTRUCTOR_P (node); - node = patch_method_invocation_stmt (node, NULL_TREE, - NULL_TREE, 0, &decl, 0); + node = patch_method_invocation (node, NULL_TREE, + NULL_TREE, 0, &decl, 0); if (node != error_mark_node) { check_thrown_exceptions (EXPR_WFL_LINECOL (node), decl); @@ -7228,14 +7329,6 @@ java_complete_tree (node) nn = java_complete_tree (TREE_OPERAND (node, 1)); if (nn == error_mark_node) { - /* It's hopeless, but we can further things on to discover - 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))) - patch_assignment (node, wfl_op1, wfl_op2); - /* Now, we still mark the lhs as initialized */ if (DECL_P (TREE_OPERAND (node, 0))) INITIALIZED_P (TREE_OPERAND (node, 0)) = 1; @@ -7249,7 +7342,9 @@ java_complete_tree (node) STRING_CST or a StringBuffer at this stage */ if ((nn = patch_string (TREE_OPERAND (node, 1)))) TREE_OPERAND (node, 1) = nn; - return patch_assignment (node, wfl_op1, wfl_op2); + node = patch_assignment (node, wfl_op1, wfl_op2); + CAN_COMPLETE_NORMALLY (node) = 1; + return node; case MULT_EXPR: case PLUS_EXPR: @@ -7275,6 +7370,7 @@ java_complete_tree (node) wfl_op1 = TREE_OPERAND (node, 0); wfl_op2 = TREE_OPERAND (node, 1); + CAN_COMPLETE_NORMALLY (node) = 1; /* Don't complete string nodes if dealing with the PLUS operand. */ if (TREE_CODE (node) != PLUS_EXPR || !JSTRING_P (wfl_op1)) { @@ -7307,6 +7403,7 @@ java_complete_tree (node) /* There are cases were wfl_op1 is a WFL. patch_unaryop knows how to handle those cases. */ wfl_op1 = TREE_OPERAND (node, 0); + CAN_COMPLETE_NORMALLY (node) = 1; TREE_OPERAND (node, 0) = java_complete_tree (wfl_op1); if (TREE_OPERAND (node, 0) == error_mark_node) return error_mark_node; @@ -7352,6 +7449,7 @@ java_complete_tree (node) return current_this; default: + CAN_COMPLETE_NORMALLY (node) = 1; /* Ok: may be we have a STRING_CST or a crafted `StringBuffer' and it's time to turn it into the appropriate String object */ @@ -7607,7 +7705,7 @@ build_assignment (op, op_location, lhs, rhs) /* Print an INTEGER_CST node in a static buffer, and return the buffer. */ -static char * +char * print_int_node (node) tree node; { @@ -8072,6 +8170,17 @@ valid_cast_to_p (source, dest) converted to type DEST through the methond invocation conversion process (5.3) */ +static tree +do_unary_numeric_promotion (arg) + tree arg; +{ + tree type = TREE_TYPE (arg); + if (TREE_CODE (type) == INTEGER_TYPE ? TYPE_PRECISION (type) < 32 + : TREE_CODE (type) == CHAR_TYPE) + arg = convert (int_type_node, arg); + return arg; +} + static int valid_method_invocation_conversion_p (dest, source) tree dest, source; @@ -8275,8 +8384,8 @@ patch_binop (node, wfl_op1, wfl_op2) /* Unary numeric promotion (5.6.1) is performed on each operand separatly */ - op1 = convert (promote_type (op1_type), op1); - op2 = convert (promote_type (op2_type), op2); + op1 = do_unary_numeric_promotion (op1); + op2 = do_unary_numeric_promotion (op2); /* The type of the shift expression is the type of the promoted type of the left-hand operand */ @@ -8291,7 +8400,7 @@ patch_binop (node, wfl_op1, wfl_op2) build_int_2 (0x3f, 0))); /* The >>> operator is a >> operating on unsigned quantities */ - if (code == URSHIFT_EXPR) + if (code == URSHIFT_EXPR && ! flag_emit_class_files) { op1 = convert (unsigned_type (prom_type), op1); TREE_SET_CODE (node, RSHIFT_EXPR); @@ -8325,6 +8434,11 @@ patch_binop (node, wfl_op1, wfl_op2) /* If the first operand is null, the result is always false */ if (op1 == null_pointer_node) return boolean_false_node; + else if (flag_emit_class_files) + { + TREE_OPERAND (node, 1) = op2_type; + return node; + } /* Otherwise we have to invoke instance of to figure it out */ else { @@ -8665,10 +8779,13 @@ patch_string_cst (node) tree node; { int location; - push_obstacks (&permanent_obstack, &permanent_obstack); - node = get_identifier (TREE_STRING_POINTER (node)); - location = alloc_name_constant (CONSTANT_String, node); - node = build_ref_from_constant_pool (location); + if (! flag_emit_class_files) + { + push_obstacks (&permanent_obstack, &permanent_obstack); + node = get_identifier (TREE_STRING_POINTER (node)); + location = alloc_name_constant (CONSTANT_String, node); + node = build_ref_from_constant_pool (location); + } TREE_TYPE (node) = promote_type (string_type_node); TREE_CONSTANT (node) = 1; return node; @@ -8821,8 +8938,8 @@ patch_unaryop (node, wfl_op) /* Unary numeric promotion is performed on operand */ else { - prom_type = promote_type (op_type); - op = convert (prom_type, op); + op = do_unary_numeric_promotion (op); + prom_type = TREE_TYPE (op); if (code == UNARY_PLUS_EXPR) node = op; } @@ -8838,8 +8955,8 @@ patch_unaryop (node, wfl_op) } else { - prom_type = promote_type (op_type); - op = convert (prom_type, op); + op = do_unary_numeric_promotion (op); + prom_type = TREE_TYPE (op); } break; @@ -8859,22 +8976,11 @@ patch_unaryop (node, wfl_op) case CONVERT_EXPR: value = patch_cast (node, wfl_operator); if (value == error_mark_node) - { - TREE_TYPE (node) = error_mark_node; - error_found = 1; - } - else - node = value; + return value; + node = value; break; } - /* Check variable initialization */ - if (not_initialized_as_it_should_p (op)) - { - ERROR_VARIABLE_NOT_INITIALIZED (wfl_op, DECL_NAME (op)); - INITIALIZED_P (op) = 1; - } - if (error_found) return error_mark_node; /* In the case of UNARY_PLUS_EXPR, we replaced NODE by a new one */ @@ -8958,7 +9064,16 @@ patch_cast (node, wfl_operator) conversion (5.2) */ if (valid_ref_assignconv_cast_p (op_type, cast_type, 0)) - return node; + { + TREE_SET_CODE (node, NOP_EXPR); + return node; + } + + if (flag_emit_class_files) + { + TREE_SET_CODE (node, CONVERT_EXPR); + return node; + } /* The cast requires a run-time check */ return build (CALL_EXPR, promote_type (cast_type), @@ -9009,17 +9124,10 @@ patch_array_ref (node, wfl_array, wfl_index) tree array_type = TREE_TYPE (array); tree index = TREE_OPERAND (node, 1); tree index_type = TREE_TYPE (index); - tree promoted_index_type; int error_found = 0; EXPR_WFL_LINECOL (wfl_operator) = EXPR_WFL_LINECOL (node); - if (not_initialized_as_it_should_p (array)) - { - ERROR_VARIABLE_NOT_INITIALIZED (wfl_array, DECL_NAME (array)); - INITIALIZED_P (array) = 1; - } - if (TREE_CODE (array_type) == POINTER_TYPE) array_type = TREE_TYPE (array_type); @@ -9035,8 +9143,8 @@ patch_array_ref (node, wfl_array, wfl_index) /* The array index underdoes unary numeric promotion. The promoted type must be int */ - promoted_index_type = promote_type (index_type); - if (promoted_index_type != int_type_node) + index = do_unary_numeric_promotion (index); + if (TREE_TYPE (index) != int_type_node) { int could_cast = valid_cast_to_p (index_type, int_type_node); parse_error_context @@ -9049,26 +9157,15 @@ patch_array_ref (node, wfl_array, wfl_index) error_found = 1; } - /* Now if the index is a var/parm decl, check on its initialization */ - if (not_initialized_as_it_should_p (index)) - { - ERROR_VARIABLE_NOT_INITIALIZED (wfl_index, DECL_NAME (index)); - INITIALIZED_P (index) = 1; - } - if (error_found) return error_mark_node; - index = convert (promoted_index_type, index); 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; - TREE_OPERAND (node, 1)= index; + TREE_OPERAND (node, 0) = array; + TREE_OPERAND (node, 1) = index; } else node = build_java_arrayaccess (array, array_type, index); @@ -9100,7 +9197,6 @@ patch_newarray (node) int error_found = 0; int ndims = 0; int xdims = TREE_INT_CST_LOW (TREE_OPERAND (node, 2)); - int total_dims; /* Dimension types are verified. It's better for the types to be verified in order. */ @@ -9120,7 +9216,7 @@ patch_newarray (node) promoted type must be int. */ else { - dim = convert (promote_type (TREE_TYPE (dim)), dim); + dim = do_unary_numeric_promotion (dim); if (TREE_TYPE (dim) != int_type_node) dim_error = 1; } @@ -9138,15 +9234,6 @@ patch_newarray (node) error_found = 1; } - /* Check for uninitialized variables */ - if (not_initialized_as_it_should_p (dim)) - { - ERROR_VARIABLE_NOT_INITIALIZED (TREE_PURPOSE (cdim), - DECL_NAME (dim)); - INITIALIZED_P (dim) = 1; - error_found = 1; - } - TREE_PURPOSE (cdim) = NULL_TREE; } @@ -9162,12 +9249,30 @@ patch_newarray (node) return error_mark_node; } + /* Set array_type to the actual (promoted) array type of the result. */ + if (TREE_CODE (type) == RECORD_TYPE) + type = build_pointer_type (type); + while (--xdims >= 0) + { + type = promote_type (build_java_array_type (type, -1)); + } + dims = nreverse (dims); + array_type = type; + for (cdim = dims; cdim; cdim = TREE_CHAIN (cdim)) + { + type = array_type; + array_type = build_java_array_type (type, + TREE_CODE (cdim) == INTEGER_CST ? + TREE_INT_CST_LOW (cdim) : -1); + array_type = promote_type (array_type); + } + dims = nreverse (dims); + /* The node is transformed into a function call. Things are done differently according to the number of dimensions. If the number of dimension is equal to 1, then the nature of the base type (primitive or not) matters. */ - total_dims = xdims + ndims; - if (total_dims == 1) + if (ndims == 1) { if (JPRIMITIVE_TYPE_P (type)) { @@ -9193,28 +9298,16 @@ patch_newarray (node) return build_newarray (type_code, TREE_VALUE (dims)); } else - return build_anewarray (type, TREE_VALUE (dims)); + return build_anewarray (TREE_TYPE (type), TREE_VALUE (dims)); } - /* Add extra dimensions as unknown dimensions */ - while (xdims--) - dims = - chainon (dims, build_tree_list (NULL_TREE, integer_negative_one_node)); - dims = chainon (dims, build_tree_list (NULL_TREE, integer_zero_node)); - /* Can't reuse what's already written in expr.c because it uses the JVM stack representation. Provide a build_multianewarray. FIXME */ - array_type = type; - for (cdim = TREE_CHAIN (dims); cdim; cdim = TREE_CHAIN (cdim)) - array_type = build_java_array_type (promote_type (array_type), - TREE_CODE (cdim) == INTEGER_CST ? - TREE_INT_CST_LOW (cdim) : -1); - return build (CALL_EXPR, - promote_type (array_type), + return build (CALL_EXPR, array_type, build_address_of (soft_multianewarray_node), - tree_cons (NULL_TREE, build_class_ref (array_type), + tree_cons (NULL_TREE, build_class_ref (TREE_TYPE (array_type)), tree_cons (NULL_TREE, - build_int_2 (total_dims, 0), dims )), + build_int_2 (ndims, 0), dims )), NULL_TREE); } @@ -9363,6 +9456,9 @@ patch_if_else_statement (node) TREE_TYPE (node) = void_type_node; TREE_SIDE_EFFECTS (node) = 1; + CAN_COMPLETE_NORMALLY (node) + = CAN_COMPLETE_NORMALLY (TREE_OPERAND (node, 0)) + | CAN_COMPLETE_NORMALLY (TREE_OPERAND (node, 1)); return node; } @@ -9676,9 +9772,11 @@ patch_bc_statement (node) /* Everything looks good. We can fix the `continue' jump to go at the place in the loop were the continue is. The continue is the current labeled block, by construction. */ - EXIT_BLOCK_LABELED_BLOCK (node) = ctxp->current_labeled_block; + EXIT_BLOCK_LABELED_BLOCK (node) = bc_label = ctxp->current_labeled_block; } + CAN_COMPLETE_NORMALLY (bc_label) = 1; + /* Our break/continue don't return values. */ TREE_TYPE (node) = void_type_node; /* Encapsulate the break within a compound statement so that it's @@ -9714,6 +9812,15 @@ patch_exit_expr (node) return */ TREE_OPERAND (node, 0) = fold (build1 (TRUTH_NOT_EXPR, boolean_type_node, expression)); + + if (! integer_zerop (TREE_OPERAND (node, 0)) + && ctxp->current_loop != NULL_TREE + && TREE_CODE (ctxp->current_loop) == LOOP_EXPR) + CAN_COMPLETE_NORMALLY (ctxp->current_loop) = 1; + if (! integer_onep (TREE_OPERAND (node, 0))) + CAN_COMPLETE_NORMALLY (node) = 1; + + TREE_TYPE (node) = void_type_node; return node; } @@ -9724,9 +9831,7 @@ static tree patch_switch_statement (node) tree node; { - int error_found = 0; tree se = TREE_OPERAND (node, 0), se_type, sb; - tree default_found = NULL_TREE; /* Complete the switch expression */ se = TREE_OPERAND (node, 0) = java_complete_tree (se); @@ -9744,150 +9849,21 @@ patch_switch_statement (node) return error_mark_node; } - /* Process the switch body. We should have a list of TREE_LIST. The - PURPOSE of each node should be a list of case values, VALUE - should be the associated block. We try to process all cases and - defaults before returning, possibly finding errors. */ - TREE_OPERAND (node, 1) = nreverse (TREE_OPERAND (node, 1)); - for (sb = TREE_OPERAND (node, 1); sb; sb = TREE_CHAIN (sb)) - { - tree label; - - /* If we don't have a TREE_LIST here, we have a statement inside - the switch that isn't tied to a label. This error is caught - by the parser and we don't have to report it here. */ - - TREE_PURPOSE (sb) = nreverse (TREE_PURPOSE (sb)); - for (label = TREE_PURPOSE (sb); label; label = TREE_CHAIN (label)) - { - tree case_expr; - - /* Verification of the default label */ - if (TREE_CODE (label) == DEFAULT_EXPR) - { - /* Only one default label is allowed per switch - statement */ - if (default_found) - { - EXPR_WFL_LINECOL (wfl_operator) = EXPR_WFL_LINECOL (label); - parse_error_context (wfl_operator, - "Duplicate case label: `default'"); - error_found = 1; - } - else - default_found = label; - continue; - } - /* Verification of case labels */ - else - { - case_expr = java_complete_tree (TREE_OPERAND (label, 0)); - if (case_expr == error_mark_node) - continue; - - /* First, the case expression must be constant */ - case_expr = fold (case_expr); - if (!TREE_CONSTANT (case_expr)) - { - EXPR_WFL_LINECOL (wfl_operator) = EXPR_WFL_LINECOL (label); - parse_error_context (label, "Constant expression required"); - error_found = 1; - break; - } - - /* It must be assignable to the type of the switch - expression. */ - if (!try_builtin_assignconv (NULL_TREE, se_type, case_expr)) - { - EXPR_WFL_LINECOL (wfl_operator) = EXPR_WFL_LINECOL (label); - parse_error_context - (wfl_operator, - "Incompatible type for case. Can't convert `%s' to `int'", - lang_printable_name (TREE_TYPE (case_expr), 0)); - error_found = 1; - break; - } - - /* Multiple instance of a case label bearing the same - value is checked during code generation. The case - expression is allright so far. */ - TREE_OPERAND (label, 0) = case_expr; - } - } - - /* First TREE_VALUE should be the block tied to this list of - cases. Check that this block exists and the walk it */ - if (TREE_VALUE (sb)) - { - TREE_VALUE (sb) = java_complete_tree (TREE_VALUE (sb)); - if (TREE_VALUE (sb) == error_mark_node) - error_found = 1; - } - } + TREE_OPERAND (node, 1) = java_complete_tree (TREE_OPERAND (node, 1)); /* Ready to return */ - if (error_found) + if (TREE_CODE (TREE_OPERAND (node, 1)) == ERROR_MARK) { TREE_TYPE (node) = error_mark_node; return error_mark_node; } TREE_TYPE (node) = void_type_node; TREE_SIDE_EFFECTS (node) = 1; + CAN_COMPLETE_NORMALLY (node) + = CAN_COMPLETE_NORMALLY (TREE_OPERAND (node, 1)) || ! SWITCH_HAS_DEFAULT (node); return node; } -/* Do the expansion of a Java switch. With Gcc, switches are front-end - dependant things, but they rely on gcc routines. This function is - placed here because it uses things defined locally in parse.y. */ - -static tree case_identity (t, v) - tree t __attribute__ ((__unused__)); - tree v; -{ - return v; -} - -void -java_expand_switch (exp) - tree exp; -{ - tree sb; - expand_start_case (0, TREE_OPERAND (exp, 0), int_type_node, "switch"); - - for (sb = TREE_OPERAND (exp, 1); sb; sb = TREE_CHAIN (sb)) - { - /* We have a list of TREE_LIST. PURPOSE is the case value, and - when it exists, VALUE is the associated block */ - - /* The first CASE element should contain the associated block, - if any. All other should be case statements related to the - same block */ - tree label; - for (label = TREE_PURPOSE (sb); label; label = TREE_CHAIN (label)) - { - tree label_decl = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE); - if (TREE_CODE (label) == CASE_EXPR) - { - tree duplicate; - if (pushcase (TREE_OPERAND (label, 0), case_identity, - label_decl, &duplicate) == 2) - { - EXPR_WFL_LINECOL (wfl_operator) = EXPR_WFL_LINECOL (label); - parse_error_context - (wfl_operator, "Duplicate case label: `%s'", - print_int_node (TREE_OPERAND (label, 0))); - } - } - else - pushcase (NULL_TREE, 0, label_decl, NULL); - } - /* Expand the associated block, if any */ - if (TREE_VALUE (sb)) - expand_expr_stmt (TREE_VALUE (sb)); - } - expand_end_case (TREE_OPERAND (exp, 0)); -} - /* 14.18 The try statement */ /* Wrap BLOCK around a LABELED_BLOCK, set DECL to the newly generated @@ -9926,7 +9902,7 @@ build_try_statement (location, try_block, catches, finally) { tree node, rff; - if (finally) + if (finally && ! flag_emit_class_files) { /* This block defines a scope for the entire try[-catch]-finally sequence. It hold a local variable used to return from the @@ -9993,7 +9969,8 @@ build_try_statement (location, try_block, catches, finally) /* If we have a finally, surround this whole thing by a block where the RFF local variable is defined. */ - return (finally ? build_expr_block (node, rff) : node); + return (finally && ! flag_emit_class_files ? build_expr_block (node, rff) + : node); } /* Get the catch clause block from an element of the catch clause @@ -10100,13 +10077,6 @@ patch_try_statement (node) break; } } - if (unreachable) - continue; - - /* Things to do here: the exception must be thrown */ - - /* Link this type to the caught type list */ - caught_type_list = tree_cons (NULL_TREE, carg_type, caught_type_list); /* Complete the catch clause block */ catch_block = java_complete_tree (TREE_OPERAND (current, 0)); @@ -10115,21 +10085,36 @@ patch_try_statement (node) error_found = 1; continue; } + if (CAN_COMPLETE_NORMALLY (catch_block)) + CAN_COMPLETE_NORMALLY (node) = 1; TREE_OPERAND (current, 0) = catch_block; + + if (unreachable) + continue; + + /* Things to do here: the exception must be thrown */ + + /* Link this type to the caught type list */ + caught_type_list = tree_cons (NULL_TREE, carg_type, caught_type_list); + } PUSH_EXCEPTIONS (caught_type_list); if ((try = java_complete_tree (try)) == error_mark_node) error_found = 1; + if (CAN_COMPLETE_NORMALLY (try)) + CAN_COMPLETE_NORMALLY (node) = 1; POP_EXCEPTIONS (); /* Process finally */ if (finally) { - FINALLY_EXPR_BLOCK (finally) = - java_complete_tree (FINALLY_EXPR_BLOCK (finally)); - if (FINALLY_EXPR_BLOCK (finally) == error_mark_node) + current = java_complete_tree (FINALLY_EXPR_BLOCK (finally)); + FINALLY_EXPR_BLOCK (finally) = current; + if (current == error_mark_node) error_found = 1; + if (! CAN_COMPLETE_NORMALLY (current)) + CAN_COMPLETE_NORMALLY (node) = 0; } /* Verification ends here */ @@ -10276,7 +10261,8 @@ patch_throw_statement (node, wfl_op1) unchecked exception or its value is always caught by some try statement that contains it. FIXME, static initializer. */ - BUILD_THROW (node, expr); + if (! flag_emit_class_files) + BUILD_THROW (node, expr); return node; } @@ -10447,5 +10433,6 @@ patch_conditional_expr (node, wfl_cond, wfl_op1) TREE_TYPE (node) = resulting_type; TREE_SET_CODE (node, COND_EXPR); + CAN_COMPLETE_NORMALLY (node) = 1; return node; }