c-common.h (genrtl_clear_out_block): Remove.
* c-common.h (genrtl_clear_out_block): Remove. * c-semantics.c (genrtl_clear_out_block): Remove. (genrtl_while_stmt): Don't call it. (genrtl_for_stmt): Likewise. * cp-tree.h (struct saved_scope): Remove x_function_parms. (current_function_parms): Don't define. (struct cp_language_function): Remove parms_stored. (current_function_just_assigned_this): Don't define. (current_function_parms_stored): Likewise. (static_ctors): Declare. (static_dtors): Likewise. (SF_EXPAND): Don't define. (expand_start_early_try_stmts): Remove declaration. (store_parm_decls): Likewise. * decl.c (static_ctors): Don't declare. (static_dtors): Likewise. (struct binding_level): Remove this_block. (poplevel): Remove dead code. (set_block): Likewise. (mark_binding_level): Don't mark this_block. (mark_saved_scope): Don't mark x_function_parms. (init_decl_processing): Don't add current_function_parms as a GC root. (check_function_type): Change prototype. (start_function): Remove RTL-generation code. (expand_start_early_try_stmts): Remove. (store_parm_decls): Give it internal linkage. Remove RTL-generation code. (finish_function): Remove RTL-generation code. * decl2.c (static_ctors): Fix formatting. (static_dtors): Likewise. * method.c (use_thunk): Don't call store_parm_decls. (synthesize_method): Likewise. * optimize.c (maybe_clone_body): Likewise. * parse.y (fn.def2): Likewise. (.set_base_init): Likewise. (nodecls): Likewise. * pt.c (instantiate_decl): Likewise. * rtti.c (synthesize_tinfo_fn): Likewise. * semantics.c (genrtl_try_block): Simplify. (expand_body): Use genrtl_start_function and genrtl_finish_function. (genrtl_start_function): New function. (genrtl_finish_function): Likewise. From-SVN: r36350
This commit is contained in:
parent
484d9e58a4
commit
f444e36b2d
12 changed files with 412 additions and 429 deletions
|
@ -1,3 +1,10 @@
|
|||
2000-09-11 Mark Mitchell <mark@codesourcery.com>
|
||||
|
||||
* c-common.h (genrtl_clear_out_block): Remove.
|
||||
* c-semantics.c (genrtl_clear_out_block): Remove.
|
||||
(genrtl_while_stmt): Don't call it.
|
||||
(genrtl_for_stmt): Likewise.
|
||||
|
||||
2000-09-11 Zack Weinberg <zack@wolery.cumb.org>
|
||||
|
||||
* cppfiles.c: Move all default-#defines to top of file.
|
||||
|
|
|
@ -570,7 +570,6 @@ enum c_tree_code {
|
|||
|
||||
extern void add_c_tree_codes PARAMS ((void));
|
||||
extern void genrtl_do_pushlevel PARAMS ((void));
|
||||
extern void genrtl_clear_out_block PARAMS ((void));
|
||||
extern void genrtl_goto_stmt PARAMS ((tree));
|
||||
extern void genrtl_expr_stmt PARAMS ((tree));
|
||||
extern void genrtl_decl_stmt PARAMS ((tree));
|
||||
|
|
|
@ -1,3 +1,46 @@
|
|||
2000-09-11 Mark Mitchell <mark@codesourcery.com>
|
||||
|
||||
* cp-tree.h (struct saved_scope): Remove x_function_parms.
|
||||
(current_function_parms): Don't define.
|
||||
(struct cp_language_function): Remove parms_stored.
|
||||
(current_function_just_assigned_this): Don't define.
|
||||
(current_function_parms_stored): Likewise.
|
||||
(static_ctors): Declare.
|
||||
(static_dtors): Likewise.
|
||||
(SF_EXPAND): Don't define.
|
||||
(expand_start_early_try_stmts): Remove declaration.
|
||||
(store_parm_decls): Likewise.
|
||||
* decl.c (static_ctors): Don't declare.
|
||||
(static_dtors): Likewise.
|
||||
(struct binding_level): Remove this_block.
|
||||
(poplevel): Remove dead code.
|
||||
(set_block): Likewise.
|
||||
(mark_binding_level): Don't mark this_block.
|
||||
(mark_saved_scope): Don't mark x_function_parms.
|
||||
(init_decl_processing): Don't add current_function_parms as a GC
|
||||
root.
|
||||
(check_function_type): Change prototype.
|
||||
(start_function): Remove RTL-generation code.
|
||||
(expand_start_early_try_stmts): Remove.
|
||||
(store_parm_decls): Give it internal linkage. Remove
|
||||
RTL-generation code.
|
||||
(finish_function): Remove RTL-generation code.
|
||||
* decl2.c (static_ctors): Fix formatting.
|
||||
(static_dtors): Likewise.
|
||||
* method.c (use_thunk): Don't call store_parm_decls.
|
||||
(synthesize_method): Likewise.
|
||||
* optimize.c (maybe_clone_body): Likewise.
|
||||
* parse.y (fn.def2): Likewise.
|
||||
(.set_base_init): Likewise.
|
||||
(nodecls): Likewise.
|
||||
* pt.c (instantiate_decl): Likewise.
|
||||
* rtti.c (synthesize_tinfo_fn): Likewise.
|
||||
* semantics.c (genrtl_try_block): Simplify.
|
||||
(expand_body): Use genrtl_start_function and
|
||||
genrtl_finish_function.
|
||||
(genrtl_start_function): New function.
|
||||
(genrtl_finish_function): Likewise.
|
||||
|
||||
2000-09-11 Nathan Sidwell <nathan@codesourcery.com>
|
||||
|
||||
* error.c (cp_tree_printer, case 'P'): Append break.
|
||||
|
|
|
@ -792,7 +792,6 @@ struct saved_scope {
|
|||
varray_type lang_base;
|
||||
tree *lang_stack;
|
||||
tree lang_name;
|
||||
tree x_function_parms;
|
||||
tree template_parms;
|
||||
tree x_previous_class_type;
|
||||
tree x_previous_class_values;
|
||||
|
@ -841,7 +840,6 @@ struct saved_scope {
|
|||
/* Parsing a function declarator leaves a list of parameter names
|
||||
or a chain or parameter decls here. */
|
||||
|
||||
#define current_function_parms scope_chain->x_function_parms
|
||||
#define current_template_parms scope_chain->template_parms
|
||||
|
||||
#define processing_template_decl scope_chain->x_processing_template_decl
|
||||
|
@ -889,7 +887,6 @@ struct cp_language_function
|
|||
|
||||
int returns_value;
|
||||
int returns_null;
|
||||
int parms_stored;
|
||||
int in_function_try_handler;
|
||||
int x_expanding_p;
|
||||
int name_declared;
|
||||
|
@ -956,12 +953,6 @@ struct cp_language_function
|
|||
|
||||
#define current_function_returns_null cp_function_chain->returns_null
|
||||
|
||||
#define current_function_just_assigned_this \
|
||||
cp_function_chain->just_assigned_this
|
||||
|
||||
#define current_function_parms_stored \
|
||||
cp_function_chain->parms_stored
|
||||
|
||||
/* Nonzero if we have already generated code to initialize virtual
|
||||
function tables in this function. */
|
||||
|
||||
|
@ -3509,6 +3500,11 @@ extern int flag_inline_trees;
|
|||
|
||||
extern int at_eof;
|
||||
|
||||
/* Functions called along with real static constructors and destructors. */
|
||||
|
||||
extern tree static_ctors;
|
||||
extern tree static_dtors;
|
||||
|
||||
enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, OP_FLAG, TYPENAME_FLAG };
|
||||
|
||||
/* Some macros for char-based bitfields. */
|
||||
|
@ -3637,8 +3633,6 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, OP_FLAG, TYPENAME_FLAG };
|
|||
already been parsed. */
|
||||
#define SF_INCLASS_INLINE 2 /* The function is an inline, defined
|
||||
in the class body. */
|
||||
#define SF_EXPAND 4 /* Generate RTL for this function. */
|
||||
|
||||
|
||||
/* Returns nonzero iff TYPE1 and TYPE2 are the same type, or if TYPE2
|
||||
is derived from TYPE1, or if TYPE2 is a pointer (reference) to a
|
||||
|
@ -3905,8 +3899,6 @@ extern tree start_enum PARAMS ((tree));
|
|||
extern tree finish_enum PARAMS ((tree));
|
||||
extern void build_enumerator PARAMS ((tree, tree, tree));
|
||||
extern int start_function PARAMS ((tree, tree, tree, int));
|
||||
extern void expand_start_early_try_stmts PARAMS ((void));
|
||||
extern void store_parm_decls PARAMS ((void));
|
||||
extern tree finish_function PARAMS ((int));
|
||||
extern tree start_method PARAMS ((tree, tree, tree));
|
||||
extern tree finish_method PARAMS ((tree));
|
||||
|
|
454
gcc/cp/decl.c
454
gcc/cp/decl.c
|
@ -46,8 +46,6 @@ Boston, MA 02111-1307, USA. */
|
|||
|
||||
extern int current_class_depth;
|
||||
|
||||
extern tree static_ctors, static_dtors;
|
||||
|
||||
extern tree global_namespace;
|
||||
|
||||
extern int (*valid_lang_attribute) PARAMS ((tree, tree, tree, tree));
|
||||
|
@ -163,7 +161,7 @@ static void mark_saved_scope PARAMS ((void *));
|
|||
static void mark_lang_function PARAMS ((struct cp_language_function *));
|
||||
static void mark_stmt_tree PARAMS ((stmt_tree));
|
||||
static void save_function_data PARAMS ((tree));
|
||||
static void check_function_type PARAMS ((tree));
|
||||
static void check_function_type PARAMS ((tree, tree));
|
||||
static void destroy_local_var PARAMS ((tree));
|
||||
static void finish_constructor_body PARAMS ((void));
|
||||
static void finish_destructor_body PARAMS ((void));
|
||||
|
@ -179,6 +177,7 @@ static tree check_special_function_return_type
|
|||
static tree push_cp_library_fn PARAMS ((enum tree_code, tree));
|
||||
static tree build_cp_library_fn PARAMS ((tree, enum tree_code, tree));
|
||||
static int case_compare PARAMS ((splay_tree_key, splay_tree_key));
|
||||
static void store_parm_decls PARAMS ((tree));
|
||||
|
||||
#if defined (DEBUG_CP_BINDING_LEVELS)
|
||||
static void indent PARAMS ((void));
|
||||
|
@ -447,10 +446,6 @@ struct binding_level
|
|||
that were entered and exited one level down. */
|
||||
tree blocks;
|
||||
|
||||
/* The BLOCK node for this level, if one has been preallocated.
|
||||
If 0, the BLOCK is allocated (if needed) when the level is popped. */
|
||||
tree this_block;
|
||||
|
||||
/* The _TYPE node for this level, if parm_flag == 2. */
|
||||
tree this_class;
|
||||
|
||||
|
@ -1288,7 +1283,6 @@ poplevel (keep, reverse, functionbody)
|
|||
tree subblocks;
|
||||
tree block = NULL_TREE;
|
||||
tree decl;
|
||||
int block_previously_created;
|
||||
int leaving_for_scope;
|
||||
|
||||
if (cfun && !doing_semantic_analysis_p ())
|
||||
|
@ -1396,34 +1390,12 @@ poplevel (keep, reverse, functionbody)
|
|||
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)
|
||||
block = current_binding_level->this_block;
|
||||
else if (keep == 1 || functionbody)
|
||||
if (keep == 1 || functionbody)
|
||||
block = make_node (BLOCK);
|
||||
if (block != NULL_TREE)
|
||||
{
|
||||
if (block_previously_created)
|
||||
{
|
||||
if (decls || tags || subblocks)
|
||||
{
|
||||
if (BLOCK_VARS (block))
|
||||
warning ("internal compiler error: debugging info corrupted");
|
||||
|
||||
BLOCK_VARS (block) = decls;
|
||||
|
||||
/* We can have previous subblocks and new subblocks when
|
||||
doing fixup_gotos with complex cleanups. We chain the new
|
||||
subblocks onto the end of any pre-existing subblocks. */
|
||||
BLOCK_SUBBLOCKS (block) = chainon (BLOCK_SUBBLOCKS (block),
|
||||
subblocks);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
BLOCK_VARS (block) = decls;
|
||||
BLOCK_SUBBLOCKS (block) = subblocks;
|
||||
}
|
||||
BLOCK_VARS (block) = decls;
|
||||
BLOCK_SUBBLOCKS (block) = subblocks;
|
||||
}
|
||||
|
||||
/* In each subblock, record that this is its superior. */
|
||||
|
@ -1574,11 +1546,9 @@ poplevel (keep, reverse, functionbody)
|
|||
if (functionbody)
|
||||
DECL_INITIAL (current_function_decl) = block;
|
||||
else if (block)
|
||||
{
|
||||
if (!block_previously_created)
|
||||
current_binding_level->blocks
|
||||
= chainon (current_binding_level->blocks, block);
|
||||
}
|
||||
current_binding_level->blocks
|
||||
= chainon (current_binding_level->blocks, block);
|
||||
|
||||
/* If we did not make a block for the level just exited,
|
||||
any blocks made for inner levels
|
||||
(since they cannot be recorded as subblocks in that level)
|
||||
|
@ -1655,9 +1625,11 @@ insert_block (block)
|
|||
|
||||
void
|
||||
set_block (block)
|
||||
register tree block;
|
||||
tree block ATTRIBUTE_UNUSED;
|
||||
{
|
||||
current_binding_level->this_block = block;
|
||||
/* The RTL expansion machinery requires us to provide this callback,
|
||||
but it is not applicable in function-at-a-time mode. */
|
||||
my_friendly_assert (cfun && !doing_semantic_analysis_p (), 20000911);
|
||||
}
|
||||
|
||||
/* Do a pushlevel for class declarations. */
|
||||
|
@ -2011,7 +1983,6 @@ mark_binding_level (arg)
|
|||
ggc_mark_tree (lvl->type_shadowed);
|
||||
ggc_mark_tree (lvl->shadowed_labels);
|
||||
ggc_mark_tree (lvl->blocks);
|
||||
ggc_mark_tree (lvl->this_block);
|
||||
ggc_mark_tree (lvl->this_class);
|
||||
ggc_mark_tree (lvl->incomplete);
|
||||
ggc_mark_tree (lvl->dead_vars_from_for);
|
||||
|
@ -2469,7 +2440,6 @@ mark_saved_scope (arg)
|
|||
if (t->lang_base)
|
||||
ggc_mark_tree_varray (t->lang_base);
|
||||
ggc_mark_tree (t->lang_name);
|
||||
ggc_mark_tree (t->x_function_parms);
|
||||
ggc_mark_tree (t->template_parms);
|
||||
ggc_mark_tree (t->x_previous_class_type);
|
||||
ggc_mark_tree (t->x_previous_class_values);
|
||||
|
@ -6868,7 +6838,6 @@ init_decl_processing ()
|
|||
|
||||
ggc_add_tree_root (&last_function_parm_tags, 1);
|
||||
ggc_add_tree_root (¤t_function_return_value, 1);
|
||||
ggc_add_tree_root (¤t_function_parms, 1);
|
||||
ggc_add_tree_root (¤t_function_parm_tags, 1);
|
||||
ggc_add_tree_root (&last_function_parms, 1);
|
||||
ggc_add_tree_root (&error_mark_list, 1);
|
||||
|
@ -13593,8 +13562,9 @@ build_enumerator (name, value, enumtype)
|
|||
/* We're defining DECL. Make sure that it's type is OK. */
|
||||
|
||||
static void
|
||||
check_function_type (decl)
|
||||
check_function_type (decl, current_function_parms)
|
||||
tree decl;
|
||||
tree current_function_parms;
|
||||
{
|
||||
tree fntype = TREE_TYPE (decl);
|
||||
tree return_type = complete_type (TREE_TYPE (fntype));
|
||||
|
@ -13636,9 +13606,7 @@ check_function_type (decl)
|
|||
FLAGS is a bitwise or of SF_PRE_PARSED (indicating that the
|
||||
DECLARATOR is really the DECL for the function we are about to
|
||||
process and that DECLSPECS should be ignored), SF_INCLASS_INLINE
|
||||
indicating that the function is an inline defined in-class, and
|
||||
SF_EXPAND indicating that we should generate RTL for this
|
||||
function.
|
||||
indicating that the function is an inline defined in-class.
|
||||
|
||||
This function creates a binding context for the function body
|
||||
as well as setting up the FUNCTION_DECL in current_function_decl.
|
||||
|
@ -13665,6 +13633,7 @@ start_function (declspecs, declarator, attrs, flags)
|
|||
extern int used_extern_spec;
|
||||
int doing_friend = 0;
|
||||
struct binding_level *bl;
|
||||
tree current_function_parms;
|
||||
|
||||
/* Sanity check. */
|
||||
my_friendly_assert (TREE_CODE (TREE_VALUE (void_list_node)) == VOID_TYPE, 160);
|
||||
|
@ -13812,7 +13781,7 @@ start_function (declspecs, declarator, attrs, flags)
|
|||
you declare a function, these types can be incomplete, but they
|
||||
must be complete when you define the function. */
|
||||
if (! processing_template_decl)
|
||||
check_function_type (decl1);
|
||||
check_function_type (decl1, current_function_parms);
|
||||
|
||||
/* Build the return declaration for the function. */
|
||||
restype = TREE_TYPE (fntype);
|
||||
|
@ -13837,7 +13806,6 @@ start_function (declspecs, declarator, attrs, flags)
|
|||
bl = current_binding_level;
|
||||
init_function_start (decl1, input_filename, lineno);
|
||||
current_binding_level = bl;
|
||||
expanding_p = (flags & SF_EXPAND) != 0;
|
||||
|
||||
/* Even though we're inside a function body, we still don't want to
|
||||
call expand_expr to calculate the size of a variable-sized array.
|
||||
|
@ -13846,9 +13814,8 @@ start_function (declspecs, declarator, attrs, flags)
|
|||
immediate_size_expand = 0;
|
||||
cfun->x_dont_save_pending_sizes_p = 1;
|
||||
|
||||
/* If we're building a statement-tree, start the tree now. */
|
||||
if (processing_template_decl || !expanding_p)
|
||||
begin_stmt_tree (&DECL_SAVED_TREE (decl1));
|
||||
/* Start the statement-tree, start the tree now. */
|
||||
begin_stmt_tree (&DECL_SAVED_TREE (decl1));
|
||||
|
||||
/* Let the user know we're compiling this function. */
|
||||
announce_function (decl1);
|
||||
|
@ -13877,29 +13844,11 @@ start_function (declspecs, declarator, attrs, flags)
|
|||
current_function_decl = decl1;
|
||||
cfun->decl = decl1;
|
||||
|
||||
/* Initialize the per-function data. */
|
||||
if (!DECL_PENDING_INLINE_P (decl1) && DECL_SAVED_FUNCTION_DATA (decl1))
|
||||
{
|
||||
/* If we already parsed this function, and we're just expanding it
|
||||
now, restore saved state. */
|
||||
struct binding_level *bl = current_binding_level;
|
||||
*cp_function_chain = *DECL_SAVED_FUNCTION_DATA (decl1);
|
||||
current_binding_level = bl;
|
||||
my_friendly_assert ((DECL_PENDING_INLINE_P (decl1)
|
||||
|| !DECL_SAVED_FUNCTION_DATA (decl1)),
|
||||
20000911);
|
||||
|
||||
/* This function is being processed in whole-function mode; we
|
||||
already did semantic analysis. */
|
||||
cfun->x_whole_function_mode_p = 1;
|
||||
|
||||
/* If we decided that we didn't want to inline this function,
|
||||
make sure the back-end knows that. */
|
||||
if (!current_function_cannot_inline)
|
||||
current_function_cannot_inline = cp_function_chain->cannot_inline;
|
||||
|
||||
/* We don't need the saved data anymore. */
|
||||
free (DECL_SAVED_FUNCTION_DATA (decl1));
|
||||
DECL_SAVED_FUNCTION_DATA (decl1) = NULL;
|
||||
}
|
||||
else if (ctype && !doing_friend && !DECL_STATIC_FUNCTION_P (decl1))
|
||||
if (ctype && !doing_friend && !DECL_STATIC_FUNCTION_P (decl1))
|
||||
{
|
||||
/* We know that this was set up by `grokclassfn'. We do not
|
||||
wait until `store_parm_decls', since evil parse errors may
|
||||
|
@ -13987,18 +13936,12 @@ start_function (declspecs, declarator, attrs, flags)
|
|||
DECL_INTERFACE_KNOWN (decl1) = 1;
|
||||
}
|
||||
|
||||
if (doing_semantic_analysis_p ())
|
||||
{
|
||||
pushlevel (0);
|
||||
current_binding_level->parm_flag = 1;
|
||||
}
|
||||
pushlevel (0);
|
||||
current_binding_level->parm_flag = 1;
|
||||
|
||||
if (attrs)
|
||||
cplus_decl_attributes (decl1, NULL_TREE, attrs);
|
||||
|
||||
if (!building_stmt_tree ())
|
||||
GNU_xref_function (decl1, current_function_parms);
|
||||
|
||||
/* We need to do this even if we aren't expanding yet so that
|
||||
assemble_external works. */
|
||||
make_function_rtl (decl1);
|
||||
|
@ -14038,25 +13981,20 @@ start_function (declspecs, declarator, attrs, flags)
|
|||
DECL_CONTEXT (ctor_label) = current_function_decl;
|
||||
}
|
||||
|
||||
store_parm_decls (current_function_parms);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Called after store_parm_decls for a function-try-block. */
|
||||
|
||||
void
|
||||
expand_start_early_try_stmts ()
|
||||
{
|
||||
expand_start_try_stmts ();
|
||||
}
|
||||
|
||||
/* Store the parameter declarations into the current function declaration.
|
||||
This is called after parsing the parameter declarations, before
|
||||
digesting the body of the function.
|
||||
|
||||
Also install to binding contour return value identifier, if any. */
|
||||
|
||||
void
|
||||
store_parm_decls ()
|
||||
static void
|
||||
store_parm_decls (current_function_parms)
|
||||
tree current_function_parms;
|
||||
{
|
||||
register tree fndecl = current_function_decl;
|
||||
register tree parm;
|
||||
|
@ -14071,10 +14009,6 @@ store_parm_decls ()
|
|||
then CONST_DECLs for foo and bar are put here. */
|
||||
tree nonparms = NULL_TREE;
|
||||
|
||||
/* Create a binding level for the parms. */
|
||||
if (!building_stmt_tree ())
|
||||
expand_start_bindings (2);
|
||||
|
||||
if (current_function_parms)
|
||||
{
|
||||
/* This case is when the function was defined with an ANSI prototype.
|
||||
|
@ -14085,45 +14019,34 @@ store_parm_decls ()
|
|||
tree specparms = current_function_parms;
|
||||
tree next;
|
||||
|
||||
if (doing_semantic_analysis_p ())
|
||||
{
|
||||
/* Must clear this because it might contain TYPE_DECLs declared
|
||||
/* Must clear this because it might contain TYPE_DECLs declared
|
||||
at class level. */
|
||||
storedecls (NULL_TREE);
|
||||
storedecls (NULL_TREE);
|
||||
|
||||
/* If we're doing semantic analysis, then we'll call pushdecl
|
||||
/* If we're doing semantic analysis, then we'll call pushdecl
|
||||
for each of these. We must do them in reverse order so that
|
||||
they end in the correct forward order. */
|
||||
specparms = nreverse (specparms);
|
||||
}
|
||||
specparms = nreverse (specparms);
|
||||
|
||||
for (parm = specparms; parm; parm = next)
|
||||
{
|
||||
next = TREE_CHAIN (parm);
|
||||
if (TREE_CODE (parm) == PARM_DECL)
|
||||
{
|
||||
tree type = TREE_TYPE (parm);
|
||||
tree cleanup;
|
||||
|
||||
if (doing_semantic_analysis_p ())
|
||||
{
|
||||
tree cleanup;
|
||||
if (DECL_NAME (parm) == NULL_TREE
|
||||
|| TREE_CODE (parm) != VOID_TYPE)
|
||||
pushdecl (parm);
|
||||
else
|
||||
cp_error ("parameter `%D' declared void", parm);
|
||||
|
||||
if (DECL_NAME (parm) == NULL_TREE
|
||||
|| TREE_CODE (parm) != VOID_TYPE)
|
||||
pushdecl (parm);
|
||||
else
|
||||
cp_error ("parameter `%D' declared void", parm);
|
||||
cleanup = (processing_template_decl
|
||||
? NULL_TREE
|
||||
: maybe_build_cleanup (parm));
|
||||
|
||||
cleanup = (processing_template_decl
|
||||
? NULL_TREE
|
||||
: maybe_build_cleanup (parm));
|
||||
|
||||
if (cleanup)
|
||||
cleanups = tree_cons (parm, cleanup, cleanups);
|
||||
}
|
||||
else if (type != error_mark_node
|
||||
&& TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
|
||||
parms_have_cleanups = 1;
|
||||
if (cleanup)
|
||||
cleanups = tree_cons (parm, cleanup, cleanups);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -14134,14 +14057,11 @@ store_parm_decls ()
|
|||
}
|
||||
}
|
||||
|
||||
if (doing_semantic_analysis_p ())
|
||||
{
|
||||
/* Get the decls in their original chain order
|
||||
and record in the function. This is all and only the
|
||||
PARM_DECLs that were pushed into scope by the loop above. */
|
||||
DECL_ARGUMENTS (fndecl) = getdecls ();
|
||||
storetags (chainon (parmtags, gettags ()));
|
||||
}
|
||||
/* Get the decls in their original chain order and record in the
|
||||
function. This is all and only the PARM_DECLs that were
|
||||
pushed into scope by the loop above. */
|
||||
DECL_ARGUMENTS (fndecl) = getdecls ();
|
||||
storetags (chainon (parmtags, gettags ()));
|
||||
}
|
||||
else
|
||||
DECL_ARGUMENTS (fndecl) = NULL_TREE;
|
||||
|
@ -14150,20 +14070,7 @@ store_parm_decls ()
|
|||
as the decl-chain of the current lexical scope.
|
||||
Put the enumerators in as well, at the front so that
|
||||
DECL_ARGUMENTS is not modified. */
|
||||
if (doing_semantic_analysis_p ())
|
||||
storedecls (chainon (nonparms, DECL_ARGUMENTS (fndecl)));
|
||||
|
||||
/* Initialize the RTL code for the function. */
|
||||
DECL_SAVED_INSNS (fndecl) = 0;
|
||||
if (! building_stmt_tree ())
|
||||
expand_function_start (fndecl, parms_have_cleanups);
|
||||
|
||||
current_function_parms_stored = 1;
|
||||
|
||||
/* If this function is `main', emit a call to `__main'
|
||||
to run global initializers, etc. */
|
||||
if (DECL_MAIN_P (fndecl) && !building_stmt_tree ())
|
||||
expand_main_function ();
|
||||
storedecls (chainon (nonparms, DECL_ARGUMENTS (fndecl)));
|
||||
|
||||
/* Now that we have initialized the parms, we can start their
|
||||
cleanups. We cannot do this before, since expand_decl_cleanup
|
||||
|
@ -14176,19 +14083,13 @@ store_parm_decls ()
|
|||
}
|
||||
|
||||
/* Create a binding contour which can be used to catch
|
||||
cleanup-generated temporaries. Also, if the return value needs or
|
||||
has initialization, deal with that now. */
|
||||
cleanup-generated temporaries. */
|
||||
if (parms_have_cleanups)
|
||||
{
|
||||
pushlevel (0);
|
||||
if (!building_stmt_tree ())
|
||||
expand_start_bindings (2);
|
||||
}
|
||||
pushlevel (0);
|
||||
|
||||
/* Do the starting of the exception specifications, if we have any. */
|
||||
if (flag_exceptions && !processing_template_decl
|
||||
&& flag_enforce_eh_specs
|
||||
&& building_stmt_tree ()
|
||||
&& TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl)))
|
||||
current_eh_spec_try_block = expand_start_eh_spec ();
|
||||
}
|
||||
|
@ -14384,13 +14285,9 @@ finish_function (flags)
|
|||
{
|
||||
register tree fndecl = current_function_decl;
|
||||
tree fntype, ctype = NULL_TREE;
|
||||
/* Label to use if this function is supposed to return a value. */
|
||||
tree no_return_label = NULL_TREE;
|
||||
int call_poplevel = (flags & 1) != 0;
|
||||
int inclass_inline = (flags & 2) != 0;
|
||||
int expand_p;
|
||||
int nested;
|
||||
int current_line = lineno;
|
||||
|
||||
/* When we get some parse errors, we can end up without a
|
||||
current_function_decl, so cope. */
|
||||
|
@ -14404,18 +14301,11 @@ finish_function (flags)
|
|||
This caused &foo to be of type ptr-to-const-function
|
||||
which then got a warning when stored in a ptr-to-function variable. */
|
||||
|
||||
/* This happens on strange parse errors. */
|
||||
if (! current_function_parms_stored)
|
||||
{
|
||||
call_poplevel = 0;
|
||||
store_parm_decls ();
|
||||
}
|
||||
my_friendly_assert (building_stmt_tree (), 20000911);
|
||||
|
||||
/* For a cloned function, we've already got all the code we need;
|
||||
there's no need to add any extra bits. */
|
||||
if (building_stmt_tree () && DECL_CLONED_FUNCTION_P (fndecl))
|
||||
;
|
||||
else if (building_stmt_tree ())
|
||||
if (!DECL_CLONED_FUNCTION_P (fndecl))
|
||||
{
|
||||
if (DECL_CONSTRUCTOR_P (fndecl))
|
||||
{
|
||||
|
@ -14443,132 +14333,16 @@ finish_function (flags)
|
|||
(TREE_TYPE (current_function_decl)),
|
||||
current_eh_spec_try_block);
|
||||
}
|
||||
else
|
||||
{
|
||||
#if 0
|
||||
if (write_symbols != NO_DEBUG /*&& TREE_CODE (fntype) != METHOD_TYPE*/)
|
||||
{
|
||||
/* Keep this code around in case we later want to control debug info
|
||||
based on whether a type is "used". (jason 1999-11-11) */
|
||||
|
||||
tree ttype = target_type (fntype);
|
||||
tree parmdecl;
|
||||
|
||||
if (IS_AGGR_TYPE (ttype))
|
||||
/* Let debugger know it should output info for this type. */
|
||||
note_debug_info_needed (ttype);
|
||||
|
||||
for (parmdecl = DECL_ARGUMENTS (fndecl); parmdecl; parmdecl = TREE_CHAIN (parmdecl))
|
||||
{
|
||||
ttype = target_type (TREE_TYPE (parmdecl));
|
||||
if (IS_AGGR_TYPE (ttype))
|
||||
/* Let debugger know it should output info for this type. */
|
||||
note_debug_info_needed (ttype);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Clean house because we will need to reorder insns here. */
|
||||
do_pending_stack_adjust ();
|
||||
|
||||
if (dtor_label)
|
||||
;
|
||||
else if (DECL_CONSTRUCTOR_P (fndecl))
|
||||
{
|
||||
if (call_poplevel)
|
||||
do_poplevel ();
|
||||
}
|
||||
else if (return_label != NULL_RTX
|
||||
&& flag_this_is_variable <= 0
|
||||
&& current_function_return_value == NULL_TREE
|
||||
&& ! DECL_NAME (DECL_RESULT (current_function_decl)))
|
||||
no_return_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
|
||||
|
||||
if (flag_exceptions)
|
||||
expand_exception_blocks ();
|
||||
|
||||
/* If this function is supposed to return a value, ensure that
|
||||
we do not fall into the cleanups by mistake. The end of our
|
||||
function will look like this:
|
||||
|
||||
user code (may have return stmt somewhere)
|
||||
goto no_return_label
|
||||
cleanup_label:
|
||||
cleanups
|
||||
goto return_label
|
||||
no_return_label:
|
||||
NOTE_INSN_FUNCTION_END
|
||||
return_label:
|
||||
things for return
|
||||
|
||||
If the user omits a return stmt in the USER CODE section, we
|
||||
will have a control path which reaches NOTE_INSN_FUNCTION_END.
|
||||
Otherwise, we won't. */
|
||||
if (no_return_label)
|
||||
{
|
||||
DECL_CONTEXT (no_return_label) = fndecl;
|
||||
DECL_INITIAL (no_return_label) = error_mark_node;
|
||||
DECL_SOURCE_FILE (no_return_label) = input_filename;
|
||||
DECL_SOURCE_LINE (no_return_label) = current_line;
|
||||
expand_goto (no_return_label);
|
||||
}
|
||||
|
||||
if (cleanup_label)
|
||||
{
|
||||
/* Remove the binding contour which is used
|
||||
to catch cleanup-generated temporaries. */
|
||||
expand_end_bindings (0, 0, 0);
|
||||
poplevel (0, 0, 0);
|
||||
|
||||
/* Emit label at beginning of cleanup code for parameters. */
|
||||
emit_label (cleanup_label);
|
||||
}
|
||||
|
||||
/* Get return value into register if that's where it's supposed
|
||||
to be. */
|
||||
if (original_result_rtx)
|
||||
fixup_result_decl (DECL_RESULT (fndecl), original_result_rtx);
|
||||
|
||||
/* Finish building code that will trigger warnings if users forget
|
||||
to make their functions return values. */
|
||||
if (no_return_label || cleanup_label)
|
||||
emit_jump (return_label);
|
||||
if (no_return_label)
|
||||
{
|
||||
/* We don't need to call `expand_*_return' here because we
|
||||
don't need any cleanups here--this path of code is only
|
||||
for error checking purposes. */
|
||||
expand_label (no_return_label);
|
||||
}
|
||||
|
||||
/* We hard-wired immediate_size_expand to zero in
|
||||
start_function. Expand_function_end will decrement this
|
||||
variable. So, we set the variable to one here, so that after
|
||||
the decrement it will remain zero. */
|
||||
immediate_size_expand = 1;
|
||||
|
||||
/* Generate rtl for function exit. */
|
||||
expand_function_end (input_filename, current_line, 1);
|
||||
}
|
||||
|
||||
/* We have to save this value here in case
|
||||
maybe_end_member_template_processing decides to pop all the
|
||||
template parameters. */
|
||||
expand_p = !building_stmt_tree ();
|
||||
|
||||
/* If we're saving up tree structure, tie off the function now. */
|
||||
if (!expand_p)
|
||||
finish_stmt_tree (&DECL_SAVED_TREE (fndecl));
|
||||
finish_stmt_tree (&DECL_SAVED_TREE (fndecl));
|
||||
|
||||
/* This must come after expand_function_end because cleanups might
|
||||
have declarations (from inline functions) that need to go into
|
||||
this function's blocks. */
|
||||
if (doing_semantic_analysis_p ())
|
||||
{
|
||||
if (current_binding_level->parm_flag != 1)
|
||||
my_friendly_abort (122);
|
||||
poplevel (1, 0, 1);
|
||||
}
|
||||
if (current_binding_level->parm_flag != 1)
|
||||
my_friendly_abort (122);
|
||||
poplevel (1, 0, 1);
|
||||
|
||||
/* Remember that we were in class scope. */
|
||||
if (current_class_name)
|
||||
|
@ -14582,7 +14356,7 @@ finish_function (flags)
|
|||
BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
|
||||
|
||||
/* Save away current state, if appropriate. */
|
||||
if (!expanding_p && !processing_template_decl)
|
||||
if (!processing_template_decl)
|
||||
save_function_data (fndecl);
|
||||
|
||||
/* If this function calls `setjmp' it cannot be inlined. When
|
||||
|
@ -14594,96 +14368,15 @@ finish_function (flags)
|
|||
this function to modify local variables in `c', but their
|
||||
addresses may have been stored somewhere accessible to this
|
||||
function.) */
|
||||
if (!expanding_p && !processing_template_decl && calls_setjmp_p (fndecl))
|
||||
if (!processing_template_decl && calls_setjmp_p (fndecl))
|
||||
DECL_UNINLINABLE (fndecl) = 1;
|
||||
|
||||
if (expand_p)
|
||||
{
|
||||
int returns_null;
|
||||
int returns_value;
|
||||
|
||||
/* So we can tell if jump_optimize sets it to 1. */
|
||||
can_reach_end = 0;
|
||||
|
||||
/* Before we call rest_of_compilation (which will pop the
|
||||
CURRENT_FUNCTION), we must save these values. */
|
||||
returns_null = current_function_returns_null;
|
||||
returns_value = current_function_returns_value;
|
||||
|
||||
/* If this is a nested function (like a template instantiation
|
||||
that we're compiling in the midst of compiling something
|
||||
else), push a new GC context. That will keep local variables
|
||||
on the stack from being collected while we're doing the
|
||||
compilation of this function. */
|
||||
if (function_depth > 1)
|
||||
ggc_push_context ();
|
||||
|
||||
/* Run the optimizers and output the assembler code for this
|
||||
function. */
|
||||
rest_of_compilation (fndecl);
|
||||
|
||||
/* Undo the call to ggc_push_context above. */
|
||||
if (function_depth > 1)
|
||||
ggc_pop_context ();
|
||||
|
||||
if (DECL_SAVED_INSNS (fndecl) && ! TREE_ASM_WRITTEN (fndecl))
|
||||
{
|
||||
/* Set DECL_EXTERNAL so that assemble_external will be called as
|
||||
necessary. We'll clear it again in finish_file. */
|
||||
if (! DECL_EXTERNAL (fndecl))
|
||||
DECL_NOT_REALLY_EXTERN (fndecl) = 1;
|
||||
DECL_EXTERNAL (fndecl) = 1;
|
||||
defer_fn (fndecl);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Keep this code around in case we later want to control debug info
|
||||
based on whether a type is "used". (jason 1999-11-11) */
|
||||
|
||||
if (ctype && TREE_ASM_WRITTEN (fndecl))
|
||||
note_debug_info_needed (ctype);
|
||||
#endif
|
||||
|
||||
/* If this function is marked with the constructor attribute,
|
||||
add it to the list of functions to be called along with
|
||||
constructors from static duration objects. */
|
||||
if (DECL_STATIC_CONSTRUCTOR (fndecl))
|
||||
static_ctors = tree_cons (NULL_TREE, fndecl, static_ctors);
|
||||
|
||||
/* If this function is marked with the destructor attribute,
|
||||
add it to the list of functions to be called along with
|
||||
destructors from static duration objects. */
|
||||
if (DECL_STATIC_DESTRUCTOR (fndecl))
|
||||
static_dtors = tree_cons (NULL_TREE, fndecl, static_dtors);
|
||||
|
||||
if (DECL_NAME (DECL_RESULT (fndecl)))
|
||||
returns_value |= can_reach_end;
|
||||
else
|
||||
returns_null |= can_reach_end;
|
||||
|
||||
if (TREE_THIS_VOLATILE (fndecl) && returns_null)
|
||||
warning ("`noreturn' function does return");
|
||||
else if (returns_null
|
||||
&& TREE_CODE (TREE_TYPE (fntype)) != VOID_TYPE)
|
||||
{
|
||||
/* Always complain if there's just no return statement. */
|
||||
if (!returns_value)
|
||||
warning ("no return statement in function returning non-void");
|
||||
else if (warn_return_type || pedantic)
|
||||
/* If this function returns non-void and control can drop through,
|
||||
complain. */
|
||||
warning ("control reaches end of non-void function");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Clear out memory we no longer need. */
|
||||
free_after_parsing (cfun);
|
||||
/* Since we never call rest_of_compilation, we never clear
|
||||
CFUN. Do so explicitly. */
|
||||
free_after_compilation (cfun);
|
||||
cfun = NULL;
|
||||
}
|
||||
/* Clear out memory we no longer need. */
|
||||
free_after_parsing (cfun);
|
||||
/* Since we never call rest_of_compilation, we never clear
|
||||
CFUN. Do so explicitly. */
|
||||
free_after_compilation (cfun);
|
||||
cfun = NULL;
|
||||
|
||||
/* If this is a in-class inline definition, we may have to pop the
|
||||
bindings for the template parameters that we added in
|
||||
|
@ -14698,19 +14391,6 @@ finish_function (flags)
|
|||
|
||||
--function_depth;
|
||||
|
||||
if (!DECL_SAVED_INSNS (fndecl) && !DECL_SAVED_FUNCTION_DATA (fndecl)
|
||||
&& !(flag_inline_trees && DECL_INLINE (fndecl)))
|
||||
{
|
||||
tree t;
|
||||
|
||||
/* Stop pointing to the local nodes about to be freed. */
|
||||
/* But DECL_INITIAL must remain nonzero so we know this
|
||||
was an actual function definition. */
|
||||
DECL_INITIAL (fndecl) = error_mark_node;
|
||||
for (t = DECL_ARGUMENTS (fndecl); t; t = TREE_CHAIN (t))
|
||||
DECL_RTL (t) = DECL_INCOMING_RTL (t) = NULL_RTX;
|
||||
}
|
||||
|
||||
/* Clean up. */
|
||||
if (! nested)
|
||||
{
|
||||
|
|
|
@ -128,7 +128,8 @@ int at_eof;
|
|||
|
||||
/* Functions called along with real static constructors and destructors. */
|
||||
|
||||
tree static_ctors, static_dtors;
|
||||
tree static_ctors;
|
||||
tree static_dtors;
|
||||
|
||||
/* The :: namespace. */
|
||||
|
||||
|
|
|
@ -2258,7 +2258,6 @@ use_thunk (thunk_fndecl, emit_p)
|
|||
DECL_RESULT (thunk_fndecl) = NULL_TREE;
|
||||
|
||||
start_function (NULL_TREE, thunk_fndecl, NULL_TREE, SF_PRE_PARSED);
|
||||
store_parm_decls ();
|
||||
|
||||
/* Adjust the this pointer by the constant. */
|
||||
t = ssize_int (delta);
|
||||
|
@ -2530,7 +2529,6 @@ synthesize_method (fndecl)
|
|||
|
||||
interface_unknown = 1;
|
||||
start_function (NULL_TREE, fndecl, NULL_TREE, SF_DEFAULT | SF_PRE_PARSED);
|
||||
store_parm_decls ();
|
||||
clear_last_expr ();
|
||||
|
||||
if (DECL_OVERLOADED_OPERATOR_P (fndecl) == NOP_EXPR)
|
||||
|
|
|
@ -932,7 +932,6 @@ maybe_clone_body (fn)
|
|||
/* Start processing the function. */
|
||||
push_to_top_level ();
|
||||
start_function (NULL_TREE, clone, NULL_TREE, SF_PRE_PARSED);
|
||||
store_parm_decls ();
|
||||
|
||||
/* Just clone the body, as if we were making an inline call.
|
||||
But, remap the parameters in the callee to the parameters of
|
||||
|
|
|
@ -835,8 +835,6 @@ fn.def2:
|
|||
return_id:
|
||||
RETURN_KEYWORD IDENTIFIER
|
||||
{
|
||||
if (! current_function_parms_stored)
|
||||
store_parm_decls ();
|
||||
$$ = $2;
|
||||
}
|
||||
;
|
||||
|
@ -863,9 +861,6 @@ base_init:
|
|||
.set_base_init:
|
||||
/* empty */
|
||||
{
|
||||
if (! current_function_parms_stored)
|
||||
store_parm_decls ();
|
||||
|
||||
if (DECL_CONSTRUCTOR_P (current_function_decl))
|
||||
/* Make a contour for the initializer list. */
|
||||
do_pushlevel ();
|
||||
|
@ -1723,8 +1718,6 @@ string:
|
|||
nodecls:
|
||||
/* empty */
|
||||
{
|
||||
if (! current_function_parms_stored)
|
||||
store_parm_decls ();
|
||||
setup_vtbl_ptr (NULL_TREE, NULL_TREE);
|
||||
}
|
||||
;
|
||||
|
|
|
@ -9686,7 +9686,6 @@ instantiate_decl (d, defer_ok)
|
|||
|
||||
/* Set up context. */
|
||||
start_function (NULL_TREE, d, NULL_TREE, SF_PRE_PARSED);
|
||||
store_parm_decls ();
|
||||
|
||||
/* We already set up __FUNCTION__, etc., so we don't want to do
|
||||
it again now. */
|
||||
|
|
|
@ -1195,7 +1195,6 @@ synthesize_tinfo_fn (fndecl)
|
|||
start_function (NULL_TREE, fndecl, NULL_TREE,
|
||||
SF_DEFAULT | SF_PRE_PARSED);
|
||||
DECL_DEFER_OUTPUT (fndecl) = 1;
|
||||
store_parm_decls ();
|
||||
clear_last_expr ();
|
||||
|
||||
/* Begin the body of the function. */
|
||||
|
|
|
@ -57,6 +57,8 @@ static void genrtl_ctor_stmt PARAMS ((tree));
|
|||
static void genrtl_subobject PARAMS ((tree));
|
||||
static void genrtl_named_return_value PARAMS ((void));
|
||||
static void cp_expand_stmt PARAMS ((tree));
|
||||
static void genrtl_start_function PARAMS ((tree));
|
||||
static void genrtl_finish_function PARAMS ((tree));
|
||||
|
||||
/* Finish processing the COND, the SUBSTMT condition for STMT. */
|
||||
|
||||
|
@ -596,17 +598,9 @@ genrtl_try_block (t)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (FN_TRY_BLOCK_P (t))
|
||||
{
|
||||
if (! current_function_parms_stored)
|
||||
store_parm_decls ();
|
||||
expand_start_early_try_stmts ();
|
||||
}
|
||||
else
|
||||
{
|
||||
emit_line_note (input_filename, lineno);
|
||||
expand_start_try_stmts ();
|
||||
}
|
||||
if (!FN_TRY_BLOCK_P (t))
|
||||
emit_line_note (input_filename, lineno);
|
||||
expand_start_try_stmts ();
|
||||
|
||||
expand_stmt (TRY_STMTS (t));
|
||||
|
||||
|
@ -2387,7 +2381,6 @@ emit_associated_thunks (fn)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/* Generate RTL for FN. */
|
||||
|
||||
void
|
||||
|
@ -2484,8 +2477,7 @@ expand_body (fn)
|
|||
lineno = DECL_SOURCE_LINE (fn);
|
||||
input_filename = DECL_SOURCE_FILE (fn);
|
||||
|
||||
start_function (NULL_TREE, fn, NULL_TREE, SF_PRE_PARSED | SF_EXPAND);
|
||||
store_parm_decls ();
|
||||
genrtl_start_function (fn);
|
||||
current_function_is_thunk = DECL_THUNK_P (fn);
|
||||
|
||||
/* We don't need to redeclare __FUNCTION__, __PRETTY_FUNCTION__, or
|
||||
|
@ -2505,7 +2497,7 @@ expand_body (fn)
|
|||
lineno = STMT_LINENO (DECL_SAVED_TREE (fn));
|
||||
|
||||
/* Generate code for the function. */
|
||||
finish_function (0);
|
||||
genrtl_finish_function (fn);
|
||||
|
||||
/* If possible, obliterate the body of the function so that it can
|
||||
be garbage collected. */
|
||||
|
@ -2528,6 +2520,287 @@ expand_body (fn)
|
|||
timevar_pop (TV_EXPAND);
|
||||
}
|
||||
|
||||
/* Start generating the RTL for FN. */
|
||||
|
||||
static void
|
||||
genrtl_start_function (fn)
|
||||
tree fn;
|
||||
{
|
||||
tree parm;
|
||||
|
||||
/* Tell everybody what function we're processing. */
|
||||
current_function_decl = fn;
|
||||
/* Get the RTL machinery going for this function. */
|
||||
init_function_start (fn, DECL_SOURCE_FILE (fn), DECL_SOURCE_LINE (fn));
|
||||
/* Let everybody know that we're expanding this function, not doing
|
||||
semantic analysis. */
|
||||
expanding_p = 1;
|
||||
|
||||
/* Even though we're inside a function body, we still don't want to
|
||||
call expand_expr to calculate the size of a variable-sized array.
|
||||
We haven't necessarily assigned RTL to all variables yet, so it's
|
||||
not safe to try to expand expressions involving them. */
|
||||
immediate_size_expand = 0;
|
||||
cfun->x_dont_save_pending_sizes_p = 1;
|
||||
|
||||
/* Let the user know we're compiling this function. */
|
||||
announce_function (fn);
|
||||
|
||||
/* Initialize the per-function data. */
|
||||
my_friendly_assert (!DECL_PENDING_INLINE_P (fn), 20000911);
|
||||
if (DECL_SAVED_FUNCTION_DATA (fn))
|
||||
{
|
||||
/* If we already parsed this function, and we're just expanding it
|
||||
now, restore saved state. */
|
||||
*cp_function_chain = *DECL_SAVED_FUNCTION_DATA (fn);
|
||||
|
||||
/* This function is being processed in whole-function mode; we
|
||||
already did semantic analysis. */
|
||||
cfun->x_whole_function_mode_p = 1;
|
||||
|
||||
/* If we decided that we didn't want to inline this function,
|
||||
make sure the back-end knows that. */
|
||||
if (!current_function_cannot_inline)
|
||||
current_function_cannot_inline = cp_function_chain->cannot_inline;
|
||||
|
||||
/* We don't need the saved data anymore. */
|
||||
free (DECL_SAVED_FUNCTION_DATA (fn));
|
||||
DECL_SAVED_FUNCTION_DATA (fn) = NULL;
|
||||
}
|
||||
|
||||
/* Tell the cross-reference machinery that we're defining this
|
||||
function. */
|
||||
GNU_xref_function (fn, DECL_ARGUMENTS (fn));
|
||||
|
||||
/* Keep track of how many functions we're presently expanding. */
|
||||
++function_depth;
|
||||
|
||||
/* Create a binding level for the parameters. */
|
||||
expand_start_bindings (2);
|
||||
/* Clear out any previously saved instructions for this function, in
|
||||
case it was defined more than once. */
|
||||
DECL_SAVED_INSNS (fn) = NULL;
|
||||
/* Go through the PARM_DECLs for this function to see if any need
|
||||
cleanups. */
|
||||
for (parm = DECL_ARGUMENTS (fn); parm; parm = TREE_CHAIN (parm))
|
||||
if (TREE_TYPE (parm) != error_mark_node
|
||||
&& TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (parm)))
|
||||
{
|
||||
expand_function_start (fn, /*parms_have_cleanups=*/1);
|
||||
break;
|
||||
}
|
||||
if (!parm)
|
||||
expand_function_start (fn, /*parms_have_cleanups=*/0);
|
||||
/* If this function is `main'. */
|
||||
if (DECL_MAIN_P (fn))
|
||||
expand_main_function ();
|
||||
/* Create a binding contour which can be used to catch
|
||||
cleanup-generated temporaries. */
|
||||
expand_start_bindings (2);
|
||||
}
|
||||
|
||||
/* Finish generating the RTL for FN. */
|
||||
|
||||
static void
|
||||
genrtl_finish_function (fn)
|
||||
tree fn;
|
||||
{
|
||||
int returns_null;
|
||||
int returns_value;
|
||||
tree no_return_label = NULL_TREE;
|
||||
|
||||
#if 0
|
||||
if (write_symbols != NO_DEBUG)
|
||||
{
|
||||
/* Keep this code around in case we later want to control debug info
|
||||
based on whether a type is "used". (jason 1999-11-11) */
|
||||
|
||||
tree ttype = target_type (fntype);
|
||||
tree parmdecl;
|
||||
|
||||
if (IS_AGGR_TYPE (ttype))
|
||||
/* Let debugger know it should output info for this type. */
|
||||
note_debug_info_needed (ttype);
|
||||
|
||||
for (parmdecl = DECL_ARGUMENTS (fndecl); parmdecl; parmdecl = TREE_CHAIN (parmdecl))
|
||||
{
|
||||
ttype = target_type (TREE_TYPE (parmdecl));
|
||||
if (IS_AGGR_TYPE (ttype))
|
||||
/* Let debugger know it should output info for this type. */
|
||||
note_debug_info_needed (ttype);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Clean house because we will need to reorder insns here. */
|
||||
do_pending_stack_adjust ();
|
||||
|
||||
if (!dtor_label && !DECL_CONSTRUCTOR_P (fn)
|
||||
&& return_label != NULL_RTX
|
||||
&& current_function_return_value == NULL_TREE
|
||||
&& ! DECL_NAME (DECL_RESULT (current_function_decl)))
|
||||
no_return_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
|
||||
|
||||
if (flag_exceptions)
|
||||
expand_exception_blocks ();
|
||||
|
||||
/* If this function is supposed to return a value, ensure that
|
||||
we do not fall into the cleanups by mistake. The end of our
|
||||
function will look like this:
|
||||
|
||||
user code (may have return stmt somewhere)
|
||||
goto no_return_label
|
||||
cleanup_label:
|
||||
cleanups
|
||||
goto return_label
|
||||
no_return_label:
|
||||
NOTE_INSN_FUNCTION_END
|
||||
return_label:
|
||||
things for return
|
||||
|
||||
If the user omits a return stmt in the USER CODE section, we
|
||||
will have a control path which reaches NOTE_INSN_FUNCTION_END.
|
||||
Otherwise, we won't. */
|
||||
if (no_return_label)
|
||||
{
|
||||
DECL_CONTEXT (no_return_label) = fn;
|
||||
DECL_INITIAL (no_return_label) = error_mark_node;
|
||||
DECL_SOURCE_FILE (no_return_label) = input_filename;
|
||||
DECL_SOURCE_LINE (no_return_label) = lineno;
|
||||
expand_goto (no_return_label);
|
||||
}
|
||||
|
||||
if (cleanup_label)
|
||||
{
|
||||
/* Remove the binding contour which is used to catch
|
||||
cleanup-generated temporaries. */
|
||||
expand_end_bindings (0, 0, 0);
|
||||
poplevel (0, 0, 0);
|
||||
|
||||
/* Emit label at beginning of cleanup code for parameters. */
|
||||
emit_label (cleanup_label);
|
||||
}
|
||||
|
||||
/* Get return value into register if that's where it's supposed to
|
||||
be. */
|
||||
if (original_result_rtx)
|
||||
fixup_result_decl (DECL_RESULT (fn), original_result_rtx);
|
||||
|
||||
/* Finish building code that will trigger warnings if users forget
|
||||
to make their functions return values. */
|
||||
if (no_return_label || cleanup_label)
|
||||
emit_jump (return_label);
|
||||
if (no_return_label)
|
||||
{
|
||||
/* We don't need to call `expand_*_return' here because we don't
|
||||
need any cleanups here--this path of code is only for error
|
||||
checking purposes. */
|
||||
expand_label (no_return_label);
|
||||
}
|
||||
|
||||
/* We hard-wired immediate_size_expand to zero in start_function.
|
||||
Expand_function_end will decrement this variable. So, we set the
|
||||
variable to one here, so that after the decrement it will remain
|
||||
zero. */
|
||||
immediate_size_expand = 1;
|
||||
|
||||
/* Generate rtl for function exit. */
|
||||
expand_function_end (input_filename, lineno, 1);
|
||||
|
||||
/* So we can tell if jump_optimize sets it to 1. */
|
||||
can_reach_end = 0;
|
||||
|
||||
/* Before we call rest_of_compilation (which will pop the
|
||||
CURRENT_FUNCTION), we must save these values. */
|
||||
returns_null = current_function_returns_null;
|
||||
returns_value = current_function_returns_value;
|
||||
|
||||
/* If this is a nested function (like a template instantiation that
|
||||
we're compiling in the midst of compiling something else), push a
|
||||
new GC context. That will keep local variables on the stack from
|
||||
being collected while we're doing the compilation of this
|
||||
function. */
|
||||
if (function_depth > 1)
|
||||
ggc_push_context ();
|
||||
|
||||
/* Run the optimizers and output the assembler code for this
|
||||
function. */
|
||||
rest_of_compilation (fn);
|
||||
|
||||
/* Undo the call to ggc_push_context above. */
|
||||
if (function_depth > 1)
|
||||
ggc_pop_context ();
|
||||
|
||||
if (DECL_SAVED_INSNS (fn) && ! TREE_ASM_WRITTEN (fn))
|
||||
{
|
||||
/* Set DECL_EXTERNAL so that assemble_external will be called as
|
||||
necessary. We'll clear it again in finish_file. */
|
||||
if (! DECL_EXTERNAL (fn))
|
||||
DECL_NOT_REALLY_EXTERN (fn) = 1;
|
||||
DECL_EXTERNAL (fn) = 1;
|
||||
defer_fn (fn);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Keep this code around in case we later want to control debug info
|
||||
based on whether a type is "used". (jason 1999-11-11) */
|
||||
|
||||
if (ctype && TREE_ASM_WRITTEN (fn))
|
||||
note_debug_info_needed (ctype);
|
||||
#endif
|
||||
|
||||
/* If this function is marked with the constructor attribute, add it
|
||||
to the list of functions to be called along with constructors
|
||||
from static duration objects. */
|
||||
if (DECL_STATIC_CONSTRUCTOR (fn))
|
||||
static_ctors = tree_cons (NULL_TREE, fn, static_ctors);
|
||||
|
||||
/* If this function is marked with the destructor attribute, add it
|
||||
to the list of functions to be called along with destructors from
|
||||
static duration objects. */
|
||||
if (DECL_STATIC_DESTRUCTOR (fn))
|
||||
static_dtors = tree_cons (NULL_TREE, fn, static_dtors);
|
||||
|
||||
if (DECL_NAME (DECL_RESULT (fn)))
|
||||
returns_value |= can_reach_end;
|
||||
else
|
||||
returns_null |= can_reach_end;
|
||||
|
||||
if (TREE_THIS_VOLATILE (fn) && returns_null)
|
||||
warning ("`noreturn' function does return");
|
||||
else if (returns_null
|
||||
&& TREE_CODE (TREE_TYPE (TREE_TYPE (fn))) != VOID_TYPE)
|
||||
{
|
||||
/* Always complain if there's just no return statement. */
|
||||
if (!returns_value)
|
||||
warning ("no return statement in function returning non-void");
|
||||
else if (warn_return_type || pedantic)
|
||||
/* If this function returns non-void and control can drop through,
|
||||
complain. */
|
||||
warning ("control reaches end of non-void function");
|
||||
}
|
||||
|
||||
--function_depth;
|
||||
|
||||
if (!DECL_SAVED_INSNS (fn)
|
||||
&& !(flag_inline_trees && DECL_INLINE (fn)))
|
||||
{
|
||||
tree t;
|
||||
|
||||
/* Stop pointing to the local nodes about to be freed. */
|
||||
/* But DECL_INITIAL must remain nonzero so we know this
|
||||
was an actual function definition. */
|
||||
DECL_INITIAL (fn) = error_mark_node;
|
||||
for (t = DECL_ARGUMENTS (fn); t; t = TREE_CHAIN (t))
|
||||
DECL_RTL (t) = DECL_INCOMING_RTL (t) = NULL_RTX;
|
||||
}
|
||||
|
||||
/* Let the error reporting routines know that we're outside a
|
||||
function. For a nested function, this value is used in
|
||||
pop_cp_function_context and then reset via pop_function_context. */
|
||||
current_function_decl = NULL_TREE;
|
||||
}
|
||||
|
||||
/* Perform initialization related to this module. */
|
||||
|
||||
void
|
||||
|
|
Loading…
Add table
Reference in a new issue