#include "config.h"
#include "system.h"
#include "tree.h"
#include "cp-tree.h"
#include "tree-inline.h"
#include "except.h"
#include "lex.h"
#include "toplev.h"
#include "flags.h"
#include "rtl.h"
#include "expr.h"
#include "output.h"
#include "timevar.h"
#include "debug.h"
#include "langhooks.h"
#include "genindex.h"
static tree maybe_convert_cond PARAMS ((tree));
static tree simplify_aggr_init_exprs_r PARAMS ((tree *, int *, void *));
static void deferred_type_access_control PARAMS ((void));
static void emit_associated_thunks PARAMS ((tree));
static void genrtl_try_block PARAMS ((tree));
static void genrtl_eh_spec_block PARAMS ((tree));
static void genrtl_handler 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));
static tree clear_decl_rtl PARAMS ((tree *, int *, void *));
#define FINISH_COND(COND, STMT, SUBSTMT) \
do { \
if (last_tree != (STMT)) \
{ \
RECHAIN_STMTS (STMT, SUBSTMT); \
if (!processing_template_decl) \
{ \
(COND) = build_tree_list (SUBSTMT, COND); \
(SUBSTMT) = (COND); \
} \
} \
else \
(SUBSTMT) = (COND); \
} while (0)
int
stmts_are_full_exprs_p ()
{
return current_stmt_tree ()->stmts_are_full_exprs_p;
}
stmt_tree
current_stmt_tree ()
{
return (cfun
? &cfun->language->base.x_stmt_tree
: &scope_chain->x_stmt_tree);
}
int
anon_aggr_type_p (node)
tree node;
{
return ANON_AGGR_TYPE_P (node);
}
tree
do_poplevel ()
{
tree block = NULL_TREE;
if (stmts_are_full_exprs_p ())
{
tree scope_stmts = NULL_TREE;
if (!processing_template_decl)
scope_stmts = add_scope_stmt (0, 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 block;
}
void
do_pushlevel ()
{
if (stmts_are_full_exprs_p ())
{
pushlevel (0);
if (!processing_template_decl)
add_scope_stmt (1, 0);
}
}
tree
finish_goto_stmt (destination)
tree destination;
{
if (TREE_CODE (destination) == IDENTIFIER_NODE)
destination = lookup_label (destination);
if (TREE_CODE (destination) == LABEL_DECL)
TREE_USED (destination) = 1;
if (TREE_CODE (destination) != LABEL_DECL)
DECL_UNINLINABLE (current_function_decl) = 1;
check_goto (destination);
return add_stmt (build_stmt (GOTO_STMT, destination));
}
tree
maybe_convert_cond (cond)
tree cond;
{
if (!cond)
return NULL_TREE;
if (processing_template_decl)
return cond;
cond = convert_from_reference (cond);
return condition_conversion (cond);
}
tree
finish_expr_stmt (expr)
tree expr;
{
tree r = NULL_TREE;
tree expr_type = NULL_TREE;;
if (expr != NULL_TREE)
{
if (!processing_template_decl
&& !(stmts_are_full_exprs_p ())
&& ((TREE_CODE (TREE_TYPE (expr)) == ARRAY_TYPE
&& lvalue_p (expr))
|| TREE_CODE (TREE_TYPE (expr)) == FUNCTION_TYPE))
expr = default_conversion (expr);
expr_type = TREE_TYPE (expr);
if (stmts_are_full_exprs_p ())
expr = convert_to_void (expr, "statement");
r = add_stmt (build_stmt (EXPR_STMT, expr));
}
finish_stmt ();
last_expr_type = expr_type;
return r;
}
tree
begin_if_stmt ()
{
tree r;
do_pushlevel ();
r = build_stmt (IF_STMT, NULL_TREE, NULL_TREE, NULL_TREE);
add_stmt (r);
return r;
}
void
finish_if_stmt_cond (cond, if_stmt)
tree cond;
tree if_stmt;
{
cond = maybe_convert_cond (cond);
FINISH_COND (cond, if_stmt, IF_COND (if_stmt));
}
tree
finish_then_clause (if_stmt)
tree if_stmt;
{
RECHAIN_STMTS (if_stmt, THEN_CLAUSE (if_stmt));
return if_stmt;
}
void
begin_else_clause ()
{
}
void
finish_else_clause (if_stmt)
tree if_stmt;
{
RECHAIN_STMTS (if_stmt, ELSE_CLAUSE (if_stmt));
}
void
finish_if_stmt ()
{
finish_stmt ();
do_poplevel ();
}
tree
begin_while_stmt ()
{
tree r;
r = build_stmt (WHILE_STMT, NULL_TREE, NULL_TREE);
add_stmt (r);
do_pushlevel ();
return r;
}
void
finish_while_stmt_cond (cond, while_stmt)
tree cond;
tree while_stmt;
{
cond = maybe_convert_cond (cond);
if (processing_template_decl)
FINISH_COND (cond, while_stmt, WHILE_COND (while_stmt));
else if (getdecls () == NULL_TREE)
WHILE_COND (while_stmt) = cond;
else
{
tree if_stmt;
WHILE_COND (while_stmt) = boolean_true_node;
if_stmt = begin_if_stmt ();
cond = build_unary_op (TRUTH_NOT_EXPR, cond, 0);
finish_if_stmt_cond (cond, if_stmt);
finish_break_stmt ();
finish_then_clause (if_stmt);
finish_if_stmt ();
}
}
void
finish_while_stmt (while_stmt)
tree while_stmt;
{
do_poplevel ();
RECHAIN_STMTS (while_stmt, WHILE_BODY (while_stmt));
finish_stmt ();
}
tree
begin_do_stmt ()
{
tree r = build_stmt (DO_STMT, NULL_TREE, NULL_TREE);
add_stmt (r);
return r;
}
void
finish_do_body (do_stmt)
tree do_stmt;
{
RECHAIN_STMTS (do_stmt, DO_BODY (do_stmt));
}
void
finish_do_stmt (cond, do_stmt)
tree cond;
tree do_stmt;
{
cond = maybe_convert_cond (cond);
DO_COND (do_stmt) = cond;
finish_stmt ();
}
tree
finish_return_stmt (expr)
tree expr;
{
tree r;
if (!processing_template_decl)
expr = check_return_expr (expr);
if (!processing_template_decl)
{
if (DECL_DESTRUCTOR_P (current_function_decl))
{
return finish_goto_stmt (dtor_label);
}
}
r = add_stmt (build_stmt (RETURN_STMT, expr));
finish_stmt ();
return r;
}
tree
begin_for_stmt ()
{
tree r;
r = build_stmt (FOR_STMT, NULL_TREE, NULL_TREE,
NULL_TREE, NULL_TREE);
NEW_FOR_SCOPE_P (r) = flag_new_for_scope > 0;
if (NEW_FOR_SCOPE_P (r))
{
do_pushlevel ();
note_level_for_for ();
}
add_stmt (r);
return r;
}
void
finish_for_init_stmt (for_stmt)
tree for_stmt;
{
if (last_tree != for_stmt)
RECHAIN_STMTS (for_stmt, FOR_INIT_STMT (for_stmt));
do_pushlevel ();
}
void
finish_for_cond (cond, for_stmt)
tree cond;
tree for_stmt;
{
cond = maybe_convert_cond (cond);
if (processing_template_decl)
FINISH_COND (cond, for_stmt, FOR_COND (for_stmt));
else if (getdecls () == NULL_TREE)
FOR_COND (for_stmt) = cond;
else
{
tree if_stmt;
FOR_COND (for_stmt) = NULL_TREE;
if_stmt = begin_if_stmt ();
cond = build_unary_op (TRUTH_NOT_EXPR, cond, 0);
finish_if_stmt_cond (cond, if_stmt);
finish_break_stmt ();
finish_then_clause (if_stmt);
finish_if_stmt ();
}
}
void
finish_for_expr (expr, for_stmt)
tree expr;
tree for_stmt;
{
FOR_EXPR (for_stmt) = expr;
}
void
finish_for_stmt (for_stmt)
tree for_stmt;
{
do_poplevel ();
RECHAIN_STMTS (for_stmt, FOR_BODY (for_stmt));
if (NEW_FOR_SCOPE_P (for_stmt))
do_poplevel ();
finish_stmt ();
}
tree
finish_break_stmt ()
{
return add_stmt (build_break_stmt ());
}
tree
finish_continue_stmt ()
{
return add_stmt (build_continue_stmt ());
}
tree
begin_switch_stmt ()
{
tree r;
do_pushlevel ();
r = build_stmt (SWITCH_STMT, NULL_TREE, NULL_TREE, NULL_TREE);
add_stmt (r);
return r;
}
void
finish_switch_cond (cond, switch_stmt)
tree cond;
tree switch_stmt;
{
tree orig_type = NULL;
if (!processing_template_decl)
{
tree index;
cond = build_expr_type_conversion (WANT_INT | WANT_ENUM, cond, 1);
if (cond == NULL_TREE)
{
error ("switch quantity not an integer");
cond = error_mark_node;
}
orig_type = TREE_TYPE (cond);
if (cond != error_mark_node)
{
cond = default_conversion (cond);
cond = fold (build1 (CLEANUP_POINT_EXPR, TREE_TYPE (cond), cond));
}
if (cond != error_mark_node)
{
index = get_unwidened (cond, NULL_TREE);
if (TREE_UNSIGNED (TREE_TYPE (cond))
== TREE_UNSIGNED (TREE_TYPE (index)))
cond = index;
}
}
FINISH_COND (cond, switch_stmt, SWITCH_COND (switch_stmt));
SWITCH_TYPE (switch_stmt) = orig_type;
push_switch (switch_stmt);
}
void
finish_switch_stmt (switch_stmt)
tree switch_stmt;
{
RECHAIN_STMTS (switch_stmt, SWITCH_BODY (switch_stmt));
pop_switch ();
finish_stmt ();
do_poplevel ();
}
static void
genrtl_try_block (t)
tree t;
{
if (CLEANUP_P (t))
{
expand_eh_region_start ();
expand_stmt (TRY_STMTS (t));
expand_eh_region_end_cleanup (TRY_HANDLERS (t));
}
else
{
if (!FN_TRY_BLOCK_P (t))
emit_line_note (input_filename, lineno);
expand_eh_region_start ();
expand_stmt (TRY_STMTS (t));
if (FN_TRY_BLOCK_P (t))
{
expand_start_all_catch ();
in_function_try_handler = 1;
expand_stmt (TRY_HANDLERS (t));
in_function_try_handler = 0;
expand_end_all_catch ();
}
else
{
expand_start_all_catch ();
expand_stmt (TRY_HANDLERS (t));
expand_end_all_catch ();
}
}
}
static void
genrtl_eh_spec_block (t)
tree t;
{
expand_eh_region_start ();
expand_stmt (EH_SPEC_STMTS (t));
expand_eh_region_end_allowed (EH_SPEC_RAISES (t),
build_call (call_unexpected_node,
tree_cons (NULL_TREE,
build_exc_ptr (),
NULL_TREE)));
}
tree
begin_try_block ()
{
tree r = build_stmt (TRY_BLOCK, NULL_TREE, NULL_TREE);
add_stmt (r);
return r;
}
tree
begin_function_try_block ()
{
tree r = build_stmt (TRY_BLOCK, NULL_TREE, NULL_TREE);
FN_TRY_BLOCK_P (r) = 1;
add_stmt (r);
return r;
}
void
finish_try_block (try_block)
tree try_block;
{
RECHAIN_STMTS (try_block, TRY_STMTS (try_block));
}
void
finish_cleanup_try_block (try_block)
tree try_block;
{
RECHAIN_STMTS (try_block, TRY_STMTS (try_block));
}
void
finish_cleanup (cleanup, try_block)
tree cleanup;
tree try_block;
{
TRY_HANDLERS (try_block) = cleanup;
CLEANUP_P (try_block) = 1;
}
void
finish_function_try_block (try_block)
tree try_block;
{
if (TREE_CHAIN (try_block)
&& TREE_CODE (TREE_CHAIN (try_block)) == CTOR_INITIALIZER)
{
TREE_CHAIN (TREE_CHAIN (try_block)) = last_tree;
RECHAIN_STMTS (try_block, TRY_STMTS (try_block));
}
else
RECHAIN_STMTS (try_block, TRY_STMTS (try_block));
in_function_try_handler = 1;
}
void
finish_handler_sequence (try_block)
tree try_block;
{
RECHAIN_STMTS (try_block, TRY_HANDLERS (try_block));
check_handlers (TRY_HANDLERS (try_block));
}
void
finish_function_handler_sequence (try_block)
tree try_block;
{
in_function_try_handler = 0;
RECHAIN_STMTS (try_block, TRY_HANDLERS (try_block));
check_handlers (TRY_HANDLERS (try_block));
}
static void
genrtl_handler (t)
tree t;
{
genrtl_do_pushlevel ();
if (!processing_template_decl)
expand_start_catch (HANDLER_TYPE (t));
expand_stmt (HANDLER_BODY (t));
if (!processing_template_decl)
expand_end_catch ();
}
tree
begin_handler ()
{
tree r;
r = build_stmt (HANDLER, NULL_TREE, NULL_TREE);
add_stmt (r);
do_pushlevel ();
note_level_for_catch ();
return r;
}
void
finish_handler_parms (decl, handler)
tree decl;
tree handler;
{
tree type = NULL_TREE;
if (processing_template_decl)
{
if (decl)
{
decl = pushdecl (decl);
decl = push_template_decl (decl);
add_decl_stmt (decl);
RECHAIN_STMTS (handler, HANDLER_PARMS (handler));
type = TREE_TYPE (decl);
}
}
else
type = expand_start_catch_block (decl);
HANDLER_TYPE (handler) = type;
}
void
finish_handler (handler)
tree handler;
{
if (!processing_template_decl)
expand_end_catch_block ();
do_poplevel ();
RECHAIN_STMTS (handler, HANDLER_BODY (handler));
}
tree
begin_compound_stmt (has_no_scope)
int has_no_scope;
{
tree r;
int is_try = 0;
r = build_stmt (COMPOUND_STMT, NULL_TREE);
if (last_tree && TREE_CODE (last_tree) == TRY_BLOCK)
is_try = 1;
add_stmt (r);
if (has_no_scope)
COMPOUND_STMT_NO_SCOPE (r) = 1;
last_expr_type = NULL_TREE;
if (!has_no_scope)
{
do_pushlevel ();
if (is_try)
note_level_for_try ();
}
else
keep_next_level (0);
return r;
}
tree
finish_compound_stmt (has_no_scope, compound_stmt)
int has_no_scope;
tree compound_stmt;
{
tree r;
tree t;
if (!has_no_scope)
{
if (flag_objc)
objc_clear_super_receiver ();
r = do_poplevel ();
}
else
r = NULL_TREE;
RECHAIN_STMTS (compound_stmt, COMPOUND_BODY (compound_stmt));
t = last_expr_type;
finish_stmt ();
last_expr_type = t;
return r;
}
tree
finish_asm_stmt (cv_qualifier, string, output_operands,
input_operands, clobbers)
tree cv_qualifier;
tree string;
tree output_operands;
tree input_operands;
tree clobbers;
{
tree r;
tree t;
if (cv_qualifier != NULL_TREE
&& cv_qualifier != ridpointers[(int) RID_VOLATILE])
{
warning ("%s qualifier ignored on asm",
IDENTIFIER_POINTER (cv_qualifier));
cv_qualifier = NULL_TREE;
}
if (!processing_template_decl)
{
int i;
int ninputs;
int noutputs;
for (t = input_operands; t; t = TREE_CHAIN (t))
{
tree converted_operand
= decay_conversion (TREE_VALUE (t));
if (TREE_TYPE (converted_operand) == unknown_type_node)
{
error ("type of asm operand `%E' could not be determined",
TREE_VALUE (t));
converted_operand = error_mark_node;
}
TREE_VALUE (t) = converted_operand;
}
ninputs = list_length (input_operands);
noutputs = list_length (output_operands);
for (i = 0, t = output_operands; t; t = TREE_CHAIN (t), ++i)
{
bool allows_mem;
bool allows_reg;
bool is_inout;
const char *constraint;
tree operand;
constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (t)));
operand = TREE_VALUE (t);
if (!parse_output_constraint (&constraint,
i, ninputs, noutputs,
&allows_mem,
&allows_reg,
&is_inout))
{
TREE_TYPE (operand) = error_mark_node;
continue;
}
if (!allows_reg && DECL_P (operand))
cxx_mark_addressable (operand);
}
}
r = build_stmt (ASM_STMT, cv_qualifier, string,
output_operands, input_operands,
clobbers);
return add_stmt (r);
}
void
finish_label_stmt (name)
tree name;
{
tree decl = define_label (input_filename, lineno, name);
add_stmt (build_stmt (LABEL_STMT, decl));
}
void
finish_label_decl (name)
tree name;
{
tree decl = declare_local_label (name);
add_decl_stmt (decl);
}
void
finish_decl_cleanup (decl, cleanup)
tree decl;
tree cleanup;
{
add_stmt (build_stmt (CLEANUP_STMT, decl, cleanup));
}
void
finish_eh_cleanup (cleanup)
tree cleanup;
{
tree r = build_stmt (CLEANUP_STMT, NULL_TREE, cleanup);
CLEANUP_EH_ONLY (r) = 1;
add_stmt (r);
}
static void
genrtl_named_return_value ()
{
tree decl = DECL_RESULT (current_function_decl);
if (DECL_REGISTER (decl))
{
SET_DECL_RTL (decl, gen_reg_rtx (GET_MODE (DECL_RTL (decl))));
if (TREE_ADDRESSABLE (decl))
put_var_into_stack (decl);
}
emit_local_var (decl);
}
void
finish_named_return_value (return_id, init)
tree return_id, init;
{
tree decl = DECL_RESULT (current_function_decl);
if (pedantic)
pedwarn ("ISO C++ does not permit named return values");
cp_deprecated ("the named return value extension");
if (return_id != NULL_TREE)
{
if (DECL_NAME (decl) == NULL_TREE)
DECL_NAME (decl) = return_id;
else
{
error ("return identifier `%D' already in place", return_id);
return;
}
}
if (DECL_CONSTRUCTOR_P (current_function_decl))
{
error ("can't redefine default return value for constructors");
return;
}
if (DECL_NAME (decl) != NULL_TREE)
{
DECL_INITIAL (decl) = init;
if (doing_semantic_analysis_p ())
pushdecl (decl);
if (!processing_template_decl)
{
cp_finish_decl (decl, init, NULL_TREE, 0);
add_stmt (build_stmt (RETURN_INIT, NULL_TREE, NULL_TREE));
}
else
add_stmt (build_stmt (RETURN_INIT, return_id, init));
}
DECL_UNINLINABLE (current_function_decl) = 1;
}
void
begin_mem_initializers ()
{
if (! DECL_CONSTRUCTOR_P (current_function_decl))
error ("only constructors take base initializers");
}
void
finish_mem_initializers (tree mem_inits)
{
mem_inits = nreverse (mem_inits);
if (processing_template_decl)
add_stmt (build_min_nt (CTOR_INITIALIZER, mem_inits));
else
emit_mem_initializers (mem_inits);
}
tree *
current_scope_stmt_stack ()
{
return &cfun->language->base.x_scope_stmt_stack;
}
tree
finish_parenthesized_expr (expr)
tree expr;
{
if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (expr))))
C_SET_EXP_ORIGINAL_CODE (expr, ERROR_MARK);
if (TREE_CODE (expr) == OFFSET_REF)
PTRMEM_OK_P (expr) = 0;
return expr;
}
tree
begin_stmt_expr ()
{
if (! cfun && !last_tree)
begin_stmt_tree (&scope_chain->x_saved_tree);
keep_next_level (1);
return last_tree;
}
tree
begin_global_stmt_expr ()
{
if (! cfun && !last_tree)
begin_stmt_tree (&scope_chain->x_saved_tree);
keep_next_level (1);
return last_tree ? last_tree : expand_start_stmt_expr(1);
}
tree
finish_global_stmt_expr (stmt_expr)
tree stmt_expr;
{
stmt_expr = expand_end_stmt_expr (stmt_expr);
if (! cfun
&& TREE_CHAIN (scope_chain->x_saved_tree) == NULL_TREE)
finish_stmt_tree (&scope_chain->x_saved_tree);
return stmt_expr;
}
tree
finish_stmt_expr (rtl_expr)
tree rtl_expr;
{
tree result;
if (!last_expr_type)
last_expr_type = void_type_node;
result = build_min (STMT_EXPR, last_expr_type, last_tree);
TREE_SIDE_EFFECTS (result) = 1;
last_tree = rtl_expr;
TREE_CHAIN (last_tree) = NULL_TREE;
if (! cfun
&& TREE_CHAIN (scope_chain->x_saved_tree) == NULL_TREE)
finish_stmt_tree (&scope_chain->x_saved_tree);
return result;
}
tree
finish_call_expr (tree fn, tree args, bool disallow_virtual)
{
if (fn == error_mark_node || args == error_mark_node)
return error_mark_node;
if (processing_template_decl)
return build_nt (CALL_EXPR, fn, args, NULL_TREE);
my_friendly_assert (!args || TREE_CODE (args) == TREE_LIST,
20020712);
if (BASELINK_P (fn))
{
tree object;
if (current_class_type
&& DERIVED_FROM_P (BINFO_TYPE (BASELINK_ACCESS_BINFO (fn)),
current_class_type)
&& current_class_ref)
object = current_class_ref;
else
{
tree representative_fn;
representative_fn = BASELINK_FUNCTIONS (fn);
if (TREE_CODE (representative_fn) == TEMPLATE_ID_EXPR)
representative_fn = TREE_OPERAND (representative_fn, 0);
representative_fn = get_first_fn (representative_fn);
object = build_dummy_object (DECL_CONTEXT (representative_fn));
}
return build_new_method_call (object, fn, args, NULL_TREE,
(disallow_virtual
? LOOKUP_NONVIRTUAL : 0));
}
else if (is_overloaded_fn (fn))
return build_new_function_call (fn, args);
else if (CLASS_TYPE_P (TREE_TYPE (fn)))
{
tree result;
result = build_opfncall (CALL_EXPR, LOOKUP_NORMAL, fn, args, NULL_TREE);
if (result)
return result;
}
return build_function_call (fn, args);
}
tree
finish_increment_expr (expr, code)
tree expr;
enum tree_code code;
{
if (TREE_CODE (expr) == OFFSET_REF)
expr = resolve_offset_ref (expr);
return build_x_unary_op (code, expr);
}
tree
finish_this_expr ()
{
tree result;
if (current_class_ptr)
{
result = current_class_ptr;
}
else if (current_function_decl
&& DECL_STATIC_FUNCTION_P (current_function_decl))
{
error ("`this' is unavailable for static member functions");
result = error_mark_node;
}
else
{
if (current_function_decl)
error ("invalid use of `this' in non-member function");
else
error ("invalid use of `this' at top level");
result = error_mark_node;
}
return result;
}
tree
finish_object_call_expr (fn, object, args)
tree fn;
tree object;
tree args;
{
if (DECL_DECLARES_TYPE_P (fn))
{
if (processing_template_decl)
fn = DECL_NAME (fn);
else
{
error ("calling type `%T' like a method", fn);
return error_mark_node;
}
}
if (name_p (fn))
return build_method_call (object, fn, args, NULL_TREE, LOOKUP_NORMAL);
else
return build_new_method_call (object, fn, args, NULL_TREE, LOOKUP_NORMAL);
}
tree
finish_qualified_object_call_expr (fn, object, args)
tree fn;
tree object;
tree args;
{
return build_scoped_method_call (object, TREE_OPERAND (fn, 0),
TREE_OPERAND (fn, 1), args);
}
tree
finish_pseudo_destructor_call_expr (object, scope, destructor)
tree object;
tree scope;
tree destructor;
{
if (processing_template_decl)
return build_min_nt (PSEUDO_DTOR_EXPR, object, scope, destructor);
if (scope && scope != destructor)
error ("destructor specifier `%T::~%T()' must have matching names",
scope, destructor);
if ((scope == NULL_TREE || IDENTIFIER_GLOBAL_VALUE (destructor))
&& (TREE_CODE (TREE_TYPE (object)) !=
TREE_CODE (TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (destructor)))))
error ("`%E' is not of type `%T'", object, destructor);
return cp_convert (void_type_node, object);
}
tree
finish_unary_op_expr (code, expr)
enum tree_code code;
tree expr;
{
tree result = build_x_unary_op (code, expr);
if (code == NEGATE_EXPR && TREE_CODE (expr) == INTEGER_CST
&& TREE_CODE (result) == INTEGER_CST
&& !TREE_UNSIGNED (TREE_TYPE (result))
&& INT_CST_LT (result, integer_zero_node))
TREE_NEGATED_INT (result) = 1;
overflow_warning (result);
return result;
}
tree
finish_id_expr (expr)
tree expr;
{
if (TREE_CODE (expr) == IDENTIFIER_NODE)
expr = do_identifier (expr, 1, NULL_TREE);
if (TREE_TYPE (expr) == error_mark_node)
expr = error_mark_node;
return expr;
}
tree
finish_fname (tree id)
{
tree decl;
decl = fname_decl (C_RID_CODE (id), id);
if (processing_template_decl)
decl = build_min_nt (LOOKUP_EXPR, DECL_NAME (decl));
return decl;
}
static tree current_type_lookups;
static void
deferred_type_access_control ()
{
tree lookup = type_lookups;
if (lookup == error_mark_node)
return;
for (; lookup; lookup = TREE_CHAIN (lookup))
enforce_access (TREE_PURPOSE (lookup), TREE_VALUE (lookup));
}
void
decl_type_access_control (decl)
tree decl;
{
tree save_fn;
if (type_lookups == error_mark_node)
return;
save_fn = current_function_decl;
if (decl && TREE_CODE (decl) == FUNCTION_DECL)
current_function_decl = decl;
deferred_type_access_control ();
current_function_decl = save_fn;
type_lookups = current_type_lookups;
}
void
save_type_access_control (lookups)
tree lookups;
{
current_type_lookups = lookups;
}
void
reset_type_access_control ()
{
type_lookups = NULL_TREE;
current_type_lookups = NULL_TREE;
}
int
begin_function_definition (decl_specs, attributes, declarator)
tree decl_specs;
tree attributes;
tree declarator;
{
if (!start_function (decl_specs, declarator, attributes, SF_DEFAULT))
return 0;
deferred_type_access_control ();
type_lookups = error_mark_node;
reset_specialization ();
return 1;
}
tree
begin_constructor_declarator (scope, name)
tree scope;
tree name;
{
tree result = build_nt (SCOPE_REF, scope, name);
enter_scope_of (result);
return result;
}
tree
finish_declarator (declarator, declspecs, attributes,
prefix_attributes, initialized)
tree declarator;
tree declspecs;
tree attributes;
tree prefix_attributes;
int initialized;
{
return start_decl (declarator, declspecs, initialized, attributes,
prefix_attributes);
}
void
finish_translation_unit ()
{
pop_everything ();
while (current_namespace != global_namespace)
pop_namespace ();
finish_fname_decls ();
(*lang_hooks.finish_file) ();
}
tree
finish_template_type_parm (aggr, identifier)
tree aggr;
tree identifier;
{
if (aggr != class_type_node)
{
pedwarn ("template type parameters must use the keyword `class' or `typename'");
aggr = class_type_node;
}
return build_tree_list (aggr, identifier);
}
tree
finish_template_template_parm (aggr, identifier)
tree aggr;
tree identifier;
{
tree decl = build_decl (TYPE_DECL, identifier, NULL_TREE);
tree tmpl = build_lang_decl (TEMPLATE_DECL, identifier, NULL_TREE);
DECL_TEMPLATE_PARMS (tmpl) = current_template_parms;
DECL_TEMPLATE_RESULT (tmpl) = decl;
DECL_ARTIFICIAL (decl) = 1;
end_template_decl ();
my_friendly_assert (DECL_TEMPLATE_PARMS (tmpl), 20010110);
return finish_template_type_parm (aggr, tmpl);
}
tree
check_template_template_default_arg (tree argument)
{
if (TREE_CODE (argument) != TEMPLATE_DECL
&& TREE_CODE (argument) != TEMPLATE_TEMPLATE_PARM
&& TREE_CODE (argument) != TYPE_DECL
&& TREE_CODE (argument) != UNBOUND_CLASS_TEMPLATE)
{
error ("invalid default template argument");
return error_mark_node;
}
return argument;
}
tree
finish_parmlist (parms, ellipsis)
tree parms;
int ellipsis;
{
if (parms)
{
TREE_PARMLIST (parms) = 1;
PARMLIST_ELLIPSIS_P (parms) = ellipsis;
}
return parms;
}
tree
begin_class_definition (t)
tree t;
{
if (t == error_mark_node)
return error_mark_node;
if (!flag_suppress_builtin_indexing)
set_index_lang (PB_INDEX_LANG_CP);
decl_type_access_control (TYPE_NAME (t));
reset_type_access_control ();
if (processing_template_parmlist)
{
error ("definition of `%#T' inside template parameter list", t);
return error_mark_node;
}
if (IMPLICIT_TYPENAME_P (t))
t = TREE_TYPE (t);
else if (TREE_CODE (t) == TYPENAME_TYPE)
{
error ("invalid definition of qualified type `%T'", t);
t = error_mark_node;
}
if (t == error_mark_node || ! IS_AGGR_TYPE (t))
{
t = make_aggr_type (RECORD_TYPE);
pushtag (make_anon_name (), t, 0);
}
if (PARTIAL_INSTANTIATION_P (t))
{
if (!pedantic)
{
TYPE_BINFO_BASETYPES (t) = NULL_TREE;
TYPE_FIELDS (t) = NULL_TREE;
TYPE_METHODS (t) = NULL_TREE;
CLASSTYPE_DECL_LIST (t) = NULL_TREE;
CLASSTYPE_TAGS (t) = NULL_TREE;
CLASSTYPE_VBASECLASSES (t) = NULL_TREE;
TYPE_SIZE (t) = NULL_TREE;
}
PARTIAL_INSTANTIATION_P (t) = 0;
}
else if (COMPLETE_TYPE_P (t))
duplicate_tag_error (t);
DECL_SOURCE_FILE (TYPE_NAME (t)) = input_filename;
DECL_SOURCE_LINE (TYPE_NAME (t)) = lineno;
if (TYPE_BEING_DEFINED (t))
{
t = make_aggr_type (TREE_CODE (t));
pushtag (TYPE_IDENTIFIER (t), t, 0);
}
maybe_process_partial_specialization (t);
pushclass (t, 1);
TYPE_BEING_DEFINED (t) = 1;
TYPE_PACKED (t) = flag_pack_struct;
if (! TYPE_ANONYMOUS_P (t))
{
CLASSTYPE_INTERFACE_ONLY (t) = interface_only;
SET_CLASSTYPE_INTERFACE_UNKNOWN_X
(t, interface_unknown);
}
reset_specialization();
build_self_reference ();
if (flag_gen_index)
{
int info_tag = INDEX_ERROR;
int l_base_count = 0;
tree base_typename;
tree typename = DECL_NAME (TYPE_NAME (t));
if (CLASSTYPE_DECLARED_CLASS(t))
info_tag = INDEX_CLASS_BEGIN;
else if (TREE_CODE (t) == RECORD_TYPE)
info_tag = INDEX_RECORD_BEGIN;
else if (TREE_CODE (t) == UNION_TYPE)
info_tag = INDEX_UNION_BEGIN;
gen_indexing_info (info_tag, IDENTIFIER_POINTER (typename),
lineno);
if (current_aggr == class_type_node)
for (l_base_count = 0;
l_base_count < CLASSTYPE_N_BASECLASSES (t);
l_base_count++)
{
base_typename = TYPE_NAME (TYPE_BINFO_BASETYPE (t, l_base_count));
gen_indexing_info (INDEX_CLASS_INHERITANCE,
IDENTIFIER_POINTER (DECL_NAME (base_typename)),
lineno);
}
}
return t;
}
void
finish_member_declaration (decl)
tree decl;
{
if (decl == error_mark_node || decl == NULL_TREE)
return;
if (decl == void_type_node)
return;
my_friendly_assert (TREE_CHAIN (decl) == NULL_TREE, 0);
if (flag_gen_index)
{
if (!processing_template_decl
&& !DECL_ARTIFICIAL (decl)
&& TREE_CODE (decl) != USING_DECL
&& TREE_CODE (decl) != TEMPLATE_DECL)
{
int info_tag;
switch (TREE_CODE (decl))
{
case FUNCTION_DECL:
if (DECL_CONSTRUCTOR_P (decl))
info_tag = INDEX_CONSTRUCTOR_DECL;
else if (DECL_DESTRUCTOR_P (decl))
info_tag = INDEX_DESTRUCTOR_DECL;
else if (DECL_STATIC_FUNCTION_P (decl))
{
if (IDENTIFIER_OPNAME_P (DECL_NAME (decl)))
info_tag = INDEX_CLASS_OPERATOR_DECL;
else
info_tag = INDEX_CLASS_METHOD_DECL;
}
else if (DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
{
if (IDENTIFIER_OPNAME_P (DECL_NAME (decl)))
info_tag = INDEX_INSTANCE_OPERATOR_DECL;
else
info_tag = INDEX_INSTANCE_METHOD_DECL;
}
else
info_tag = INDEX_FUNCTION_DECL;
break;
case CONST_DECL:
info_tag = INDEX_CONST_DECL;
break;
case FIELD_DECL:
case VAR_DECL:
info_tag = INDEX_DATA_DECL;
break;
case TYPE_DECL:
info_tag = INDEX_TYPE_DECL;
break;
default:
info_tag = INDEX_ERROR;
break;
}
if (DECL_NAME (decl))
gen_indexing_info (info_tag,
IDENTIFIER_POINTER (DECL_NAME (decl)),
DECL_SOURCE_LINE (decl));
}
}
TREE_PRIVATE (decl)
= (current_access_specifier == access_private_node);
TREE_PROTECTED (decl)
= (current_access_specifier == access_protected_node);
if (TREE_CODE (decl) == TEMPLATE_DECL)
{
TREE_PRIVATE (DECL_TEMPLATE_RESULT (decl)) = TREE_PRIVATE (decl);
TREE_PROTECTED (DECL_TEMPLATE_RESULT (decl)) = TREE_PROTECTED (decl);
}
DECL_CONTEXT (decl) = current_class_type;
if (DECL_LANG_SPECIFIC (decl) && DECL_LANGUAGE (decl) == lang_c)
SET_DECL_LANGUAGE (decl, lang_cplusplus);
maybe_add_class_template_decl_list (current_class_type, decl, 0);
if (TREE_CODE (decl) == FUNCTION_DECL
|| DECL_FUNCTION_TEMPLATE_P (decl))
{
add_method (current_class_type, decl, 0);
TREE_CHAIN (decl) = TYPE_METHODS (current_class_type);
TYPE_METHODS (current_class_type) = decl;
}
else
{
if (TREE_CODE (decl) == TYPE_DECL)
TYPE_FIELDS (current_class_type)
= chainon (TYPE_FIELDS (current_class_type), decl);
else
{
TREE_CHAIN (decl) = TYPE_FIELDS (current_class_type);
TYPE_FIELDS (current_class_type) = decl;
}
if (TREE_CODE (decl) != USING_DECL)
pushdecl_class_level (decl);
}
}
tree
finish_class_definition (t, attributes, semi, pop_scope_p)
tree t;
tree attributes;
int semi;
int pop_scope_p;
{
if (t == error_mark_node)
return error_mark_node;
if (semi)
note_got_semicolon (t);
if (flag_gen_index)
{
tree typename = DECL_NAME (TYPE_NAME (t));
if (!ANON_AGGRNAME_P (typename))
{
int info_tag = INDEX_ERROR;
if (CLASSTYPE_DECLARED_CLASS(t))
info_tag = INDEX_CLASS_END;
else if (TREE_CODE (t) == RECORD_TYPE)
info_tag = INDEX_RECORD_END;
else if (TREE_CODE (t) == UNION_TYPE)
info_tag = INDEX_UNION_END;
gen_indexing_info (info_tag, NULL, lineno);
}
}
attributes = chainon (TYPE_ATTRIBUTES (t), attributes);
TYPE_ATTRIBUTES (t) = NULL_TREE;
if (TREE_CODE (t) == ENUMERAL_TYPE)
;
else
{
t = finish_struct (t, attributes);
if (semi)
note_got_semicolon (t);
}
if (! semi)
check_for_missing_semicolon (t);
if (pop_scope_p)
pop_scope (CP_DECL_CONTEXT (TYPE_MAIN_DECL (t)));
if (current_scope () == current_function_decl)
do_pending_defargs ();
return t;
}
void
begin_inline_definitions ()
{
if (current_scope () == current_function_decl)
do_pending_inlines ();
}
tree
finish_member_class_template (types)
tree types;
{
tree t;
for (t = types; t != NULL_TREE; t = TREE_CHAIN (t))
if (IS_AGGR_TYPE_CODE (TREE_CODE (TREE_VALUE (t))))
maybe_process_partial_specialization (TREE_VALUE (t));
note_list_got_semicolon (types);
grok_x_components (types);
if (TYPE_CONTEXT (TREE_VALUE (types)) != current_class_type)
types = NULL_TREE;
finish_member_template_decl (types);
return NULL_TREE;
}
void
finish_template_decl (parms)
tree parms;
{
if (parms)
end_template_decl ();
else
end_specialization ();
}
tree
finish_template_type (name, args, entering_scope)
tree name;
tree args;
int entering_scope;
{
tree decl;
decl = lookup_template_class (name, args,
NULL_TREE, NULL_TREE,
entering_scope, 1);
if (decl != error_mark_node)
decl = TYPE_STUB_DECL (decl);
return decl;
}
void
enter_scope_of (sr)
tree sr;
{
tree scope = TREE_OPERAND (sr, 0);
if (TREE_CODE (scope) == NAMESPACE_DECL)
{
push_decl_namespace (scope);
TREE_COMPLEXITY (sr) = -1;
}
else if (scope != current_class_type)
{
if (TREE_CODE (scope) == TYPENAME_TYPE)
{
scope = TREE_TYPE (scope);
TREE_OPERAND (sr, 0) = scope;
}
push_nested_class (scope, 3);
TREE_COMPLEXITY (sr) = current_class_depth;
}
}
tree
finish_base_specifier (access_specifier, base_class)
tree access_specifier;
tree base_class;
{
tree result;
if (base_class == error_mark_node)
{
error ("invalid base-class specification");
result = NULL_TREE;
}
else if (! is_aggr_type (base_class, 1))
result = NULL_TREE;
else
{
if (cp_type_quals (base_class) != 0)
{
error ("base class `%T' has cv qualifiers", base_class);
base_class = TYPE_MAIN_VARIANT (base_class);
}
result = build_tree_list (access_specifier, base_class);
}
return result;
}
void
check_multiple_declarators ()
{
if (at_function_scope_p ())
return;
if (PROCESSING_REAL_TEMPLATE_DECL_P ()
|| processing_explicit_instantiation
|| processing_specialization)
error ("multiple declarators in template declaration");
}
tree
finish_typeof (expr)
tree expr;
{
tree type;
if (processing_template_decl)
{
type = make_aggr_type (TYPEOF_TYPE);
TYPE_FIELDS (type) = expr;
return type;
}
if (TREE_CODE (expr) == OFFSET_REF)
expr = resolve_offset_ref (expr);
type = TREE_TYPE (expr);
if (!type || type == unknown_type_node)
{
error ("type of `%E' is unknown", expr);
return error_mark_node;
}
return type;
}
tree
finish_sizeof (t)
tree t;
{
if (processing_template_decl)
return build_min_nt (SIZEOF_EXPR, t);
return TYPE_P (t) ? cxx_sizeof (t) : expr_sizeof (t);
}
tree
finish_alignof (t)
tree t;
{
if (processing_template_decl)
return build_min_nt (ALIGNOF_EXPR, t);
return TYPE_P (t) ? cxx_alignof (t) : c_alignof_expr (t);
}
static void
cp_expand_stmt (t)
tree t;
{
switch (TREE_CODE (t))
{
case TRY_BLOCK:
genrtl_try_block (t);
break;
case EH_SPEC_BLOCK:
genrtl_eh_spec_block (t);
break;
case HANDLER:
genrtl_handler (t);
break;
case RETURN_INIT:
genrtl_named_return_value ();
break;
case USING_STMT:
break;
default:
abort ();
break;
}
}
static tree
simplify_aggr_init_exprs_r (tp, walk_subtrees, data)
tree *tp;
int *walk_subtrees ATTRIBUTE_UNUSED;
void *data ATTRIBUTE_UNUSED;
{
tree aggr_init_expr;
tree call_expr;
tree fn;
tree args;
tree slot;
tree type;
int copy_from_buffer_p;
aggr_init_expr = *tp;
if (TYPE_P (aggr_init_expr))
{
*walk_subtrees = 0;
return NULL_TREE;
}
else if (TREE_CODE (aggr_init_expr) != AGGR_INIT_EXPR)
return NULL_TREE;
fn = TREE_OPERAND (aggr_init_expr, 0);
args = TREE_OPERAND (aggr_init_expr, 1);
slot = TREE_OPERAND (aggr_init_expr, 2);
type = TREE_TYPE (aggr_init_expr);
if (AGGR_INIT_VIA_CTOR_P (aggr_init_expr))
{
cxx_mark_addressable (slot);
args = tree_cons (NULL_TREE,
build1 (ADDR_EXPR,
build_pointer_type (TREE_TYPE (slot)),
slot),
TREE_CHAIN (args));
}
call_expr = build (CALL_EXPR,
TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))),
fn, args, NULL_TREE);
TREE_SIDE_EFFECTS (call_expr) = 1;
copy_from_buffer_p = 0;
#ifdef PCC_STATIC_STRUCT_RETURN
if (!AGGR_INIT_VIA_CTOR_P (aggr_init_expr) && aggregate_value_p (type))
{
int old_ac = flag_access_control;
flag_access_control = 0;
call_expr = build_aggr_init (slot, call_expr,
DIRECT_BIND | LOOKUP_ONLYCONVERTING);
flag_access_control = old_ac;
copy_from_buffer_p = 1;
}
#endif
if (AGGR_INIT_VIA_CTOR_P (aggr_init_expr) || copy_from_buffer_p)
{
call_expr = build (COMPOUND_EXPR, type,
call_expr, slot);
TREE_SIDE_EFFECTS (call_expr) = 1;
}
TREE_CHAIN (call_expr) = TREE_CHAIN (aggr_init_expr);
*tp = call_expr;
return NULL_TREE;
}
static void
emit_associated_thunks (fn)
tree fn;
{
if (DECL_VIRTUAL_P (fn))
{
tree thunk;
for (thunk = DECL_THUNKS (fn); thunk; thunk = TREE_CHAIN (thunk))
use_thunk (thunk, 1);
}
}
void
expand_body (fn)
tree fn;
{
int saved_lineno;
const char *saved_input_filename;
tree fn_return_node_parent, fn_orig_return_type;
tree saved_function;
if (processing_template_decl
|| (DECL_LANG_SPECIFIC (fn)
&& DECL_TEMPLATE_INFO (fn)
&& uses_template_parms (DECL_TI_ARGS (fn))))
{
ggc_collect ();
return;
}
walk_tree_without_duplicates (&DECL_SAVED_TREE (fn),
simplify_aggr_init_exprs_r,
NULL);
if (maybe_clone_body (fn))
{
TREE_ASM_WRITTEN (fn) = 1;
return;
}
if (flag_syntax_only)
return;
if (
(DECL_INLINE (fn) || DECL_COMDAT (fn))
&& !flag_keep_inline_functions
&& !DECL_NEEDED_P (fn))
{
if (!DECL_EXTERNAL (fn))
{
DECL_NOT_REALLY_EXTERN (fn) = 1;
DECL_EXTERNAL (fn) = 1;
}
defer_fn (fn);
(*debug_hooks->deferred_inline_function) (fn);
return;
}
if (DECL_DECLARED_INLINE_P (fn))
import_export_decl (fn);
if (DECL_EXTERNAL (fn))
return;
if (flag_apple_kext && DECL_CONSTRUCTOR_P (fn))
{
tree this_var = DECL_ARGUMENTS (fn);
tree t = DECL_SAVED_TREE (fn);
fn_return_node_parent = NULL_TREE;
fn_orig_return_type = NULL_TREE;
while (t && t != error_mark_node)
{
if (TREE_CHAIN (t) == NULL)
{
TREE_CHAIN (t) = build_stmt (RETURN_STMT, this_var);
fn_return_node_parent = t;
break;
}
else
t = TREE_CHAIN (t);
}
DECL_RESULT (fn) = this_var;
if (!optimize)
TREE_ADDRESSABLE (DECL_RESULT (fn)) = 1;
fn_orig_return_type = TREE_TYPE (TREE_TYPE (fn));
TREE_TYPE (TREE_TYPE (fn)) = TREE_TYPE (DECL_RESULT (fn));
}
saved_lineno = lineno;
saved_input_filename = input_filename;
saved_function = current_function_decl;
lineno = DECL_SOURCE_LINE (fn);
input_filename = DECL_SOURCE_FILE (fn);
current_function_decl = fn;
timevar_push (TV_INTEGRATION);
optimize_function (fn);
timevar_pop (TV_INTEGRATION);
timevar_push (TV_EXPAND);
genrtl_start_function (fn);
current_function_is_thunk = DECL_THUNK_P (fn);
#ifdef CHECK_TRIVIAL_FUNCTION
CHECK_TRIVIAL_FUNCTION (fn);
#endif
expand_stmt (DECL_SAVED_TREE (fn));
my_friendly_assert (stmts_are_full_exprs_p (), 19990831);
lineno = STMT_LINENO (DECL_SAVED_TREE (fn));
genrtl_finish_function (fn);
if (dump_enabled_p (TDI_all))
;
else if (DECL_INLINE (fn) && flag_inline_trees)
;
else
DECL_SAVED_TREE (fn) = NULL_TREE;
current_function_decl = saved_function;
lineno = saved_lineno;
input_filename = saved_input_filename;
extract_interface_info ();
if (flag_apple_kext && DECL_CONSTRUCTOR_P (fn))
{
if (fn_return_node_parent != NULL_TREE)
TREE_CHAIN (fn_return_node_parent) = NULL;
TREE_TYPE (TREE_TYPE (fn)) = fn_orig_return_type;
}
timevar_pop (TV_EXPAND);
emit_associated_thunks (fn);
}
tree
nullify_returns_r (tp, walk_subtrees, data)
tree *tp;
int *walk_subtrees;
void *data;
{
tree nrv = (tree) data;
if (TYPE_P (*tp))
*walk_subtrees = 0;
else if (TREE_CODE (*tp) == RETURN_STMT)
RETURN_STMT_EXPR (*tp) = NULL_TREE;
else if (TREE_CODE (*tp) == CLEANUP_STMT
&& CLEANUP_DECL (*tp) == nrv)
CLEANUP_EH_ONLY (*tp) = 1;
return NULL_TREE;
}
static void
genrtl_start_function (fn)
tree fn;
{
current_function_decl = fn;
init_function_start (fn, DECL_SOURCE_FILE (fn), DECL_SOURCE_LINE (fn));
expanding_p = 1;
immediate_size_expand = 0;
cfun->x_dont_save_pending_sizes_p = 1;
announce_function (fn);
my_friendly_assert (!DECL_PENDING_INLINE_P (fn), 20000911);
if (DECL_SAVED_FUNCTION_DATA (fn))
{
*cp_function_chain = *DECL_SAVED_FUNCTION_DATA (fn);
cfun->x_whole_function_mode_p = 1;
if (!current_function_cannot_inline)
current_function_cannot_inline = cp_function_chain->cannot_inline;
if (! DECL_INLINE (fn))
DECL_SAVED_FUNCTION_DATA (fn) = NULL;
}
++function_depth;
expand_function_start (fn, 0);
if (DECL_MAIN_P (fn))
expand_main_function ();
if (current_function_return_value)
COPY_DECL_RTL (DECL_RESULT (fn), current_function_return_value);
}
static void
genrtl_finish_function (fn)
tree fn;
{
tree t;
#if 0
if (write_symbols != NO_DEBUG)
{
tree ttype = target_type (fntype);
tree parmdecl;
if (IS_AGGR_TYPE (ttype))
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))
note_debug_info_needed (ttype);
}
}
#endif
do_pending_stack_adjust ();
if (DECL_NAME (DECL_RESULT (fn)))
emit_jump (return_label);
immediate_size_expand = 1;
if (lang_expand_function_end)
(*lang_expand_function_end) ();
expand_function_end (input_filename, lineno, 0);
if (function_depth > 1)
ggc_push_context ();
DECL_DEFER_OUTPUT (fn) = 0;
rest_of_compilation (fn);
if (function_depth > 1)
ggc_pop_context ();
#if 0
if (ctype && TREE_ASM_WRITTEN (fn))
note_debug_info_needed (ctype);
#endif
if (DECL_STATIC_CONSTRUCTOR (fn))
static_ctors = tree_cons (NULL_TREE, fn, static_ctors);
if (DECL_STATIC_DESTRUCTOR (fn))
static_dtors = tree_cons (NULL_TREE, fn, static_dtors);
--function_depth;
my_friendly_assert (!DECL_SAVED_INSNS (fn), 20010903);
walk_tree_without_duplicates (&DECL_SAVED_TREE (fn),
clear_decl_rtl,
NULL);
for (t = DECL_ARGUMENTS (fn); t; t = TREE_CHAIN (t))
{
SET_DECL_RTL (t, NULL_RTX);
DECL_INCOMING_RTL (t) = NULL_RTX;
}
if (!(flag_inline_trees && DECL_INLINE (fn)))
DECL_INITIAL (fn) = error_mark_node;
current_function_decl = NULL_TREE;
}
static tree
clear_decl_rtl (tp, walk_subtrees, data)
tree *tp;
int *walk_subtrees ATTRIBUTE_UNUSED;
void *data ATTRIBUTE_UNUSED;
{
if (nonstatic_local_decl_p (*tp))
SET_DECL_RTL (*tp, NULL_RTX);
return NULL_TREE;
}
void
init_cp_semantics ()
{
lang_expand_stmt = cp_expand_stmt;
}