C++ PATCH for explicit cleanup representation
Mark Mitchell
mark@codesourcery.com
Sat Sep 11 18:15:00 GMT 1999
This patch moves the declaration of __FUNCTION__, etc., to the
semantic analysis pass (where they belong) rather than to the RTL
generation pass. (In function-at-a-time mode, of course.) And, we
also now explicitly represent cleanups for local variables in the
statement-tree. (Eventually, all tree generation will be done in the
fisrt pass; the second pass will just go through calling expand_* to
build RTL.)
--
Mark Mitchell mark@codesourcery.com
CodeSourcery, LLC http://www.codesourcery.com
1999-09-11 Mark Mitchell <mark@codesourcery.com>
* cp-tree.def (CLEANUP_STMT): New node.
* cp-tree.h (language_function): Add name_declared.
(current_function_name_declared): New macro.
(CLEANUP_DECL): New macro.
(CLEANUP_EXPR): Likewise.
(emit_local_var): Likewise.
(finish_decl_cleanup): New function.
* cvt.c (build_up_reference): Simplify.
(ocp_convert): Remove dead code.
* decl.c (start_decl): Remove call to add_decl_stmt.
(grok_reference_init): Adjust, to handle bindings temporaries to
references. Remove dead code.
(initialize_local_var): Don't generate RTL for
declarations here, or build cleanups here. Don't fuss with
obstacks. Replace expand_start_target_temps calls with explicit
setting of stms_are_full_exprs_p.
(destroy_local_var): New function.
(emit_local_var): Likewise.
(cp_finish_decl): Use them, as appropriate.
(start_function): Announce template functions.
(store_parm_decls): Don't call declare_function_name here.
(finish_stmt): Don't start emit base-initialization code when just
building the statement-tree.
* init.c (create_temporary_var): Move add_decl_stmt call ...
(get_temp_regvar): Here.
* pt.c (tsubst_expr): Make DECL_INITIAL look like what
cp_finish_decl would expect. Don't call add_decl_stmt.
* semantics.c (begin_compound_stmt): Call declare_function_name,
if appropriate.
(finish_decl_cleanup): New function.
(expand_stmt): Use emit_local_var to output variables.
(expand_body): Set current_funtion_name_declared.
Index: cp-tree.def
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/cp-tree.def,v
retrieving revision 1.35
diff -c -p -r1.35 cp-tree.def
*** cp-tree.def 1999/09/07 16:07:19 1.35
--- cp-tree.def 1999/09/12 01:11:39
*************** DEFTREECODE (ASM_STMT, "asm_stmt", 'e',
*** 235,240 ****
--- 235,244 ----
run if an exception is thrown before the end of the enclosing
function. */
DEFTREECODE (SUBOBJECT, "subobject", 'e', 1)
+ /* A CLEANUP_STMT marks the point at which a declaration is fully
+ constructed. If, after this point, the CLEANUP_DECL goes out of
+ scope, the CLEANUP_EXPR must be run. */
+ DEFTREECODE (CLEANUP_STMT, "cleanup", 'e', 2)
DEFTREECODE (CTOR_INITIALIZER, "ctor_initializer", 'e', 2)
DEFTREECODE (CASE_LABEL, "case_label", 'e', 2)
DEFTREECODE (RETURN_INIT, "return_init", 'e', 2)
Index: cp-tree.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.302
diff -c -p -r1.302 cp-tree.h
*** cp-tree.h 1999/09/10 10:35:53 1.302
--- cp-tree.h 1999/09/12 01:11:42
*************** struct language_function
*** 636,641 ****
--- 636,642 ----
int in_function_try_handler;
int x_expanding_p;
int stmts_are_full_exprs_p;
+ int name_declared;
struct named_label_list *x_named_label_uses;
struct binding_level *bindings;
*************** struct language_function
*** 708,713 ****
--- 709,720 ----
#define current_function_parms_stored \
cp_function_chain->parms_stored
+ /* Non-zero if we have already declared __FUNCTION__ (and related
+ variables) in the current function. */
+
+ #define current_function_name_declared \
+ cp_function_chain->name_declared
+
/* Used to help generate temporary names which are unique within
a function. Reset to 0 by start_function. */
*************** extern int flag_new_for_scope;
*** 2437,2442 ****
--- 2444,2451 ----
#define DECL_STMT_DECL(NODE) TREE_OPERAND (NODE, 0)
#define STMT_EXPR_STMT(NODE) TREE_OPERAND (NODE, 0)
#define SUBOBJECT_CLEANUP(NODE) TREE_OPERAND (NODE, 0)
+ #define CLEANUP_DECL(NODE) TREE_OPERAND (NODE, 0)
+ #define CLEANUP_EXPR(NODE) TREE_OPERAND (NODE, 1)
#define LABEL_STMT_LABEL(NODE) TREE_OPERAND (NODE, 0)
/* Nonzero for an ASM_STMT if the assembly statement is volatile. */
*************** extern int wrapup_globals_for_namespace
*** 3237,3242 ****
--- 3246,3252 ----
extern tree cp_namespace_decls PROTO((tree));
extern tree create_implicit_typedef PROTO((tree, tree));
extern tree maybe_push_decl PROTO((tree));
+ extern void emit_local_var PROTO((tree));
/* in decl2.c */
extern void init_decl2 PROTO((void));
*************** extern void finish_member_declaration
*** 3651,3656 ****
--- 3661,3667 ----
extern void check_multiple_declarators PROTO((void));
extern tree finish_typeof PROTO((tree));
extern void add_decl_stmt PROTO((tree));
+ extern void finish_decl_cleanup PROTO((tree, tree));
extern void finish_named_return_value PROTO((tree, tree));
extern tree expand_stmt PROTO((tree));
extern void expand_body PROTO((tree));
Index: cvt.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/cvt.c,v
retrieving revision 1.65
diff -c -p -r1.65 cvt.c
*** cvt.c 1999/09/09 12:07:43 1.65
--- cvt.c 1999/09/12 01:11:42
*************** build_up_reference (type, arg, flags)
*** 345,352 ****
if ((flags & DIRECT_BIND) && ! real_lvalue_p (arg))
{
- tree compound_stmt;
-
/* Create a new temporary variable. */
tree targ = arg;
if (toplevel_bindings_p ())
--- 345,350 ----
*************** build_up_reference (type, arg, flags)
*** 355,379 ****
{
arg = pushdecl (build_decl (VAR_DECL, NULL_TREE, argtype));
DECL_ARTIFICIAL (arg) = 1;
- /* Generate code to initialize it. We wrap it in a
- statement-expression so that when we are building a
- statement-tree we will have a representation of this
- declaration. */
- begin_init_stmts (&stmt_expr, &compound_stmt);
}
/* Process the initializer for the declaration. */
DECL_INITIAL (arg) = targ;
cp_finish_decl (arg, targ, NULL_TREE, 0,
LOOKUP_ONLYCONVERTING|DIRECT_BIND);
-
- /* And wrap up the statement-expression, if necessary. */
- if (!toplevel_bindings_p ())
- {
- if (building_stmt_tree ())
- add_decl_stmt (arg);
- stmt_expr = finish_init_stmts (stmt_expr, compound_stmt);
- }
}
else if (!(flags & DIRECT_BIND) && ! lvalue_p (arg))
{
--- 353,364 ----
*************** ocp_convert (type, expr, convtype, flags
*** 719,744 ****
return e;
}
- #if 0
- /* This is incorrect. A truncation can't be stripped this way.
- Extensions will be stripped by the use of get_unwidened. */
- if (TREE_CODE (e) == NOP_EXPR)
- return cp_convert (type, TREE_OPERAND (e, 0));
- #endif
-
/* Just convert to the type of the member. */
if (code == OFFSET_TYPE)
{
type = TREE_TYPE (type);
code = TREE_CODE (type);
}
-
- #if 0
- if (code == REFERENCE_TYPE)
- return fold (convert_to_reference (type, e, convtype, flags, NULL_TREE));
- else if (TREE_CODE (TREE_TYPE (e)) == REFERENCE_TYPE)
- e = convert_from_reference (e);
- #endif
if (TREE_CODE (e) == OFFSET_REF)
e = resolve_offset_ref (e);
--- 704,715 ----
Index: decl.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/decl.c,v
retrieving revision 1.444
diff -c -p -r1.444 decl.c
*** decl.c 1999/09/10 10:35:53 1.444
--- decl.c 1999/09/12 01:11:51
*************** static void mark_cp_function_context PRO
*** 179,184 ****
--- 179,185 ----
static void mark_saved_scope PROTO((void *));
static void check_function_type PROTO((tree));
static void destroy_local_static PROTO((tree));
+ static void destroy_local_var PROTO((tree));
#if defined (DEBUG_CP_BINDING_LEVELS)
static void indent PROTO((void));
*************** start_decl (declarator, declspecs, initi
*** 6843,6857 ****
{
if (at_function_scope_p ())
push_permanent_obstack ();
-
tem = push_template_decl (tem);
- /* In a a local scope, add a representation of this declaration
- to the statement tree. */
if (at_function_scope_p ())
! {
! add_decl_stmt (decl);
! pop_obstacks ();
! }
}
--- 6844,6852 ----
{
if (at_function_scope_p ())
push_permanent_obstack ();
tem = push_template_decl (tem);
if (at_function_scope_p ())
! pop_obstacks ();
}
*************** grok_reference_init (decl, type, init)
*** 6987,6993 ****
/* Note: default conversion is only called in very special cases. */
init = default_conversion (init);
}
!
tmp = convert_to_reference
(type, init, CONV_IMPLICIT,
LOOKUP_SPECULATIVELY|LOOKUP_NORMAL|DIRECT_BIND, decl);
--- 6982,6995 ----
/* Note: default conversion is only called in very special cases. */
init = default_conversion (init);
}
!
! /* Convert INIT to the reference type TYPE. This may involve the
! creation of a temporary, whose lifetime must be the same as that
! of the reference. If so, a DECL_STMT for the temporary will be
! added just after the DECL_STMT for DECL. That's why we don't set
! DECL_INITIAL for local references (instead assigning to them
! explicitly); we need to allow the temporary to be initialized
! first. */
tmp = convert_to_reference
(type, init, CONV_IMPLICIT,
LOOKUP_SPECULATIVELY|LOOKUP_NORMAL|DIRECT_BIND, decl);
*************** grok_reference_init (decl, type, init)
*** 6997,7003 ****
else if (tmp != NULL_TREE)
{
init = tmp;
! DECL_INITIAL (decl) = save_expr (init);
}
else
{
--- 6999,7016 ----
else if (tmp != NULL_TREE)
{
init = tmp;
! tmp = save_expr (tmp);
! if (building_stmt_tree ())
! {
! /* Initialize the declaration. */
! tmp = build (INIT_EXPR, TREE_TYPE (decl), decl, tmp);
! /* Setting TREE_SIDE_EFFECTS prevents expand_expr from
! omitting this expression entirely. */
! TREE_SIDE_EFFECTS (tmp) = 1;
! finish_expr_stmt (tmp);
! }
! else
! DECL_INITIAL (decl) = tmp;
}
else
{
*************** grok_reference_init (decl, type, init)
*** 7005,7015 ****
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);
-
if (TREE_STATIC (decl) && ! TREE_CONSTANT (DECL_INITIAL (decl)))
{
expand_static_init (decl, DECL_INITIAL (decl));
--- 7018,7023 ----
*************** initialize_local_var (decl, init, flags)
*** 7526,7537 ****
int flags;
{
tree type;
- tree cleanup;
type = complete_type (TREE_TYPE (decl));
- cleanup = build_cleanup_on_safe_obstack (decl);
-
if (DECL_SIZE (decl) == NULL_TREE && !TREE_STATIC (decl))
{
/* If we used it already as memory, it must stay in memory. */
--- 7534,7542 ----
*************** initialize_local_var (decl, init, flags)
*** 7539,7554 ****
TREE_ADDRESSABLE (decl) = TREE_USED (decl);
}
- if (DECL_RTL (decl))
- /* Only a RESULT_DECL should have non-NULL RTL when arriving here.
- All other local variables are assigned RTL in this function. */
- my_friendly_assert (TREE_CODE (decl) == RESULT_DECL, 19990828);
- else
- /* Create RTL for this variable. */
- expand_decl (decl);
-
- expand_start_target_temps ();
-
if (DECL_SIZE (decl) && type != error_mark_node)
{
int already_used;
--- 7544,7549 ----
*************** initialize_local_var (decl, init, flags)
*** 7558,7578 ****
if (init || TYPE_NEEDS_CONSTRUCTING (type))
{
emit_line_note (DECL_SOURCE_FILE (decl),
DECL_SOURCE_LINE (decl));
! /* We call push_momentary here so that when
! finish_expr_stmt clears the momentary obstack it
! doesn't destory any momentary expressions we may
! have lying around. Although cp_finish_decl is
! usually called at the end of a declaration
! statement, it may also be called for a temporary
! object in the middle of an expression. */
! push_momentary ();
finish_expr_stmt (build_aggr_init (decl, init, flags));
! pop_momentary ();
}
- else
- expand_decl_init (decl);
/* Set this to 0 so we can tell whether an aggregate which was
initialized was ever used. Don't do this if it has a
--- 7553,7567 ----
if (init || TYPE_NEEDS_CONSTRUCTING (type))
{
+ int saved_stmts_are_full_exprs_p;
+
emit_line_note (DECL_SOURCE_FILE (decl),
DECL_SOURCE_LINE (decl));
! saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p;
! stmts_are_full_exprs_p = 1;
finish_expr_stmt (build_aggr_init (decl, init, flags));
! stmts_are_full_exprs_p = saved_stmts_are_full_exprs_p;
}
/* Set this to 0 so we can tell whether an aggregate which was
initialized was ever used. Don't do this if it has a
*************** initialize_local_var (decl, init, flags)
*** 7582,7605 ****
marked used. (see TREE_USED, above.) */
if (TYPE_NEEDS_CONSTRUCTING (type)
&& ! already_used
! && cleanup == NULL_TREE
&& DECL_NAME (decl))
TREE_USED (decl) = 0;
else if (already_used)
TREE_USED (decl) = 1;
}
! /* Cleanup any temporaries needed for the initial value. */
! expand_end_target_temps ();
/* Record the cleanup required for this declaration. */
! if (DECL_SIZE (decl)
! && type != error_mark_node
! && cleanup
! && !expand_decl_cleanup (decl, cleanup))
! cp_error ("parser lost in parsing declaration of `%D'", decl);
}
/* Finish processing of a declaration;
install its line number and initial value.
If the length of an array type is not known before,
--- 7571,7620 ----
marked used. (see TREE_USED, above.) */
if (TYPE_NEEDS_CONSTRUCTING (type)
&& ! already_used
! && !TYPE_NEEDS_DESTRUCTOR (type)
&& DECL_NAME (decl))
TREE_USED (decl) = 0;
else if (already_used)
TREE_USED (decl) = 1;
}
+ }
! /* Generate code to destroy DECL (a local variable). */
!
! void
! destroy_local_var (decl)
! tree decl;
! {
! tree cleanup = build_cleanup_on_safe_obstack (decl);
/* Record the cleanup required for this declaration. */
! if (DECL_SIZE (decl) && TREE_TYPE (decl) != error_mark_node
! && cleanup)
! finish_decl_cleanup (decl, cleanup);
}
+ /* Let the back-end know about DECL. */
+
+ void
+ emit_local_var (decl)
+ tree decl;
+ {
+ /* Create RTL for this variable. */
+ if (DECL_RTL (decl))
+ /* Only a RESULT_DECL should have non-NULL RTL when
+ arriving here. All other local variables are
+ assigned RTL in this function. */
+ my_friendly_assert (TREE_CODE (decl) == RESULT_DECL,
+ 19990828);
+ else
+ expand_decl (decl);
+
+ /* Actually do the initialization. */
+ expand_start_target_temps ();
+ expand_decl_init (decl);
+ expand_end_target_temps ();
+ }
+
/* Finish processing of a declaration;
install its line number and initial value.
If the length of an array type is not known before,
*************** cp_finish_decl (decl, init, asmspec_tree
*** 7680,7688 ****
return;
}
if (TYPE_HAS_MUTABLE_P (type))
TREE_READONLY (decl) = 0;
!
if (processing_template_decl)
{
if (init && DECL_INITIAL (decl))
--- 7695,7708 ----
return;
}
+ /* Add this declaration to the statement-tree. */
+ if (building_stmt_tree ()
+ && TREE_CODE (current_scope ()) == FUNCTION_DECL)
+ add_decl_stmt (decl);
+
if (TYPE_HAS_MUTABLE_P (type))
TREE_READONLY (decl) = 0;
!
if (processing_template_decl)
{
if (init && DECL_INITIAL (decl))
*************** cp_finish_decl (decl, init, asmspec_tree
*** 7808,7817 ****
/* Initialize the local variable. But, if we're building a
statement-tree, we'll do the initialization when we
expand the tree. */
! if (!building_stmt_tree ())
! initialize_local_var (decl, init, flags);
! else if (init || DECL_INITIAL (decl) == error_mark_node)
! DECL_INITIAL (decl) = init;
}
finish_end0:
--- 7828,7846 ----
/* Initialize the local variable. But, if we're building a
statement-tree, we'll do the initialization when we
expand the tree. */
! if (processing_template_decl)
! {
! if (init || DECL_INITIAL (decl) == error_mark_node)
! DECL_INITIAL (decl) = init;
! }
! else
! {
! if (!building_stmt_tree ())
! emit_local_var (decl);
! initialize_local_var (decl, init, flags);
! /* Clean up the variable. */
! destroy_local_var (decl);
! }
}
finish_end0:
*************** start_function (declspecs, declarator, a
*** 12900,12906 ****
get_pending_sizes ();
/* Let the user know we're compiling this function. */
! if (!building_stmt_tree ())
announce_function (decl1);
/* Record the decl so that the function name is defined.
--- 12929,12935 ----
get_pending_sizes ();
/* Let the user know we're compiling this function. */
! if (processing_template_decl || !building_stmt_tree ())
announce_function (decl1);
/* Record the decl so that the function name is defined.
*************** store_parm_decls ()
*** 13210,13218 ****
storedecls (chainon (nonparms, DECL_ARGUMENTS (fndecl)));
- /* Declare __FUNCTION__ and __PRETTY_FUNCTION__ for this function. */
- declare_function_name ();
-
/* Initialize the RTL code for the function. */
DECL_SAVED_INSNS (fndecl) = 0;
if (! building_stmt_tree ())
--- 13239,13244 ----
*************** finish_stmt ()
*** 14222,14228 ****
if (!current_function_assigns_this
&& current_function_just_assigned_this)
{
! if (DECL_CONSTRUCTOR_P (current_function_decl))
{
/* Constructors must wait until we are out of control
zones before calling base constructors. */
--- 14248,14255 ----
if (!current_function_assigns_this
&& current_function_just_assigned_this)
{
! if (DECL_CONSTRUCTOR_P (current_function_decl)
! && !building_stmt_tree ())
{
/* Constructors must wait until we are out of control
zones before calling base constructors. */
Index: init.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/init.c,v
retrieving revision 1.133
diff -c -p -r1.133 init.c
*** init.c 1999/09/10 10:19:46 1.133
--- init.c 1999/09/12 01:11:53
*************** create_temporary_var (type)
*** 2668,2676 ****
DECL_SOURCE_LINE (decl) = lineno;
DECL_IGNORED_P (decl) = 1;
- if (building_stmt_tree ())
- add_decl_stmt (decl);
-
return decl;
}
--- 2668,2673 ----
*************** get_temp_regvar (type, init)
*** 2688,2693 ****
--- 2685,2692 ----
tree decl;
decl = create_temporary_var (type);
+ if (building_stmt_tree ())
+ add_decl_stmt (decl);
DECL_REGISTER (decl) = 1;
if (!building_stmt_tree ())
DECL_RTL (decl) = assign_temp (type, 2, 0, 1);
Index: pt.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/pt.c,v
retrieving revision 1.356
diff -c -p -r1.356 pt.c
*** pt.c 1999/09/10 09:21:36 1.356
--- pt.c 1999/09/12 01:11:59
*************** tsubst_expr (t, args, complain, in_decl)
*** 7284,7290 ****
init = DECL_INITIAL (decl);
decl = tsubst (decl, args, complain, in_decl);
init = tsubst_expr (init, args, complain, in_decl);
! DECL_INITIAL (decl) = init;
/* By marking the declaration as instantiated, we avoid
trying to instantiate it. Since instantiate_decl can't
handle local variables, and since we've already done
--- 7284,7291 ----
init = DECL_INITIAL (decl);
decl = tsubst (decl, args, complain, in_decl);
init = tsubst_expr (init, args, complain, in_decl);
! if (init)
! DECL_INITIAL (decl) = error_mark_node;
/* By marking the declaration as instantiated, we avoid
trying to instantiate it. Since instantiate_decl can't
handle local variables, and since we've already done
*************** tsubst_expr (t, args, complain, in_decl)
*** 7293,7300 ****
if (TREE_CODE (decl) == VAR_DECL)
DECL_TEMPLATE_INSTANTIATED (decl) = 1;
maybe_push_decl (decl);
! cp_finish_decl (decl, DECL_INITIAL (decl), NULL_TREE, 0, 0);
! add_decl_stmt (decl);
}
resume_momentary (i);
return decl;
--- 7294,7300 ----
if (TREE_CODE (decl) == VAR_DECL)
DECL_TEMPLATE_INSTANTIATED (decl) = 1;
maybe_push_decl (decl);
! cp_finish_decl (decl, init, NULL_TREE, 0, 0);
}
resume_momentary (i);
return decl;
Index: semantics.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/semantics.c,v
retrieving revision 1.80
diff -c -p -r1.80 semantics.c
*** semantics.c 1999/09/10 10:19:47 1.80
--- semantics.c 1999/09/12 01:12:00
*************** begin_compound_stmt (has_no_scope)
*** 869,874 ****
--- 869,882 ----
to accidentally keep a block *inside* the scopeless block. */
keep_next_level (0);
+ /* If this is the outermost block of the function, declare the
+ variables __FUNCTION__, __PRETTY_FUNCTION__, and so forth. */
+ if (!current_function_name_declared && !processing_template_decl)
+ {
+ declare_function_name ();
+ current_function_name_declared = 1;
+ }
+
return r;
}
*************** finish_subobject (cleanup)
*** 1027,1032 ****
--- 1035,1053 ----
add_partial_entry (cleanup);
}
+ /* When DECL goes out of scope, make sure that CLEANUP is executed. */
+
+ void
+ finish_decl_cleanup (decl, cleanup)
+ tree decl;
+ tree cleanup;
+ {
+ if (building_stmt_tree ())
+ add_tree (build_min_nt (CLEANUP_STMT, decl, cleanup));
+ else if (DECL_SIZE (decl) && TREE_TYPE (decl) != error_mark_node)
+ expand_decl_cleanup (decl, cleanup);
+ }
+
/* Bind a name and initialization to the return value of
the current function. */
*************** expand_stmt (t)
*** 2153,2165 ****
compatibility. */
maybe_inject_for_scope_var (decl);
/* Let the back-end know about this variable. */
! initialize_local_var (decl, DECL_INITIAL (decl), 0);
}
}
resume_momentary (i);
}
break;
case FOR_STMT:
{
tree tmp;
--- 2174,2190 ----
compatibility. */
maybe_inject_for_scope_var (decl);
/* Let the back-end know about this variable. */
! emit_local_var (decl);
}
}
resume_momentary (i);
}
break;
+ case CLEANUP_STMT:
+ finish_decl_cleanup (CLEANUP_DECL (t), CLEANUP_EXPR (t));
+ break;
+
case FOR_STMT:
{
tree tmp;
*************** expand_body (fn)
*** 2337,2342 ****
--- 2362,2372 ----
start_function (NULL_TREE, fn, NULL_TREE, SF_PRE_PARSED | SF_EXPAND);
store_parm_decls ();
+
+ /* We don't need to redeclare __FUNCTION__, __PRETTY_FUNCTION__, or
+ any of the other magic variables we set up when starting a
+ function body. */
+ current_function_name_declared = 1;
/* There are a few things that we do not handle recursively. For
example, a function try-block is handled differently from an
More information about the Gcc-patches
mailing list