diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 8996c44b5123..b242b3e67b10 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,31 @@ 1999-09-10 Mark Mitchell + * cp-tree.h (language_function): Rename expanding_p to + x_expanding_p. Rename named_label_uses to x_named_label_uses. + (expanding_p): Adjust accordingly. + (TREE_VIA_PRIVATE): Fix typo in comment. + (DECL_REFERENCE_SLOT): Remove. + (SET_DECL_REFERENCE_SLOT): Likewise. + * decl.c (named_label_uses): Adjust. Remove chicken comment. + (push_overloaded_decl): Don't truncate the chain of bindings when + adding an overloaded function. + (grok_reference_init): Don't use DECL_REFERENCE_SLOT. + (initialize_local_var): Fix typo in comment. + (store_parm_decls): Don't set DECL_REFERENCE_SLOT. Tidy up. + * decl2.c (start_objects): Make the fact that we are expanding + the generated function right away explicit. + (start_static_storage_duration_function): Likewise. + (finish_file): Fix typo in comment. + * init.c (build_vec_init): Correct bugs in handling cleanups. + * semantics.c (maybe_convert_cond): New function. + (FINISH_COND): Always store the condition, even if there's + a declaration. + (finish_if_stmt_cond): Use maybe_convert_cond. + (finish_while_stmt_cond): Likewise. + (finish_do_stmt): Likewise. + (finish_for_cond): Likewise. + (expand_cond): Adjust. + * cp-tree.h (FN_TRY_BLOCK_P): New macro. * init.c (perform_member_init): Remove obstack machinations. (expand_cleanup_for_base): Likewise. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 79eae1a6b7ab..74ef7af849e3 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -634,10 +634,10 @@ struct language_function int temp_name_counter; int static_labelno; int in_function_try_handler; - int expanding_p; + int x_expanding_p; int stmts_are_full_exprs_p; - struct named_label_list *named_label_uses; + struct named_label_list *x_named_label_uses; struct binding_level *bindings; }; @@ -719,7 +719,7 @@ struct language_function When this is zero, we just accumulate tree structure, without interacting with the back end. */ -#define expanding_p cp_function_chain->expanding_p +#define expanding_p cp_function_chain->x_expanding_p /* Non-zero if we should treat statements as full expressions. In particular, this variable is no-zero if at the end of a statement @@ -1384,7 +1384,7 @@ struct lang_type We use TREE_VIA_PROTECTED and TREE_VIA_PUBLIC, but private inheritance is indicated by the absence of the other two flags, not - by TREE_VIAR_PRIVATE, which is unused. + by TREE_VIA_PRIVATE, which is unused. The TREE_CHAIN is for scratch space in search.c. */ @@ -2185,11 +2185,6 @@ extern int flag_new_for_scope; protected_access_node will appear in the DECL_ACCESS for the node. */ #define DECL_ACCESS(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.access) -/* C++: all of these are overloaded! - These apply to PARM_DECLs and VAR_DECLs. */ -#define DECL_REFERENCE_SLOT(NODE) ((tree)(NODE)->decl.arguments) -#define SET_DECL_REFERENCE_SLOT(NODE,VAL) ((NODE)->decl.arguments=VAL) - /* Accessor macros for C++ template decl nodes. */ /* The DECL_TEMPLATE_PARMS are a list. The TREE_PURPOSE of each node diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 40f691c93486..273f455f4db8 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -338,24 +338,10 @@ struct named_label_list struct named_label_list *next; }; -/* A list (chain of TREE_LIST nodes) of named label uses. - The TREE_PURPOSE field is the list of variables defined - in the label's scope defined at the point of use. - The TREE_VALUE field is the LABEL_DECL used. - The TREE_TYPE field holds `current_binding_level' at the - point of the label's use. +/* Used only for jumps to as-yet undefined labels, since jumps to + defined labels can have their validity checked by stmt.c. */ - BWAHAHAAHAHahhahahahaah. No, no, no, said the little chicken. - - Look at the pretty struct named_label_list. See the pretty struct - with the pretty named fields that describe what they do. See the - pretty lack of gratuitous casts. Notice the code got a lot cleaner. - - Used only for jumps to as-yet undefined labels, since - jumps to defined labels can have their validity checked - by stmt.c. */ - -#define named_label_uses cp_function_chain->named_label_uses +#define named_label_uses cp_function_chain->x_named_label_uses /* A list of objects which have constructors or destructors which reside in the global scope. The decl is stored in @@ -4529,7 +4515,8 @@ push_overloaded_decl (decl, flags) TREE_VALUE (*d) = new_binding; else /* Build a TREE_LIST to wrap the OVERLOAD. */ - *d = build_tree_list (NULL_TREE, new_binding); + *d = tree_cons (NULL_TREE, new_binding, + TREE_CHAIN (*d)); /* And update the CPLUS_BINDING node. */ BINDING_VALUE (IDENTIFIER_BINDING (name)) @@ -7118,19 +7105,14 @@ grok_reference_init (decl, type, init) if ((DECL_LANG_SPECIFIC (decl) == 0 || DECL_IN_AGGR_P (decl) == 0) && ! DECL_THIS_EXTERN (decl)) - { - cp_error ("`%D' declared as reference but not initialized", decl); - if (TREE_CODE (decl) == VAR_DECL) - SET_DECL_REFERENCE_SLOT (decl, error_mark_node); - } + cp_error ("`%D' declared as reference but not initialized", decl); return; } if (init == error_mark_node) return; - if (TREE_CODE (type) == REFERENCE_TYPE - && TREE_CODE (init) == CONSTRUCTOR) + if (TREE_CODE (init) == CONSTRUCTOR) { cp_error ("ANSI C++ forbids use of initializer list to initialize reference `%D'", decl); return; @@ -7154,7 +7136,7 @@ grok_reference_init (decl, type, init) LOOKUP_SPECULATIVELY|LOOKUP_NORMAL|DIRECT_BIND, decl); if (tmp == error_mark_node) - goto fail; + return; else if (tmp != NULL_TREE) { init = tmp; @@ -7163,16 +7145,13 @@ grok_reference_init (decl, type, init) else { cp_error ("cannot initialize `%T' from `%T'", type, TREE_TYPE (init)); - goto fail; + return; } /* ?? Can this be optimized in some cases to hand back the DECL_INITIAL slot?? */ if (TYPE_SIZE (TREE_TYPE (type))) - { - init = convert_from_reference (decl); - SET_DECL_REFERENCE_SLOT (decl, init); - } + init = convert_from_reference (decl); if (TREE_STATIC (decl) && ! TREE_CONSTANT (DECL_INITIAL (decl))) { @@ -7180,11 +7159,6 @@ grok_reference_init (decl, type, init) DECL_INITIAL (decl) = NULL_TREE; } return; - - fail: - if (TREE_CODE (decl) == VAR_DECL) - SET_DECL_REFERENCE_SLOT (decl, error_mark_node); - return; } /* Fill in DECL_INITIAL with some magical value to prevent expand_decl from @@ -7686,7 +7660,7 @@ maybe_inject_for_scope_var (decl) } } -/* Generate code to initialized DECL (a local variable). */ +/* Generate code to initialize DECL (a local variable). */ void initialize_local_var (decl, init, flags) @@ -13342,26 +13316,7 @@ store_parm_decls () else if (TREE_CODE (TREE_TYPE (parm)) == VOID_TYPE) cp_error ("parameter `%D' declared void", parm); else - { - /* Now fill in DECL_REFERENCE_SLOT for any of the parm decls. - A parameter is assumed not to have any side effects. - If this should change for any reason, then this - will have to wrap the bashed reference type in a save_expr. - - Also, if the parameter type is declared to be an X - and there is an X(X&) constructor, we cannot lay it - into the stack (any more), so we make this parameter - look like it is really of reference type. Functions - which pass parameters to this function will know to - create a temporary in their frame, and pass a reference - to that. */ - - if (TREE_CODE (TREE_TYPE (parm)) == REFERENCE_TYPE - && TYPE_SIZE (TREE_TYPE (TREE_TYPE (parm)))) - SET_DECL_REFERENCE_SLOT (parm, convert_from_reference (parm)); - - pushdecl (parm); - } + pushdecl (parm); if (! building_stmt_tree () && (cleanup = maybe_build_cleanup (parm), cleanup)) { @@ -13418,9 +13373,12 @@ store_parm_decls () should not be called before the parm can be used. */ if (cleanups && !building_stmt_tree ()) { - for (cleanups = nreverse (cleanups); cleanups; cleanups = TREE_CHAIN (cleanups)) + for (cleanups = nreverse (cleanups); + cleanups; + cleanups = TREE_CHAIN (cleanups)) { - if (! expand_decl_cleanup (TREE_PURPOSE (cleanups), TREE_VALUE (cleanups))) + if (! expand_decl_cleanup (TREE_PURPOSE (cleanups), + TREE_VALUE (cleanups))) cp_error ("parser lost in parsing declaration of `%D'", TREE_PURPOSE (cleanups)); } diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 67ef37776600..8eed4521334b 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -2819,7 +2819,7 @@ start_objects (method_type, initp) start_function (void_list_node, make_call_declarator (fnname, void_list_node, NULL_TREE, NULL_TREE), - NULL_TREE, SF_DEFAULT); + NULL_TREE, SF_DEFAULT | SF_EXPAND); #if defined(ASM_OUTPUT_CONSTRUCTOR) && defined(ASM_OUTPUT_DESTRUCTOR) /* It can be a static function as long as collect2 does not have @@ -3008,7 +3008,7 @@ start_static_storage_duration_function () start_function (/*specs=*/NULL_TREE, ssdf_decl, /*attrs=*/NULL_TREE, - SF_DEFAULT | SF_PRE_PARSED); + SF_PRE_PARSED | SF_EXPAND); /* Set up the scope of the outermost block in the function. */ store_parm_decls (); @@ -3640,7 +3640,7 @@ finish_file () finish_repo (); /* The entire file is now complete. If requested, dump everything - file. */ + to a file. */ if (flag_dump_translation_unit) dump_node_to_file (global_namespace, flag_dump_translation_unit); diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 0d9af2c6bd5a..46e207b1d88d 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -2732,6 +2732,7 @@ build_vec_init (decl, base, maxindex, init, from_array) tree compound_stmt; int destroy_temps; tree try_block = NULL_TREE; + tree try_body; int num_initialized_elts = 0; maxindex = cp_convert (ptrdiff_type_node, maxindex); @@ -2796,7 +2797,10 @@ build_vec_init (decl, base, maxindex, init, from_array) /* Protect the entire array initialization so that we can destroy the partially constructed array if an exception is thrown. */ if (flag_exceptions && TYPE_NEEDS_DESTRUCTOR (type)) - try_block = begin_try_block (); + { + try_block = begin_try_block (); + try_body = begin_compound_stmt (/*has_no_scope=*/1); + } if (init != NULL_TREE && TREE_CODE (init) == CONSTRUCTOR && (!decl || same_type_p (TREE_TYPE (init), TREE_TYPE (decl)))) @@ -2991,10 +2995,8 @@ build_vec_init (decl, base, maxindex, init, from_array) { tree e; - /* Because CLEANUP will not be processed until later, it must go - on the temporary obstack. */ - push_obstacks_nochange (); - resume_temporary_allocation (); + finish_compound_stmt (/*has_no_scope=*/1, try_body); + finish_cleanup_try_block (try_block); e = build_vec_delete_1 (rval, build_binary_op (MINUS_EXPR, maxindex, iterator), @@ -3002,7 +3004,6 @@ build_vec_init (decl, base, maxindex, init, from_array) /*auto_delete_vec=*/integer_zero_node, /*auto_delete=*/integer_zero_node, /*use_global_delete=*/0); - pop_obstacks (); finish_cleanup (e, try_block); } diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index cb89c8c2fa89..eaa5354b9c7c 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -45,6 +45,7 @@ static void do_pushlevel PROTO((void)); static tree do_poplevel PROTO((void)); static void finish_expr_stmt_real PROTO((tree, int)); static tree expand_cond PROTO((tree)); +static tree maybe_convert_cond PROTO((tree)); /* When parsing a template, LAST_TREE contains the last statement parsed. These are chained together through the TREE_CHAIN field, @@ -61,12 +62,19 @@ static tree expand_cond PROTO((tree)); /* Finish processing the COND, the SUBSTMT condition for STMT. */ -#define FINISH_COND(cond, stmt, substmt) \ - do { \ - if (last_tree != stmt) \ - RECHAIN_STMTS (stmt, substmt); \ - else \ - substmt = cond; \ +#define FINISH_COND(cond, stmt, substmt) \ + do { \ + if (last_tree != stmt) \ + { \ + RECHAIN_STMTS (stmt, substmt); \ + if (!processing_template_decl) \ + { \ + cond = build_tree_list (substmt, cond); \ + substmt = cond; \ + } \ + } \ + else \ + substmt = cond; \ } while (0) /* T is a statement. Add it to the statement-tree. */ @@ -84,6 +92,26 @@ add_tree (t) STMT_IS_FULL_EXPR_P (last_tree) = stmts_are_full_exprs_p; } +/* COND is the condition-expression for an if, while, etc., + statement. Convert it to a boolean value, if appropriate. */ + +static tree +maybe_convert_cond (cond) + tree cond; +{ + /* Empty conditions remain empty. */ + if (!cond) + return NULL_TREE; + + /* Wait until we instantiate templates before doing conversion. */ + if (processing_template_decl) + return cond; + + /* Do the conversion. */ + cond = convert_from_reference (cond); + return condition_conversion (cond); +} + /* Finish an expression-statement, whose EXPRESSION is as indicated. If ASSIGNED_THIS is non-zero, then this statement just assigned to the `this' pointer. */ @@ -171,12 +199,14 @@ finish_if_stmt_cond (cond, if_stmt) tree cond; tree if_stmt; { + cond = maybe_convert_cond (cond); + if (building_stmt_tree ()) FINISH_COND (cond, if_stmt, IF_COND (if_stmt)); else { emit_line_note (input_filename, lineno); - expand_start_cond (condition_conversion (cond), 0); + expand_start_cond (cond, 0); } } @@ -263,12 +293,14 @@ finish_while_stmt_cond (cond, while_stmt) tree cond; tree while_stmt; { + cond = maybe_convert_cond (cond); + if (building_stmt_tree ()) FINISH_COND (cond, while_stmt, WHILE_COND (while_stmt)); else { emit_line_note (input_filename, lineno); - expand_exit_loop_if_false (0, condition_conversion (cond)); + expand_exit_loop_if_false (0, cond); } /* If COND wasn't a declaration, clear out the @@ -337,12 +369,14 @@ finish_do_stmt (cond, do_stmt) tree cond; tree do_stmt; { + cond = maybe_convert_cond (cond); + if (building_stmt_tree ()) DO_COND (do_stmt) = cond; else { emit_line_note (input_filename, lineno); - expand_exit_loop_if_false (0, condition_conversion (cond)); + expand_exit_loop_if_false (0, cond); expand_end_loop (); } @@ -423,13 +457,15 @@ finish_for_cond (cond, for_stmt) tree cond; tree for_stmt; { + cond = maybe_convert_cond (cond); + if (building_stmt_tree ()) FINISH_COND (cond, for_stmt, FOR_COND (for_stmt)); else { emit_line_note (input_filename, lineno); if (cond) - expand_exit_loop_if_false (0, condition_conversion (cond)); + expand_exit_loop_if_false (0, cond); } /* If the cond wasn't a declaration, clear out the @@ -2038,10 +2074,10 @@ static tree expand_cond (t) tree t; { - if (t && TREE_CODE (t) == DECL_STMT) + if (t && TREE_CODE (t) == TREE_LIST) { - expand_stmt (t); - return convert_from_reference (DECL_STMT_DECL (t)); + expand_stmt (TREE_PURPOSE (t)); + return TREE_VALUE (t); } else return t;