From 1ec2510f3f484a265b9dd889001a8d9ffe48e4e1 Mon Sep 17 00:00:00 2001 From: mmitchel Date: Sun, 5 Dec 1999 00:49:26 +0000 Subject: [PATCH] * cp-tree.def (SCOPE_STMT): Take one operand. * cp-tree.h (SCOPE_STMT_BLOCK): New macro. (SCOPE_NULLIFIED_P): Redefine. (SCOPE_NO_CLEANUPS_P): New macro. (add_scope_stmt): Change prototype. * decl.c (poplevel): Tidy. Warn about unused variables here. Record SCOPE_STMT_BLOCKs. (finish_function): Keep DECL_INITIAL for functions that might be inlined. * ir.texi: Document SCOPE_NO_CLEANUPS_P. * semantics.c: Include rtl.h. (add_scope_stmt): Return the new scope statement and, for an end-of-scope statement, its matching begin statement. Don't set SCOPE_NULLIFIED_P. (do_pushlevel): Simplify, now that we are always function-at-a-time. (do_poplevel): Likewise. Record SCOPE_STMT_BLOCKs. (expand_stmt): Don't call expand_start_bindings or expand_end_bindings for a scope with SCOPE_NO_CLEANUPS_P set. * tree.c (copy_tree_r): Clear SCOPE_STMT_BLOCK rather than setting SCOPE_NULLIFIED_P. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@30779 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/cp/ChangeLog | 22 +++++++ gcc/cp/cp-tree.def | 5 +- gcc/cp/cp-tree.h | 14 ++++- gcc/cp/decl.c | 39 +++++++----- gcc/cp/ir.texi | 6 +- gcc/cp/semantics.c | 91 ++++++++++++++++------------ gcc/cp/tree.c | 2 +- gcc/testsuite/g++.old-deja/g++.other/goto2.C | 20 ++++++ 8 files changed, 139 insertions(+), 60 deletions(-) create mode 100644 gcc/testsuite/g++.old-deja/g++.other/goto2.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index fa7e6c84bd8..d67e30d98e1 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,27 @@ 1999-12-04 Mark Mitchell + * cp-tree.def (SCOPE_STMT): Take one operand. + * cp-tree.h (SCOPE_STMT_BLOCK): New macro. + (SCOPE_NULLIFIED_P): Redefine. + (SCOPE_NO_CLEANUPS_P): New macro. + (add_scope_stmt): Change prototype. + * decl.c (poplevel): Tidy. Warn about unused variables here. + Record SCOPE_STMT_BLOCKs. + (finish_function): Keep DECL_INITIAL for functions that might be + inlined. + * ir.texi: Document SCOPE_NO_CLEANUPS_P. + * semantics.c: Include rtl.h. + (add_scope_stmt): Return the new scope statement and, for an + end-of-scope statement, its matching begin statement. Don't set + SCOPE_NULLIFIED_P. + (do_pushlevel): Simplify, now that we are always + function-at-a-time. + (do_poplevel): Likewise. Record SCOPE_STMT_BLOCKs. + (expand_stmt): Don't call expand_start_bindings or + expand_end_bindings for a scope with SCOPE_NO_CLEANUPS_P set. + * tree.c (copy_tree_r): Clear SCOPE_STMT_BLOCK rather than setting + SCOPE_NULLIFIED_P. + * decl2.c (pending_statics_used): Make it a macro. (saved_inlines_used): Likewise. (finish_static_data_member_decl): Use VARRAY_PUSH_TREE. diff --git a/gcc/cp/cp-tree.def b/gcc/cp/cp-tree.def index 6ccc8745ed9..71c1d8d1ab5 100644 --- a/gcc/cp/cp-tree.def +++ b/gcc/cp/cp-tree.def @@ -254,8 +254,9 @@ DEFTREECODE (START_CATCH_STMT, "start_catch_stmt", 'e', 0) SCOPE_BEGIN_P holds, then this is the start of a scope. If SCOPE_END_P holds, then this is the end of a scope. If SCOPE_NULLIFIED_P holds then there turned out to be no variables in - this scope. */ -DEFTREECODE (SCOPE_STMT, "scope_stmt", 'e', 0) + this scope. The SCOPE_STMT_BLOCK is the BLOCK containing the + variables declared in this scope. */ +DEFTREECODE (SCOPE_STMT, "scope_stmt", 'e', 1) DEFTREECODE (CTOR_INITIALIZER, "ctor_initializer", 'e', 2) DEFTREECODE (CASE_LABEL, "case_label", 'e', 2) DEFTREECODE (RETURN_INIT, "return_init", 'e', 2) diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index f2dc09ebc7e..d31a6ce8963 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -66,7 +66,7 @@ Boston, MA 02111-1307, USA. */ (TREE_REFERENCE_EXPR) (in NON_LVALUE_EXPR) (commented-out). ICS_BAD_FLAG (in _CONV) FN_TRY_BLOCK_P (in TRY_BLOCK) - SCOPE_NULLIFIED_P (in SCOPE_STMT) + SCOPE_NO_CLEANUPS_P (in SCOPE_STMT) 4: BINFO_NEW_VTABLE_MARKED. TREE_HAS_CONSTRUCTOR (in INDIRECT_REF, SAVE_EXPR, CONSTRUCTOR, or FIELD_DECL). @@ -2697,6 +2697,10 @@ extern int flag_new_for_scope; #define SCOPE_END_P(NODE) \ (!SCOPE_BEGIN_P (SCOPE_STMT_CHECK (NODE))) +/* The BLOCK containing the declarations contained in this scope. */ +#define SCOPE_STMT_BLOCK(NODE) \ + (TREE_OPERAND (SCOPE_STMT_CHECK (NODE), 0)) + /* Nonzero if this CTOR_STMT is for the beginning of a constructor. */ #define CTOR_BEGIN_P(NODE) \ (TREE_LANG_FLAG_0 (CTOR_STMT_CHECK (NODE))) @@ -2707,6 +2711,12 @@ extern int flag_new_for_scope; /* Nonzero for a SCOPE_STMT if there were no variables in this scope. */ #define SCOPE_NULLIFIED_P(NODE) \ + (SCOPE_STMT_BLOCK ((NODE)) == NULL_TREE) + +/* Nonzero for a SCOPE_STMT which represents a lexical scope, but + which should be treated as non-existant from the point of view of + running cleanup actions. */ +#define SCOPE_NO_CLEANUPS_P(NODE) \ (TREE_LANG_FLAG_3 (SCOPE_STMT_CHECK (NODE))) /* Nonzero for a SCOPE_STMT if this statement is for a partial scope. @@ -3969,7 +3979,7 @@ extern void expand_body PROTO((tree)); extern void begin_stmt_tree PROTO((tree *)); extern void finish_stmt_tree PROTO((tree *)); extern void prep_stmt PROTO((tree)); -extern void add_scope_stmt PROTO((int, int)); +extern tree add_scope_stmt PROTO((int, int)); extern void do_pushlevel PROTO((void)); extern tree do_poplevel PROTO((void)); /* Non-zero if we are presently building a statement tree, rather diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index deea199ddbd..20915577f89 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -1170,7 +1170,6 @@ poplevel (keep, reverse, functionbody) /* Output any nested inline functions within this block if they weren't already output. */ - for (decl = decls; decl; decl = TREE_CHAIN (decl)) if (TREE_CODE (decl) == FUNCTION_DECL && ! TREE_ASM_WRITTEN (decl) @@ -1191,10 +1190,17 @@ poplevel (keep, reverse, functionbody) } } + /* When not in function-at-a-time mode, expand_end_bindings will + warn about unused variables. But, in function-at-a-time mode + expand_end_bindings is not passed the list of variables in the + current scope, and therefore no warning is emitted. So, we + explicitly warn here. */ + if (!processing_template_decl) + warn_about_unused_variables (getdecls ()); + /* If there were any declarations or structure tags in that level, or if this level is a function body, create a BLOCK to record them for the life of this function. */ - block = NULL_TREE; block_previously_created = (current_binding_level->this_block != NULL_TREE); if (block_previously_created) @@ -1227,7 +1233,6 @@ poplevel (keep, reverse, functionbody) } /* In each subblock, record that this is its superior. */ - if (keep >= 0) for (link = subblocks; link; link = TREE_CHAIN (link)) BLOCK_SUPERCONTEXT (link) = block; @@ -1406,23 +1411,28 @@ poplevel (keep, reverse, functionbody) current_binding_level->blocks = chainon (current_binding_level->blocks, subblocks); + /* Each and every BLOCK node created here in `poplevel' is important + (e.g. for proper debugging information) so if we created one + earlier, mark it as "used". */ + if (block) + TREE_USED (block) = 1; + /* Take care of compiler's internal binding structures. */ if (tmp == 2) { - add_scope_stmt (/*begin_p=*/0, /*partial_p=*/1); - /* Each and every BLOCK node created here in `poplevel' is important - (e.g. for proper debugging information) so if we created one - earlier, mark it as "used". */ + tree scope_stmts; + + scope_stmts + = add_scope_stmt (/*begin_p=*/0, /*partial_p=*/1); if (block) - TREE_USED (block) = 1; + { + SCOPE_STMT_BLOCK (TREE_PURPOSE (scope_stmts)) = block; + SCOPE_STMT_BLOCK (TREE_VALUE (scope_stmts)) = block; + } + block = poplevel (keep, reverse, functionbody); } - /* Each and every BLOCK node created here in `poplevel' is important - (e.g. for proper debugging information) so if we created one - earlier, mark it as "used". */ - if (block) - TREE_USED (block) = 1; return block; } @@ -13777,7 +13787,8 @@ finish_function (lineno, flags) --function_depth; - if (!DECL_SAVED_INSNS (fndecl) && !DECL_SAVED_FUNCTION_DATA (fndecl)) + if (!DECL_SAVED_INSNS (fndecl) && !DECL_SAVED_FUNCTION_DATA (fndecl) + && !(flag_inline_trees && DECL_INLINE (fndecl))) { tree t; diff --git a/gcc/cp/ir.texi b/gcc/cp/ir.texi index b2e6a497270..cb6e1385d1f 100644 --- a/gcc/cp/ir.texi +++ b/gcc/cp/ir.texi @@ -1374,9 +1374,9 @@ A scope-statement represents the beginning or end of a scope. If scope; if @code{SCOPE_END_P} holds this statement represents the end of a scope. On exit from a scope, all cleanups from @code{CLEANUP_STMT}s occurring in the scope must be run, in reverse order to the order in -which they were encountered. If @code{SCOPE_NULLIFIED_P} holds of the -scope, back-ends should behave as if the @code{SCOPE_STMT} were not -present at all. +which they were encountered. If @code{SCOPE_NULLIFIED_P} or +@code{SCOPE_NO_CLEANUPS_P} holds of the scope, back-ends should behave +as if the @code{SCOPE_STMT} were not present at all. @item START_CATCH_STMT diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index fa69540ca3a..028279f8209 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -33,6 +33,7 @@ #include "toplev.h" #include "flags.h" #include "ggc.h" +#include "rtl.h" /* There routines provide a modular interface to perform many parsing operations. They may therefore be used during actual parsing, or @@ -1264,38 +1265,44 @@ setup_vtbl_ptr () /* Add a scope-statement to the statement-tree. BEGIN_P indicates whether this statements opens or closes a scope. PARTIAL_P is true for a partial scope, i.e, the scope that begins after a label when - an object that needs a cleanup is created. */ + an object that needs a cleanup is created. If BEGIN_P is nonzero, + returns a new TREE_LIST representing the top of the SCOPE_STMT + stack. The TREE_PURPOSE is the new SCOPE_STMT. If BEGIN_P is + zero, returns a TREE_LIST whose TREE_VALUE is the new SCOPE_STMT, + and whose TREE_PURPOSE is the matching SCOPE_STMT iwth + SCOPE_BEGIN_P set. */ -void +tree add_scope_stmt (begin_p, partial_p) int begin_p; int partial_p; { tree ss; + tree top; /* Build the statement. */ - ss = build_min_nt (SCOPE_STMT); + ss = build_min_nt (SCOPE_STMT, NULL_TREE); SCOPE_BEGIN_P (ss) = begin_p; SCOPE_PARTIAL_P (ss) = partial_p; - /* If we're finishing a scope, figure out whether the scope was - really necessary. */ - if (!begin_p) - { - SCOPE_NULLIFIED_P (ss) = !kept_level_p (); - SCOPE_NULLIFIED_P (TREE_VALUE (current_scope_stmt_stack)) - = SCOPE_NULLIFIED_P (ss); - } - /* Keep the scope stack up to date. */ if (begin_p) - current_scope_stmt_stack - = tree_cons (NULL_TREE, ss, current_scope_stmt_stack); + { + current_scope_stmt_stack + = tree_cons (ss, NULL_TREE, current_scope_stmt_stack); + top = current_scope_stmt_stack; + } else - current_scope_stmt_stack = TREE_CHAIN (current_scope_stmt_stack); + { + top = current_scope_stmt_stack; + TREE_VALUE (top) = ss; + current_scope_stmt_stack = TREE_CHAIN (top); + } /* Add the new statement to the statement-tree. */ add_tree (ss); + + return top; } /* Begin a new scope. */ @@ -1313,8 +1320,9 @@ do_pushlevel () pushlevel (0); if (!building_stmt_tree () && !current_function->x_whole_function_mode_p) - expand_start_bindings (0); - else if (building_stmt_tree () && !processing_template_decl) + my_friendly_abort (19991129); + + if (building_stmt_tree () && !processing_template_decl) add_scope_stmt (/*begin_p=*/1, /*partial_p=*/0); } } @@ -1324,28 +1332,27 @@ do_pushlevel () tree do_poplevel () { - tree t = NULL_TREE; + tree block = NULL_TREE; if (stmts_are_full_exprs_p) { - if (!building_stmt_tree () - && !current_function->x_whole_function_mode_p) - expand_end_bindings (getdecls (), kept_level_p (), 0); - else if (building_stmt_tree () && !processing_template_decl) + tree scope_stmts; + int keep = kept_level_p (); + + if (building_stmt_tree () && !processing_template_decl) + scope_stmts = add_scope_stmt (/*begin_p=*/0, /*partial_p=*/0); + else + scope_stmts = NULL_TREE; + + block = poplevel (kept_level_p (), 1, 0); + if (block && !processing_template_decl) { - add_scope_stmt (/*begin_p=*/0, /*partial_p=*/0); - - /* When not in function-at-a-time mode, expand_end_bindings - will warn about unused variables. But, in - function-at-a-time mode expand_end_bindings is not passed - the list of variables in the current scope, and therefore - no warning is emitted. So, we explicitly warn here. */ - warn_about_unused_variables (getdecls ()); + SCOPE_STMT_BLOCK (TREE_PURPOSE (scope_stmts)) = block; + SCOPE_STMT_BLOCK (TREE_VALUE (scope_stmts)) = block; } - - t = poplevel (kept_level_p (), 1, 0); } - return t; + + return block; } /* Finish a parenthesized expression EXPR. */ @@ -2473,11 +2480,19 @@ expand_stmt (t) break; case SCOPE_STMT: - if (SCOPE_BEGIN_P (t)) - expand_start_bindings (2 * SCOPE_NULLIFIED_P (t)); - else if (SCOPE_END_P (t)) - expand_end_bindings (NULL_TREE, !SCOPE_NULLIFIED_P (t), - SCOPE_PARTIAL_P (t)); + if (!SCOPE_NO_CLEANUPS_P (t)) + { + if (SCOPE_BEGIN_P (t)) + expand_start_bindings (2 * SCOPE_NULLIFIED_P (t)); + else if (SCOPE_END_P (t)) + expand_end_bindings (NULL_TREE, !SCOPE_NULLIFIED_P (t), + SCOPE_PARTIAL_P (t)); + } + else if (!SCOPE_NULLIFIED_P (t)) + emit_note (NULL, + (SCOPE_BEGIN_P (t) + ? NOTE_INSN_BLOCK_BEG + : NOTE_INSN_BLOCK_END)); break; case RETURN_INIT: diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 9796c8f4a16..da15a2867db 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -1821,7 +1821,7 @@ copy_tree_r (tp, walk_subtrees, data) /* For now, we don't update BLOCKs when we make copies. So, we have to nullify all scope-statements. */ if (TREE_CODE (*tp) == SCOPE_STMT) - SCOPE_NULLIFIED_P (*tp) = 1; + SCOPE_STMT_BLOCK (*tp) = NULL_TREE; } else if (code == TEMPLATE_TEMPLATE_PARM) /* These must be copied specially. */ diff --git a/gcc/testsuite/g++.old-deja/g++.other/goto2.C b/gcc/testsuite/g++.old-deja/g++.other/goto2.C new file mode 100644 index 00000000000..2b95273cd8b --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.other/goto2.C @@ -0,0 +1,20 @@ +// Build don't link: +// Origin: Mark Mitchell +// Special g++ Options: -Wunused + +struct S +{ + S (); + ~S (); +}; + +void f () +{ + { + S s1; + int j; // WARNING - unused + + t: // WARNING - unused + S s2; + } +} -- 2.11.0