From 939d7216dca76eac6675e54f10154ad5d2898cfa Mon Sep 17 00:00:00 2001 From: Per Bothner Date: Sun, 21 Feb 1999 07:42:27 -0800 Subject: [PATCH] decl.c (build_result_decl): New method. d * decl.c (build_result_decl), java-tree.h: New method. (complete_start_java_method): Handle synchronized methods. Don't build DECL_RESULT here. (Ordering dependency problem.) (start_java_method): Call build_result_decl here instead ... * parse.y (java_complete_expand_method): ... and here. (expand_start_java_method): Don't call complete_start_java_method here. (java_complete_expand_method): Call it here instead. * parse.h (BUILD_MONITOR_ENTER, BUILD_MONITOR_EXIT): Moved to .. * java-tree.h: ... here. * expr.c (force_evaluation_order): Fix typo, don't handle ARRAY_REF. * parse.y (java_complete_lhs): Don't call force_evaluation_order for ARRAY_REF - it doesn't work when array bounds are checked. (patch_array_ref): Handle it here instead. From-SVN: r25346 --- gcc/java/decl.c | 34 +++++++++++++--- gcc/java/expr.c | 3 +- gcc/java/java-tree.h | 19 +++++++++ gcc/java/parse.c | 95 ++++++++++++++++++++++++++++++-------------- gcc/java/parse.h | 18 --------- gcc/java/parse.y | 17 ++++++-- 6 files changed, 128 insertions(+), 58 deletions(-) diff --git a/gcc/java/decl.c b/gcc/java/decl.c index 5293ddc906e..14b8ece1367 100644 --- a/gcc/java/decl.c +++ b/gcc/java/decl.c @@ -1465,8 +1465,8 @@ give_name_to_locals (jcf) } } -void -complete_start_java_method (fndecl) +tree +build_result_decl (fndecl) tree fndecl; { tree restype = TREE_TYPE (TREE_TYPE (fndecl)); @@ -1474,8 +1474,13 @@ complete_start_java_method (fndecl) if (INTEGRAL_TYPE_P (restype) && TYPE_PRECISION (restype) < TYPE_PRECISION (integer_type_node)) restype = integer_type_node; - DECL_RESULT (fndecl) = build_decl (RESULT_DECL, NULL_TREE, restype); + return (DECL_RESULT (fndecl) = build_decl (RESULT_DECL, NULL_TREE, restype)); +} +void +complete_start_java_method (fndecl) + tree fndecl; +{ if (! flag_emit_class_files) { /* Initialize the RTL code for the function. */ @@ -1509,9 +1514,27 @@ complete_start_java_method (fndecl) expand_expr_stmt (init); } - if (METHOD_SYNCHRONIZED (fndecl)) + if (METHOD_SYNCHRONIZED (fndecl) && ! flag_emit_class_files + && DECL_FUNCTION_BODY (fndecl) != NULL_TREE) { - /* FIXME: surround the function body by a try/finally set. */ + /* Warp function body with a monitorenter plus monitorexit cleanup. */ + tree function_body = DECL_FUNCTION_BODY (fndecl); + tree body = BLOCK_EXPR_BODY (function_body); + tree enter, exit, lock; + if (METHOD_STATIC (fndecl)) + lock = build_class_ref (DECL_CONTEXT (fndecl)); + else + lock = DECL_ARGUMENTS (fndecl); + BUILD_MONITOR_ENTER (enter, lock); + BUILD_MONITOR_EXIT (exit, lock); + lock = build (WITH_CLEANUP_EXPR, void_type_node, + enter, NULL_TREE, exit); + TREE_SIDE_EFFECTS (lock) = 1; + lock = build (COMPOUND_EXPR, TREE_TYPE (body), lock, body); + TREE_SIDE_EFFECTS (lock) = 1; + lock = build1 (CLEANUP_POINT_EXPR, TREE_TYPE (body), lock); + TREE_SIDE_EFFECTS (lock) = 1; + BLOCK_EXPR_BODY (function_body) = lock; } /* Push local variables. Function compiled from source code are @@ -1578,6 +1601,7 @@ start_java_method (fndecl) while (i < DECL_MAX_LOCALS(fndecl)) type_map[i++] = NULL_TREE; + build_result_decl (fndecl); complete_start_java_method (fndecl); } diff --git a/gcc/java/expr.c b/gcc/java/expr.c index 0848806ac5b..7e2e26cbd69 100644 --- a/gcc/java/expr.c +++ b/gcc/java/expr.c @@ -2492,8 +2492,7 @@ force_evaluation_order (node) { if (flag_syntax_only) return node; - if (TREE_CODE_CLASS (TREE_CODE (node)) == '2' - && TREE_CODE (node) == ARRAY_REF) + if (TREE_CODE_CLASS (TREE_CODE (node)) == '2') { if (TREE_SIDE_EFFECTS (TREE_OPERAND (node, 1))) TREE_OPERAND (node, 0) = save_expr (TREE_OPERAND (node, 0)); diff --git a/gcc/java/java-tree.h b/gcc/java/java-tree.h index ad1880d9601..28cba1c7104 100644 --- a/gcc/java/java-tree.h +++ b/gcc/java/java-tree.h @@ -552,6 +552,7 @@ extern int get_access_flags_from_decl PROTO ((tree)); extern int interface_of_p PROTO ((tree, tree)); extern int inherits_from_p PROTO ((tree, tree)); extern void complete_start_java_method PROTO ((tree)); +extern tree build_result_decl PROTO ((tree)); extern void emit_handlers PROTO (()); extern void init_outgoing_cpool PROTO (()); extern void make_class_data PROTO ((tree)); @@ -861,6 +862,24 @@ extern tree *type_map; #define BLOCK_EXPR_DECLS(NODE) BLOCK_VARS(NODE) #define BLOCK_EXPR_BODY(NODE) BLOCK_SUBBLOCKS(NODE) +#define BUILD_MONITOR_ENTER(WHERE, ARG) \ + { \ + (WHERE) = build (CALL_EXPR, int_type_node, \ + build_address_of (soft_monitorenter_node), \ + build_tree_list (NULL_TREE, (ARG)), \ + NULL_TREE); \ + TREE_SIDE_EFFECTS (WHERE) = 1; \ + } + +#define BUILD_MONITOR_EXIT(WHERE, ARG) \ + { \ + (WHERE) = build (CALL_EXPR, int_type_node, \ + build_address_of (soft_monitorexit_node), \ + build_tree_list (NULL_TREE, (ARG)), \ + NULL_TREE); \ + TREE_SIDE_EFFECTS (WHERE) = 1; \ + } + /* Non zero if TYPE is an unchecked exception */ #define IS_UNCHECKED_EXCEPTION_P(TYPE) \ (inherits_from_p ((TYPE), runtime_exception_type_node) \ diff --git a/gcc/java/parse.c b/gcc/java/parse.c index 74530c3b675..13744dfcfc9 100644 --- a/gcc/java/parse.c +++ b/gcc/java/parse.c @@ -8066,7 +8066,6 @@ expand_start_java_method (fndecl) *ptr = NULL_TREE; pushdecl_force_head (DECL_ARGUMENTS (fndecl)); lineno = DECL_SOURCE_LINE_FIRST (fndecl); - complete_start_java_method (fndecl); } /* Terminate a function and expand its body. */ @@ -8333,6 +8332,7 @@ java_complete_expand_method (mdecl) tree fbody = DECL_FUNCTION_BODY (mdecl); tree block_body = BLOCK_EXPR_BODY (fbody); expand_start_java_method (mdecl); + build_result_decl (mdecl); current_this = (!METHOD_STATIC (mdecl) ? @@ -8355,6 +8355,8 @@ java_complete_expand_method (mdecl) && TREE_CODE (TREE_TYPE (TREE_TYPE (mdecl))) != VOID_TYPE) missing_return_error (current_function_decl); + complete_start_java_method (mdecl); + /* Don't go any further if we've found error(s) during the expansion */ if (!java_error_count) @@ -9052,8 +9054,9 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found) return 1; } - if (!(field_decl = - lookup_field_wrapper (type, EXPR_WFL_NODE (qual_wfl)))) + field_decl = lookup_field_wrapper (type, + EXPR_WFL_NODE (qual_wfl)); + if (field_decl == NULL_TREE) { parse_error_context (qual_wfl, "No variable `%s' defined in class `%s'", @@ -9061,6 +9064,8 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found) IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)))); return 1; } + if (field_decl == error_mark_node) + return 1; /* Layout the type of field_decl, since we may need it. Don't do primitive types or loaded classes. The @@ -10178,7 +10183,8 @@ java_complete_lhs (node) /* Now do the actual complete, without deep recursion for long blocks. */ ptr = &BLOCK_EXPR_BODY (node); - while (TREE_CODE (*ptr) == COMPOUND_EXPR) + while (TREE_CODE (*ptr) == COMPOUND_EXPR + && TREE_OPERAND (*ptr, 1) != empty_stmt_node) { tree cur = java_complete_tree (TREE_OPERAND (*ptr, 0)); tree *next = &TREE_OPERAND (*ptr, 1); @@ -10198,8 +10204,7 @@ java_complete_lhs (node) break; } if (TREE_CODE (wfl_op2) != CASE_EXPR - && TREE_CODE (wfl_op2) != DEFAULT_EXPR - && wfl_op2 != empty_stmt_node) + && TREE_CODE (wfl_op2) != DEFAULT_EXPR) unreachable_stmt_error (*ptr); } ptr = next; @@ -10389,26 +10394,30 @@ java_complete_lhs (node) 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 - && wfl_op2 != empty_stmt_node) - { - /* An unreachable condition in a do-while statement - is *not* (technically) an unreachable statement. */ - nn = wfl_op2; - if (TREE_CODE (nn) == EXPR_WITH_FILE_LOCATION) - nn = EXPR_WFL_NODE (nn); - if (TREE_CODE (nn) != EXIT_EXPR) + if (wfl_op2 == empty_stmt_node) + CAN_COMPLETE_NORMALLY (node) = CAN_COMPLETE_NORMALLY (nn); + else + { + 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"); + /* An unreachable condition in a do-while statement + is *not* (technically) an unreachable statement. */ + nn = wfl_op2; + if (TREE_CODE (nn) == EXPR_WITH_FILE_LOCATION) + nn = EXPR_WFL_NODE (nn); + if (TREE_CODE (nn) != EXIT_EXPR) + { + 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; + CAN_COMPLETE_NORMALLY (node) + = CAN_COMPLETE_NORMALLY (TREE_OPERAND (node, 1)); } - 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: @@ -10420,6 +10429,8 @@ java_complete_lhs (node) || TREE_CODE (EXPR_WFL_NODE (node)) == IDENTIFIER_NODE) { node = resolve_expression_name (node, NULL); + if (node == error_mark_node) + return node; CAN_COMPLETE_NORMALLY (node) = 1; } else @@ -10430,9 +10441,9 @@ java_complete_lhs (node) body = java_complete_tree (EXPR_WFL_NODE (node)); lineno = save_lineno; EXPR_WFL_NODE (node) = body; - TREE_SIDE_EFFECTS (node) = 1; + TREE_SIDE_EFFECTS (node) = TREE_SIDE_EFFECTS (body); CAN_COMPLETE_NORMALLY (node) = CAN_COMPLETE_NORMALLY (body); - if (EXPR_WFL_NODE (node) == error_mark_node) + if (body == error_mark_node) { /* Its important for the evaluation of assignment that this mark on the TREE_TYPE is propagated. */ @@ -10494,7 +10505,7 @@ java_complete_lhs (node) tree_cons (wfl, decl, DECL_CONSTRUCTOR_CALLS (current_function_decl)); CAN_COMPLETE_NORMALLY (node) = 1; - return node; + return force_evaluation_order (node); } case MODIFY_EXPR: @@ -10603,7 +10614,7 @@ java_complete_lhs (node) if (TREE_OPERAND (node, 1) == error_mark_node) return error_mark_node; } - return patch_binop (node, wfl_op1, wfl_op2); + return force_evaluation_order (patch_binop (node, wfl_op1, wfl_op2)); case INSTANCEOF_EXPR: wfl_op1 = TREE_OPERAND (node, 0); @@ -11573,6 +11584,8 @@ patch_binop (node, wfl_op1, wfl_op2) { tree mod = build_java_binop (TRUNC_MOD_EXPR, prom_type, op1, op2); COMPOUND_ASSIGN_P (mod) = COMPOUND_ASSIGN_P (node); + TREE_SIDE_EFFECTS (mod) + = TREE_SIDE_EFFECTS (op1) | TREE_SIDE_EFFECTS (op2); return mod; } break; @@ -11659,6 +11672,8 @@ patch_binop (node, wfl_op1, wfl_op2) to_return = convert (prom_type, node); /* Copy the original value of the COMPOUND_ASSIGN_P flag */ COMPOUND_ASSIGN_P (to_return) = COMPOUND_ASSIGN_P (node); + TREE_SIDE_EFFECTS (to_return) + = TREE_SIDE_EFFECTS (op1) | TREE_SIDE_EFFECTS (op2); return to_return; } break; @@ -11693,6 +11708,7 @@ patch_binop (node, wfl_op1, wfl_op2) else if (flag_emit_class_files) { TREE_OPERAND (node, 1) = op2_type; + TREE_SIDE_EFFECTS (node) = TREE_SIDE_EFFECTS (op1); return node; } /* Otherwise we have to invoke instance of to figure it out */ @@ -11706,7 +11722,7 @@ patch_binop (node, wfl_op1, wfl_op2) build_tree_list (NULL_TREE, build_class_ref (op2_type))), NULL_TREE); - TREE_SIDE_EFFECTS (call) = 1; + TREE_SIDE_EFFECTS (call) = TREE_SIDE_EFFECTS (op1); return call; } } @@ -11843,6 +11859,8 @@ patch_binop (node, wfl_op1, wfl_op2) TREE_OPERAND (node, 0) = op1; TREE_OPERAND (node, 1) = op2; TREE_TYPE (node) = prom_type; + TREE_SIDE_EFFECTS (node) = TREE_SIDE_EFFECTS (op1) | TREE_SIDE_EFFECTS (op2); + return fold (node); } @@ -11962,6 +11980,8 @@ build_string_concatenation (op1, op2) tree op1, op2; { tree result; + int side_effects = TREE_SIDE_EFFECTS (op1) | TREE_SIDE_EFFECTS (op2); + /* Try to do some static optimization */ if ((result = string_constant_concatenation (op1, op2))) @@ -12014,7 +12034,8 @@ build_string_concatenation (op1, op2) /* Mark the last node holding a crafted StringBuffer */ IS_CRAFTED_STRING_BUFFER_P (op1) = 1; - + + TREE_SIDE_EFFECTS (op1) = side_effects; return op1; } @@ -12264,7 +12285,11 @@ patch_unaryop (node, wfl_op) error_found = 1; } else - return fold (value); + { + value = fold (value); + TREE_SIDE_EFFECTS (value) = TREE_SIDE_EFFECTS (op); + return value; + } break; } @@ -12276,6 +12301,7 @@ patch_unaryop (node, wfl_op) CONVERT_EXPR, {POST,PRE}{INCR,DECR}EMENT_EXPR. */ TREE_OPERAND (node, 0) = fold (op); TREE_TYPE (node) = prom_type; + TREE_SIDE_EFFECTS (node) = TREE_SIDE_EFFECTS (op); return fold (node); } @@ -12464,7 +12490,16 @@ patch_array_ref (node) TREE_OPERAND (node, 1) = index; } else - node = build_java_arrayaccess (array, array_type, index); + { + /* The save_expr is for correct evaluation order. It would be cleaner + to use force_evaluation_order (see comment there), but that is + difficult when we also have to deal with bounds checking. */ + if (TREE_SIDE_EFFECTS (index)) + array = save_expr (array); + node = build_java_arrayaccess (array, array_type, index); + if (TREE_SIDE_EFFECTS (index)) + node = build (COMPOUND_EXPR, array_type, array, node); + } TREE_TYPE (node) = array_type; return node; } diff --git a/gcc/java/parse.h b/gcc/java/parse.h index aa35bd6d58d..fa6b338ebd6 100644 --- a/gcc/java/parse.h +++ b/gcc/java/parse.h @@ -509,24 +509,6 @@ static jdeplist *reverse_jdep_list (); (ARG ? build_tree_list (NULL, (ARG)) : NULL_TREE)) /* For exception handling, build diverse function calls */ -#define BUILD_MONITOR_ENTER(WHERE, ARG) \ - { \ - (WHERE) = build (CALL_EXPR, int_type_node, \ - build_address_of (soft_monitorenter_node), \ - build_tree_list (NULL_TREE, (ARG)), \ - NULL_TREE); \ - TREE_SIDE_EFFECTS (WHERE) = 1; \ - } - -#define BUILD_MONITOR_EXIT(WHERE, ARG) \ - { \ - (WHERE) = build (CALL_EXPR, int_type_node, \ - build_address_of (soft_monitorexit_node), \ - build_tree_list (NULL_TREE, (ARG)), \ - NULL_TREE); \ - TREE_SIDE_EFFECTS (WHERE) = 1; \ - } - #define BUILD_ASSIGN_EXCEPTION_INFO(WHERE, TO) \ { \ (WHERE) = build (MODIFY_EXPR, void_type_node, (TO), \ diff --git a/gcc/java/parse.y b/gcc/java/parse.y index b548ad1b1a1..8964e450fda 100644 --- a/gcc/java/parse.y +++ b/gcc/java/parse.y @@ -5464,7 +5464,6 @@ expand_start_java_method (fndecl) *ptr = NULL_TREE; pushdecl_force_head (DECL_ARGUMENTS (fndecl)); lineno = DECL_SOURCE_LINE_FIRST (fndecl); - complete_start_java_method (fndecl); } /* Terminate a function and expand its body. */ @@ -5731,6 +5730,7 @@ java_complete_expand_method (mdecl) tree fbody = DECL_FUNCTION_BODY (mdecl); tree block_body = BLOCK_EXPR_BODY (fbody); expand_start_java_method (mdecl); + build_result_decl (mdecl); current_this = (!METHOD_STATIC (mdecl) ? @@ -5753,6 +5753,8 @@ java_complete_expand_method (mdecl) && TREE_CODE (TREE_TYPE (TREE_TYPE (mdecl))) != VOID_TYPE) missing_return_error (current_function_decl); + complete_start_java_method (mdecl); + /* Don't go any further if we've found error(s) during the expansion */ if (!java_error_count) @@ -8053,7 +8055,7 @@ java_complete_lhs (node) return error_mark_node; if (!flag_emit_class_files) TREE_OPERAND (node, 1) = save_expr (TREE_OPERAND (node, 1)); - return force_evaluation_order (patch_array_ref (node)); + return patch_array_ref (node); case RECORD_TYPE: return node;; @@ -9886,7 +9888,16 @@ patch_array_ref (node) TREE_OPERAND (node, 1) = index; } else - node = build_java_arrayaccess (array, array_type, index); + { + /* The save_expr is for correct evaluation order. It would be cleaner + to use force_evaluation_order (see comment there), but that is + difficult when we also have to deal with bounds checking. */ + if (TREE_SIDE_EFFECTS (index)) + array = save_expr (array); + node = build_java_arrayaccess (array, array_type, index); + if (TREE_SIDE_EFFECTS (index)) + node = build (COMPOUND_EXPR, array_type, array, node); + } TREE_TYPE (node) = array_type; return node; } -- 2.30.2