Commit d9b2d9da by Mark Mitchell Committed by Mark Mitchell

cp-tree.def (SCOPE_STMT): Take one operand.

	* 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.

From-SVN: r30779
parent 2c0f17dc
1999-12-04 Mark Mitchell <mark@codesourcery.com> 1999-12-04 Mark Mitchell <mark@codesourcery.com>
* 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. * decl2.c (pending_statics_used): Make it a macro.
(saved_inlines_used): Likewise. (saved_inlines_used): Likewise.
(finish_static_data_member_decl): Use VARRAY_PUSH_TREE. (finish_static_data_member_decl): Use VARRAY_PUSH_TREE.
......
...@@ -254,8 +254,9 @@ DEFTREECODE (START_CATCH_STMT, "start_catch_stmt", 'e', 0) ...@@ -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_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_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 SCOPE_NULLIFIED_P holds then there turned out to be no variables in
this scope. */ this scope. The SCOPE_STMT_BLOCK is the BLOCK containing the
DEFTREECODE (SCOPE_STMT, "scope_stmt", 'e', 0) variables declared in this scope. */
DEFTREECODE (SCOPE_STMT, "scope_stmt", 'e', 1)
DEFTREECODE (CTOR_INITIALIZER, "ctor_initializer", 'e', 2) DEFTREECODE (CTOR_INITIALIZER, "ctor_initializer", 'e', 2)
DEFTREECODE (CASE_LABEL, "case_label", 'e', 2) DEFTREECODE (CASE_LABEL, "case_label", 'e', 2)
DEFTREECODE (RETURN_INIT, "return_init", 'e', 2) DEFTREECODE (RETURN_INIT, "return_init", 'e', 2)
......
...@@ -66,7 +66,7 @@ Boston, MA 02111-1307, USA. */ ...@@ -66,7 +66,7 @@ Boston, MA 02111-1307, USA. */
(TREE_REFERENCE_EXPR) (in NON_LVALUE_EXPR) (commented-out). (TREE_REFERENCE_EXPR) (in NON_LVALUE_EXPR) (commented-out).
ICS_BAD_FLAG (in _CONV) ICS_BAD_FLAG (in _CONV)
FN_TRY_BLOCK_P (in TRY_BLOCK) 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. 4: BINFO_NEW_VTABLE_MARKED.
TREE_HAS_CONSTRUCTOR (in INDIRECT_REF, SAVE_EXPR, CONSTRUCTOR, TREE_HAS_CONSTRUCTOR (in INDIRECT_REF, SAVE_EXPR, CONSTRUCTOR,
or FIELD_DECL). or FIELD_DECL).
...@@ -2697,6 +2697,10 @@ extern int flag_new_for_scope; ...@@ -2697,6 +2697,10 @@ extern int flag_new_for_scope;
#define SCOPE_END_P(NODE) \ #define SCOPE_END_P(NODE) \
(!SCOPE_BEGIN_P (SCOPE_STMT_CHECK (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. */ /* Nonzero if this CTOR_STMT is for the beginning of a constructor. */
#define CTOR_BEGIN_P(NODE) \ #define CTOR_BEGIN_P(NODE) \
(TREE_LANG_FLAG_0 (CTOR_STMT_CHECK (NODE))) (TREE_LANG_FLAG_0 (CTOR_STMT_CHECK (NODE)))
...@@ -2707,6 +2711,12 @@ extern int flag_new_for_scope; ...@@ -2707,6 +2711,12 @@ extern int flag_new_for_scope;
/* Nonzero for a SCOPE_STMT if there were no variables in this scope. */ /* Nonzero for a SCOPE_STMT if there were no variables in this scope. */
#define SCOPE_NULLIFIED_P(NODE) \ #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))) (TREE_LANG_FLAG_3 (SCOPE_STMT_CHECK (NODE)))
/* Nonzero for a SCOPE_STMT if this statement is for a partial scope. /* Nonzero for a SCOPE_STMT if this statement is for a partial scope.
...@@ -3969,7 +3979,7 @@ extern void expand_body PROTO((tree)); ...@@ -3969,7 +3979,7 @@ extern void expand_body PROTO((tree));
extern void begin_stmt_tree PROTO((tree *)); extern void begin_stmt_tree PROTO((tree *));
extern void finish_stmt_tree PROTO((tree *)); extern void finish_stmt_tree PROTO((tree *));
extern void prep_stmt 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 void do_pushlevel PROTO((void));
extern tree do_poplevel PROTO((void)); extern tree do_poplevel PROTO((void));
/* Non-zero if we are presently building a statement tree, rather /* Non-zero if we are presently building a statement tree, rather
......
...@@ -1170,7 +1170,6 @@ poplevel (keep, reverse, functionbody) ...@@ -1170,7 +1170,6 @@ poplevel (keep, reverse, functionbody)
/* Output any nested inline functions within this block /* Output any nested inline functions within this block
if they weren't already output. */ if they weren't already output. */
for (decl = decls; decl; decl = TREE_CHAIN (decl)) for (decl = decls; decl; decl = TREE_CHAIN (decl))
if (TREE_CODE (decl) == FUNCTION_DECL if (TREE_CODE (decl) == FUNCTION_DECL
&& ! TREE_ASM_WRITTEN (decl) && ! TREE_ASM_WRITTEN (decl)
...@@ -1191,10 +1190,17 @@ poplevel (keep, reverse, functionbody) ...@@ -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, /* If there were any declarations or structure tags in that level,
or if this level is a function body, or if this level is a function body,
create a BLOCK to record them for the life of this function. */ create a BLOCK to record them for the life of this function. */
block = NULL_TREE; block = NULL_TREE;
block_previously_created = (current_binding_level->this_block != NULL_TREE); block_previously_created = (current_binding_level->this_block != NULL_TREE);
if (block_previously_created) if (block_previously_created)
...@@ -1227,7 +1233,6 @@ poplevel (keep, reverse, functionbody) ...@@ -1227,7 +1233,6 @@ poplevel (keep, reverse, functionbody)
} }
/* In each subblock, record that this is its superior. */ /* In each subblock, record that this is its superior. */
if (keep >= 0) if (keep >= 0)
for (link = subblocks; link; link = TREE_CHAIN (link)) for (link = subblocks; link; link = TREE_CHAIN (link))
BLOCK_SUPERCONTEXT (link) = block; BLOCK_SUPERCONTEXT (link) = block;
...@@ -1406,23 +1411,28 @@ poplevel (keep, reverse, functionbody) ...@@ -1406,23 +1411,28 @@ poplevel (keep, reverse, functionbody)
current_binding_level->blocks current_binding_level->blocks
= chainon (current_binding_level->blocks, subblocks); = chainon (current_binding_level->blocks, subblocks);
/* 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 /* Each and every BLOCK node created here in `poplevel' is important
(e.g. for proper debugging information) so if we created one (e.g. for proper debugging information) so if we created one
earlier, mark it as "used". */ earlier, mark it as "used". */
if (block) if (block)
TREE_USED (block) = 1; TREE_USED (block) = 1;
/* Take care of compiler's internal binding structures. */
if (tmp == 2)
{
tree scope_stmts;
scope_stmts
= add_scope_stmt (/*begin_p=*/0, /*partial_p=*/1);
if (block)
{
SCOPE_STMT_BLOCK (TREE_PURPOSE (scope_stmts)) = block;
SCOPE_STMT_BLOCK (TREE_VALUE (scope_stmts)) = block;
}
block = poplevel (keep, reverse, functionbody); 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; return block;
} }
...@@ -13777,7 +13787,8 @@ finish_function (lineno, flags) ...@@ -13777,7 +13787,8 @@ finish_function (lineno, flags)
--function_depth; --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; tree t;
......
...@@ -1374,9 +1374,9 @@ A scope-statement represents the beginning or end of a scope. If ...@@ -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 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 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 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 which they were encountered. If @code{SCOPE_NULLIFIED_P} or
scope, back-ends should behave as if the @code{SCOPE_STMT} were not @code{SCOPE_NO_CLEANUPS_P} holds of the scope, back-ends should behave
present at all. as if the @code{SCOPE_STMT} were not present at all.
@item START_CATCH_STMT @item START_CATCH_STMT
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include "toplev.h" #include "toplev.h"
#include "flags.h" #include "flags.h"
#include "ggc.h" #include "ggc.h"
#include "rtl.h"
/* There routines provide a modular interface to perform many parsing /* There routines provide a modular interface to perform many parsing
operations. They may therefore be used during actual parsing, or operations. They may therefore be used during actual parsing, or
...@@ -1264,38 +1265,44 @@ setup_vtbl_ptr () ...@@ -1264,38 +1265,44 @@ setup_vtbl_ptr ()
/* Add a scope-statement to the statement-tree. BEGIN_P indicates /* Add a scope-statement to the statement-tree. BEGIN_P indicates
whether this statements opens or closes a scope. PARTIAL_P is true 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 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) add_scope_stmt (begin_p, partial_p)
int begin_p; int begin_p;
int partial_p; int partial_p;
{ {
tree ss; tree ss;
tree top;
/* Build the statement. */ /* Build the statement. */
ss = build_min_nt (SCOPE_STMT); ss = build_min_nt (SCOPE_STMT, NULL_TREE);
SCOPE_BEGIN_P (ss) = begin_p; SCOPE_BEGIN_P (ss) = begin_p;
SCOPE_PARTIAL_P (ss) = partial_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. */ /* Keep the scope stack up to date. */
if (begin_p) if (begin_p)
{
current_scope_stmt_stack current_scope_stmt_stack
= tree_cons (NULL_TREE, ss, current_scope_stmt_stack); = tree_cons (ss, NULL_TREE, current_scope_stmt_stack);
top = current_scope_stmt_stack;
}
else 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 the new statement to the statement-tree. */
add_tree (ss); add_tree (ss);
return top;
} }
/* Begin a new scope. */ /* Begin a new scope. */
...@@ -1313,8 +1320,9 @@ do_pushlevel () ...@@ -1313,8 +1320,9 @@ do_pushlevel ()
pushlevel (0); pushlevel (0);
if (!building_stmt_tree () if (!building_stmt_tree ()
&& !current_function->x_whole_function_mode_p) && !current_function->x_whole_function_mode_p)
expand_start_bindings (0); my_friendly_abort (19991129);
else if (building_stmt_tree () && !processing_template_decl)
if (building_stmt_tree () && !processing_template_decl)
add_scope_stmt (/*begin_p=*/1, /*partial_p=*/0); add_scope_stmt (/*begin_p=*/1, /*partial_p=*/0);
} }
} }
...@@ -1324,28 +1332,27 @@ do_pushlevel () ...@@ -1324,28 +1332,27 @@ do_pushlevel ()
tree tree
do_poplevel () do_poplevel ()
{ {
tree t = NULL_TREE; tree block = NULL_TREE;
if (stmts_are_full_exprs_p) if (stmts_are_full_exprs_p)
{ {
if (!building_stmt_tree () tree scope_stmts;
&& !current_function->x_whole_function_mode_p) int keep = kept_level_p ();
expand_end_bindings (getdecls (), kept_level_p (), 0);
else if (building_stmt_tree () && !processing_template_decl)
{
add_scope_stmt (/*begin_p=*/0, /*partial_p=*/0);
/* When not in function-at-a-time mode, expand_end_bindings if (building_stmt_tree () && !processing_template_decl)
will warn about unused variables. But, in scope_stmts = add_scope_stmt (/*begin_p=*/0, /*partial_p=*/0);
function-at-a-time mode expand_end_bindings is not passed else
the list of variables in the current scope, and therefore scope_stmts = NULL_TREE;
no warning is emitted. So, we explicitly warn here. */
warn_about_unused_variables (getdecls ());
}
t = poplevel (kept_level_p (), 1, 0); block = poplevel (kept_level_p (), 1, 0);
if (block && !processing_template_decl)
{
SCOPE_STMT_BLOCK (TREE_PURPOSE (scope_stmts)) = block;
SCOPE_STMT_BLOCK (TREE_VALUE (scope_stmts)) = block;
} }
return t; }
return block;
} }
/* Finish a parenthesized expression EXPR. */ /* Finish a parenthesized expression EXPR. */
...@@ -2473,11 +2480,19 @@ expand_stmt (t) ...@@ -2473,11 +2480,19 @@ expand_stmt (t)
break; break;
case SCOPE_STMT: case SCOPE_STMT:
if (!SCOPE_NO_CLEANUPS_P (t))
{
if (SCOPE_BEGIN_P (t)) if (SCOPE_BEGIN_P (t))
expand_start_bindings (2 * SCOPE_NULLIFIED_P (t)); expand_start_bindings (2 * SCOPE_NULLIFIED_P (t));
else if (SCOPE_END_P (t)) else if (SCOPE_END_P (t))
expand_end_bindings (NULL_TREE, !SCOPE_NULLIFIED_P (t), expand_end_bindings (NULL_TREE, !SCOPE_NULLIFIED_P (t),
SCOPE_PARTIAL_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; break;
case RETURN_INIT: case RETURN_INIT:
......
...@@ -1821,7 +1821,7 @@ copy_tree_r (tp, walk_subtrees, data) ...@@ -1821,7 +1821,7 @@ copy_tree_r (tp, walk_subtrees, data)
/* For now, we don't update BLOCKs when we make copies. So, we /* For now, we don't update BLOCKs when we make copies. So, we
have to nullify all scope-statements. */ have to nullify all scope-statements. */
if (TREE_CODE (*tp) == SCOPE_STMT) if (TREE_CODE (*tp) == SCOPE_STMT)
SCOPE_NULLIFIED_P (*tp) = 1; SCOPE_STMT_BLOCK (*tp) = NULL_TREE;
} }
else if (code == TEMPLATE_TEMPLATE_PARM) else if (code == TEMPLATE_TEMPLATE_PARM)
/* These must be copied specially. */ /* These must be copied specially. */
......
// Build don't link:
// Origin: Mark Mitchell <mark@codesourcery.com>
// Special g++ Options: -Wunused
struct S
{
S ();
~S ();
};
void f ()
{
{
S s1;
int j; // WARNING - unused
t: // WARNING - unused
S s2;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment