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
This commit is contained in:
Mark Mitchell 1999-12-05 00:49:26 +00:00 committed by Mark Mitchell
parent 2c0f17dc4f
commit d9b2d9da75
8 changed files with 141 additions and 62 deletions

View File

@ -1,5 +1,27 @@
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.
(saved_inlines_used): Likewise.
(finish_static_data_member_decl): Use VARRAY_PUSH_TREE.

View File

@ -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)

View File

@ -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

View File

@ -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);
/* 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". */
if (block)
TREE_USED (block) = 1;
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;
/* 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);
}
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;

View File

@ -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

View File

@ -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:

View File

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

View File

@ -0,0 +1,20 @@
// 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;
}
}