c-common.c (c_safe_from_p, [...]): Deleted.

2004-06-26  Richard Kenner  <kenner@vlsi1.ultra.nyu.edu>

        * c-common.c (c_safe_from_p, c_walk_subtrees): Deleted.
        * c-common.def (DECL_STMT): Remove.
        * c-common.h (DECL_STMT_DECL): Deleted.
        (COMPOUNT_LITERAL_EXPR_DECL): Use DECL_EXPR_DECL.
        (c_safe_from_p, c_walk_subtrees): Deleted.
        * c-decl.c, c-parse.in, c-pretty-print.c: DECL_STMT now DECL_EXPR.
        * c-dump.c (c_dump_tree, case DECL_STMT): Deleted.
        * c-gimplify.c (gimplify_decl_stmt): Deleted.
        (gimplify_compound_literal_expr): Use DECL_EXPR_DECL
        and gimplify_and_add.
        (c_gimplify_expr, case DECL_EXPR): New case.
        (c_gimplify_expr, case DECL_STMT): Deleted.
        * c-lang.c (LANG_HOOKS_SAFE_FROM_P): Likewise.
        (LANG_HOOKS_TREE_INLINING_WALK_SUBTREES): Likewise.
        * expr.c (safe_from_p, case 's'): New case.
        * gimplify.c (gimplify_decl_expr): New function.
        (gimplify_expr, case DECL_EXPR): New case.
        * tree-inline.c (walk_tree): Walk into all fields of a type and
        decl only if they are in a DECL_EXPR.
        (mark_local_for_remap_r): Minor code cleanup.
        * tree-outof-ssa.c (discover_nonconstant_array_refs_r): Add else.
        * tree.c (has_cleanups, case DECL_EXPR): New case.
        * tree.def (DECL_EXPR): New code.
        * tree.h (DECL_EXPR_DECL): New macro.

        * objc/objc-lang.c (LANG_HOOKS_SAFE_FROM_P): Deleted.

From-SVN: r83721
This commit is contained in:
Richard Kenner 2004-06-26 21:11:23 +00:00 committed by Richard Kenner
parent 6573a10434
commit 350fae6628
30 changed files with 273 additions and 337 deletions

View File

@ -3718,28 +3718,6 @@ c_expand_expr (tree exp, rtx target, enum machine_mode tmode,
}
}
/* Hook used by safe_from_p to handle language-specific tree codes. */
int
c_safe_from_p (rtx target, tree exp)
{
/* We can see statements here when processing the body of a
statement-expression. For a declaration statement declaring a
variable, look at the variable's initializer. */
if (TREE_CODE (exp) == DECL_STMT)
{
tree decl = DECL_STMT_DECL (exp);
if (TREE_CODE (decl) == VAR_DECL
&& DECL_INITIAL (decl)
&& !safe_from_p (target, DECL_INITIAL (decl), /*top_p=*/0))
return 0;
}
/* Assume everything else is safe. */
return 1;
}
/* Hook used by unsafe_for_reeval to handle language-specific tree codes. */
int
@ -5125,53 +5103,6 @@ check_function_arguments_recurse (void (*callback)
(*callback) (ctx, param, param_num);
}
/* C implementation of lang_hooks.tree_inlining.walk_subtrees. Tracks the
locus from EXPR_LOCUS and handles DECL_STMT specially. */
tree
c_walk_subtrees (tree *tp, int *walk_subtrees_p ATTRIBUTE_UNUSED,
walk_tree_fn func, void *data, void *htab)
{
enum tree_code code = TREE_CODE (*tp);
location_t save_locus;
tree result;
#define WALK_SUBTREE(NODE) \
do \
{ \
result = walk_tree (&(NODE), func, data, htab); \
if (result) goto out; \
} \
while (0)
if (code != DECL_STMT)
return NULL_TREE;
/* Set input_location here so we get the right instantiation context
if we call instantiate_decl from inlinable_function_p. */
save_locus = input_location;
if (EXPR_LOCUS (*tp))
input_location = *EXPR_LOCUS (*tp);
/* Walk the DECL_INITIAL and DECL_SIZE. We don't want to walk
into declarations that are just mentioned, rather than
declared; they don't really belong to this part of the tree.
And, we can see cycles: the initializer for a declaration can
refer to the declaration itself. */
WALK_SUBTREE (DECL_INITIAL (DECL_STMT_DECL (*tp)));
WALK_SUBTREE (DECL_SIZE (DECL_STMT_DECL (*tp)));
WALK_SUBTREE (DECL_SIZE_UNIT (DECL_STMT_DECL (*tp)));
WALK_SUBTREE (TREE_CHAIN (*tp));
*walk_subtrees_p = 0;
/* We didn't find what we were looking for. */
out:
input_location = save_locus;
return result;
#undef WALK_SUBTREE
}
/* Function to help qsort sort FIELD_DECLs by name order. */
int

View File

@ -33,10 +33,6 @@ DEFTREECODE (ALIGNOF_EXPR, "alignof_expr", '1', 1)
obtain the expression. */
DEFTREECODE (EXPR_STMT, "expr_stmt", 'e', 1)
/* Used to represent a local declaration. The operand is
DECL_STMT_DECL. */
DEFTREECODE (DECL_STMT, "decl_stmt", 'e', 1)
/* Used to represent a `for' statement. The operands are
FOR_INIT_STMT, FOR_COND, FOR_EXPR, and FOR_BODY, respectively. */
DEFTREECODE (FOR_STMT, "for_stmt", 'e', 4)

View File

@ -733,10 +733,6 @@ extern void finish_file (void);
#define SWITCH_TYPE(NODE) TREE_OPERAND (SWITCH_STMT_CHECK (NODE), 2)
/* DECL_STMT accessor. This gives access to the DECL associated with
the given declaration statement. */
#define DECL_STMT_DECL(NODE) TREE_OPERAND (DECL_STMT_CHECK (NODE), 0)
/* STMT_EXPR accessor. */
#define STMT_EXPR_STMT(NODE) TREE_OPERAND (STMT_EXPR_CHECK (NODE), 0)
@ -748,7 +744,7 @@ extern void finish_file (void);
#define COMPOUND_LITERAL_EXPR_DECL_STMT(NODE) \
TREE_OPERAND (COMPOUND_LITERAL_EXPR_CHECK (NODE), 0)
#define COMPOUND_LITERAL_EXPR_DECL(NODE) \
DECL_STMT_DECL (COMPOUND_LITERAL_EXPR_DECL_STMT (NODE))
DECL_EXPR_DECL (COMPOUND_LITERAL_EXPR_DECL_STMT (NODE))
#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) SYM,
@ -761,7 +757,7 @@ enum c_tree_code {
#undef DEFTREECODE
#define c_common_stmt_codes \
EXPR_STMT, DECL_STMT, FOR_STMT, \
EXPR_STMT, FOR_STMT, \
WHILE_STMT, DO_STMT, \
BREAK_STMT, CONTINUE_STMT, SWITCH_STMT
@ -844,8 +840,6 @@ extern int vector_types_convertible_p (tree t1, tree t2);
extern rtx c_expand_expr (tree, rtx, enum machine_mode, int, rtx *);
extern int c_safe_from_p (rtx, tree);
extern int c_staticp (tree);
extern int c_common_unsafe_for_reeval (tree);
@ -872,8 +866,6 @@ extern void dump_time_statistics (void);
extern bool c_dump_tree (void *, tree);
extern tree c_walk_subtrees (tree*, int*, walk_tree_fn, void*, void*);
extern void c_warn_unused_result (tree *);
extern void verify_sequence_points (tree);

View File

@ -2943,7 +2943,7 @@ finish_decl (tree decl, tree init, tree asmspec_tree)
}
if (TREE_CODE (decl) != FUNCTION_DECL)
add_stmt (build_stmt (DECL_STMT, decl));
add_stmt (build_stmt (DECL_EXPR, decl));
}
if (!DECL_FILE_SCOPE_P (decl))
@ -2970,7 +2970,7 @@ finish_decl (tree decl, tree init, tree asmspec_tree)
{
if (!DECL_FILE_SCOPE_P (decl)
&& variably_modified_type_p (TREE_TYPE (decl)))
add_stmt (build_stmt (DECL_STMT, decl));
add_stmt (build_stmt (DECL_EXPR, decl));
rest_of_decl_compilation (decl, NULL, DECL_FILE_SCOPE_P (decl), 0);
}
@ -3072,7 +3072,7 @@ build_compound_literal (tree type, tree init)
{
/* We do not use start_decl here because we have a type, not a declarator;
and do not use finish_decl because the decl should be stored inside
the COMPOUND_LITERAL_EXPR rather than added elsewhere as a DECL_STMT. */
the COMPOUND_LITERAL_EXPR rather than added elsewhere as a DECL_EXPR. */
tree decl = build_decl (VAR_DECL, NULL_TREE, type);
tree complit;
tree stmt;
@ -3096,7 +3096,7 @@ build_compound_literal (tree type, tree init)
if (type == error_mark_node || !COMPLETE_TYPE_P (type))
return error_mark_node;
stmt = build_stmt (DECL_STMT, decl);
stmt = build_stmt (DECL_EXPR, decl);
complit = build1 (COMPOUND_LITERAL_EXPR, TREE_TYPE (decl), stmt);
TREE_SIDE_EFFECTS (complit) = 1;

View File

@ -60,11 +60,6 @@ c_dump_tree (void *dump_info, tree t)
dump_stmt (di, t);
break;
case DECL_STMT:
dump_stmt (di, t);
dump_child ("decl", DECL_STMT_DECL (t));
break;
case DO_STMT:
dump_stmt (di, t);
dump_child ("body", DO_BODY (t));

View File

@ -465,90 +465,17 @@ gimplify_switch_stmt (tree *stmt_p)
return GS_ALL_DONE;
}
/* Gimplifies a DECL_STMT node *STMT_P by making any necessary allocation
and initialization explicit. */
static enum gimplify_status
gimplify_decl_stmt (tree *stmt_p)
{
tree stmt = *stmt_p;
tree decl = DECL_STMT_DECL (stmt);
*stmt_p = NULL_TREE;
if (TREE_TYPE (decl) == error_mark_node)
return GS_ERROR;
if (TREE_CODE (decl) == TYPE_DECL)
gimplify_type_sizes (TREE_TYPE (decl), stmt_p);
else if (TREE_CODE (decl) == VAR_DECL && !DECL_EXTERNAL (decl))
{
tree init = DECL_INITIAL (decl);
if (!TREE_CONSTANT (DECL_SIZE (decl)))
{
/* This is a variable-sized decl. Simplify its size and mark it
for deferred expansion. Note that mudflap depends on the format
of the emitted code: see mx_register_decls(). */
tree t, args;
gimplify_type_sizes (TREE_TYPE (decl), stmt_p);
gimplify_one_sizepos (&DECL_SIZE (decl), stmt_p);
gimplify_one_sizepos (&DECL_SIZE_UNIT (decl), stmt_p);
args = tree_cons (NULL, DECL_SIZE_UNIT (decl), NULL);
t = build_fold_addr_expr (decl);
args = tree_cons (NULL, t, args);
t = implicit_built_in_decls[BUILT_IN_STACK_ALLOC];
t = build_function_call_expr (t, args);
gimplify_and_add (t, stmt_p);
DECL_DEFER_OUTPUT (decl) = 1;
}
if (init && init != error_mark_node)
{
if (!TREE_STATIC (decl))
{
/* Do not warn about int x = x; as it is a GCC extension
to turn off this warning but only if warn_init_self
is zero. */
if (init == decl && !warn_init_self)
TREE_NO_WARNING (decl) = 1;
DECL_INITIAL (decl) = NULL_TREE;
init = build (MODIFY_EXPR, void_type_node, decl, init);
gimplify_and_add (init, stmt_p);
}
else
/* We must still examine initializers for static variables
as they may contain a label address. */
walk_tree (&init, force_labels_r, NULL, NULL);
}
/* This decl isn't mentioned in the enclosing block, so add it to the
list of temps. FIXME it seems a bit of a kludge to say that
anonymous artificial vars aren't pushed, but everything else is. */
if (DECL_ARTIFICIAL (decl) && DECL_NAME (decl) == NULL_TREE)
gimple_add_tmp_var (decl);
}
return GS_ALL_DONE;
}
/* Gimplification of expression trees. */
/* Gimplify a C99 compound literal expression. This just means adding the
DECL_STMT before the current EXPR_STMT and using its anonymous decl
DECL_EXPR before the current EXPR_STMT and using its anonymous decl
instead. */
static enum gimplify_status
gimplify_compound_literal_expr (tree *expr_p, tree *pre_p)
{
tree decl_s = COMPOUND_LITERAL_EXPR_DECL_STMT (*expr_p);
tree decl = DECL_STMT_DECL (decl_s);
tree decl = DECL_EXPR_DECL (decl_s);
/* This decl isn't mentioned in the enclosing block, so add it to the
list of temps. FIXME it seems a bit of a kludge to say that
@ -556,8 +483,7 @@ gimplify_compound_literal_expr (tree *expr_p, tree *pre_p)
if (DECL_NAME (decl) == NULL_TREE)
gimple_add_tmp_var (decl);
gimplify_decl_stmt (&decl_s);
append_to_statement_list (decl_s, pre_p);
gimplify_and_add (decl_s, pre_p);
*expr_p = decl;
return GS_OK;
}
@ -571,6 +497,19 @@ c_gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p ATTRIBUTE_UNUSED)
switch (code)
{
case DECL_EXPR:
/* This is handled mostly by gimplify.c, but we have to deal with
not warning about int x = x; as it is a GCC extension to turn off
this warning but only if warn_init_self is zero. */
if (TREE_CODE (DECL_EXPR_DECL (*expr_p)) == VAR_DECL
&& !DECL_EXTERNAL (DECL_EXPR_DECL (*expr_p))
&& !TREE_STATIC (DECL_EXPR_DECL (*expr_p))
&& (DECL_INITIAL (DECL_EXPR_DECL (*expr_p))
== DECL_EXPR_DECL (*expr_p))
&& !warn_init_self)
TREE_NO_WARNING (DECL_EXPR_DECL (*expr_p)) = 1;
return GS_UNHANDLED;
case COMPOUND_LITERAL_EXPR:
return gimplify_compound_literal_expr (expr_p, pre_p);
@ -589,9 +528,6 @@ c_gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p ATTRIBUTE_UNUSED)
case EXPR_STMT:
return gimplify_expr_stmt (expr_p);
case DECL_STMT:
return gimplify_decl_stmt (expr_p);
case CONTINUE_STMT:
*expr_p = build_bc_goto (bc_continue);
return GS_ALL_DONE;

View File

@ -60,8 +60,6 @@ enum c_language_kind c_language = clk_c;
#define LANG_HOOKS_POST_OPTIONS c_common_post_options
#undef LANG_HOOKS_GET_ALIAS_SET
#define LANG_HOOKS_GET_ALIAS_SET c_common_get_alias_set
#undef LANG_HOOKS_SAFE_FROM_P
#define LANG_HOOKS_SAFE_FROM_P c_safe_from_p
#undef LANG_HOOKS_EXPAND_EXPR
#define LANG_HOOKS_EXPAND_EXPR c_expand_expr
#undef LANG_HOOKS_EXPAND_DECL
@ -103,9 +101,6 @@ enum c_language_kind c_language = clk_c;
#undef LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE
#define LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE c_common_format_attribute_table
#undef LANG_HOOKS_TREE_INLINING_WALK_SUBTREES
#define LANG_HOOKS_TREE_INLINING_WALK_SUBTREES \
c_walk_subtrees
#undef LANG_HOOKS_TREE_INLINING_CANNOT_INLINE_TREE_FN
#define LANG_HOOKS_TREE_INLINING_CANNOT_INLINE_TREE_FN \
c_cannot_inline_tree_fn

View File

@ -1537,7 +1537,7 @@ nested_function:
add_stmt ($6);
finish_function ();
pop_function_context ();
add_stmt (build_stmt (DECL_STMT, decl)); }
add_stmt (build_stmt (DECL_EXPR, decl)); }
;
notype_nested_function:
@ -1567,7 +1567,7 @@ notype_nested_function:
add_stmt ($6);
finish_function ();
pop_function_context ();
add_stmt (build_stmt (DECL_STMT, decl)); }
add_stmt (build_stmt (DECL_EXPR, decl)); }
;
/* Any kind of declarator (thus, all declarators allowed
@ -2016,7 +2016,7 @@ label_decl:
{
tree label = declare_label (TREE_VALUE (link));
C_DECLARED_LABEL_FLAG (label) = 1;
add_stmt (build_stmt (DECL_STMT, label));
add_stmt (build_stmt (DECL_EXPR, label));
}
}
;

View File

@ -261,6 +261,13 @@ pp_c_pointer (c_pretty_printer *pp, tree t)
pp_c_type_qualifier_list (pp, t);
break;
/* ??? This node is now in GENERIC and so shouldn't be here. But
we'll fix that later. */
case DECL_EXPR:
pp_declaration (pp, DECL_EXPR_DECL (t));
pp_needs_newline (pp) = true;
break;
default:
pp_unsupported_tree (pp, t);
}
@ -1982,11 +1989,6 @@ pp_c_statement (c_pretty_printer *pp, tree stmt)
pp_needs_newline (pp) = true;
break;
case DECL_STMT:
pp_declaration (pp, DECL_STMT_DECL (stmt));
pp_needs_newline (pp) = true;
break;
default:
dump_generic_node (pp_base (pp), stmt, pp_indentation (pp), 0, true);
break;

View File

@ -1,3 +1,11 @@
2004-06-26 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
* call.c, cp-tree.h, cxx-pretty-print.c, decl.c, decl2.c:
Rename DECL_STMT to DECL_EXPR.
* init.c, name-lookup.c, parser.c, pt.c, semantics.c: Likewise.
* cp-lang.c (LANG_HOOKS_SAFE_FROM_P): Deleted.
* tree.c (cp_walk_subtrees): Don't call c_walk_subtrees.
2004-06-26 Jan Hubicka <jh@suse.cz>
PR C++/14865

View File

@ -6468,7 +6468,7 @@ initialize_reference (tree type, tree expr, tree decl, tree *cleanup)
init = build (INIT_EXPR, type, var, expr);
if (at_function_scope_p ())
{
add_decl_stmt (var);
add_decl_expr (var);
*cleanup = cxx_maybe_build_cleanup (var);
/* We must be careful to destroy the temporary only

View File

@ -72,8 +72,6 @@ static void cxx_initialize_diagnostics (diagnostic_context *);
#define LANG_HOOKS_EXPAND_EXPR cxx_expand_expr
#undef LANG_HOOKS_EXPAND_DECL
#define LANG_HOOKS_EXPAND_DECL c_expand_decl
#undef LANG_HOOKS_SAFE_FROM_P
#define LANG_HOOKS_SAFE_FROM_P c_safe_from_p
#undef LANG_HOOKS_PARSE_FILE
#define LANG_HOOKS_PARSE_FILE c_common_parse_file
#undef LANG_HOOKS_DUP_LANG_SPECIFIC_DECL

View File

@ -4147,7 +4147,7 @@ extern void pop_to_parent_deferring_access_checks (void);
extern void perform_deferred_access_checks (void);
extern void perform_or_defer_access_check (tree, tree);
extern void init_cp_semantics (void);
extern void add_decl_stmt (tree);
extern void add_decl_expr (tree);
extern tree finish_expr_stmt (tree);
extern tree begin_if_stmt (void);
extern void finish_if_stmt_cond (tree, tree);

View File

@ -1446,7 +1446,7 @@ pp_cxx_template_argument_list (cxx_pretty_printer *pp, tree t)
static void
pp_cxx_exception_declaration (cxx_pretty_printer *pp, tree t)
{
t = DECL_STMT_DECL (t);
t = DECL_EXPR_DECL (t);
pp_cxx_type_specifier_seq (pp, t);
if (TYPE_P (t))
pp_cxx_abstract_declarator (pp, t);

View File

@ -3873,8 +3873,8 @@ grok_reference_init (tree decl, tree type, tree init, tree *cleanup)
/* 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
of the reference. If so, a DECL_EXPR for the temporary will be
added just after the DECL_EXPR 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. */
@ -4527,7 +4527,7 @@ make_rtl_for_nonlocal_decl (tree decl, tree init, const char* asmspec)
return;
/* We defer emission of local statics until the corresponding
DECL_STMT is expanded. */
DECL_EXPR is expanded. */
defer_p = DECL_FUNCTION_SCOPE_P (decl) || DECL_VIRTUAL_P (decl);
/* We try to defer namespace-scope static constants so that they are
@ -4702,7 +4702,7 @@ cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags)
{
/* Add this declaration to the statement-tree. */
if (at_function_scope_p ())
add_decl_stmt (decl);
add_decl_expr (decl);
if (init && DECL_INITIAL (decl))
DECL_INITIAL (decl) = init;
@ -4808,10 +4808,10 @@ cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags)
}
/* Add this declaration to the statement-tree. This needs to happen
after the call to check_initializer so that the DECL_STMT for a
reference temp is added before the DECL_STMT for the reference itself. */
after the call to check_initializer so that the DECL_EXPR for a
reference temp is added before the DECL_EXPR for the reference itself. */
if (at_function_scope_p ())
add_decl_stmt (decl);
add_decl_expr (decl);
if (TREE_CODE (decl) == VAR_DECL)
layout_var_decl (decl);

View File

@ -1227,7 +1227,7 @@ finish_anon_union (tree anon_union_decl)
pushdecl (anon_union_decl);
if (building_stmt_tree ()
&& at_function_scope_p ())
add_decl_stmt (anon_union_decl);
add_decl_expr (anon_union_decl);
else if (!processing_template_decl)
rest_of_decl_compilation (anon_union_decl, NULL,
toplevel_bindings_p (), at_eof);

View File

@ -2360,7 +2360,7 @@ get_temp_regvar (tree type, tree init)
tree decl;
decl = create_temporary_var (type);
add_decl_stmt (decl);
add_decl_expr (decl);
finish_expr_stmt (build_modify_expr (decl, INIT_EXPR, init));

View File

@ -2269,7 +2269,7 @@ do_local_using_decl (tree decl, tree scope, tree name)
if (building_stmt_tree ()
&& at_function_scope_p ())
add_decl_stmt (decl);
add_decl_expr (decl);
oldval = lookup_name_current_level (name);
oldtype = lookup_type_current_level (name);

View File

@ -10695,7 +10695,7 @@ cp_parser_init_declarator (cp_parser* parser,
/* Leave the SCOPE, now that we have processed the initializer. It
is important to do this before calling cp_finish_decl because it
makes decisions about whether to create DECL_STMTs or not based
makes decisions about whether to create DECL_EXPRs or not based
on the current scope. */
if (pop_p)
pop_scope (scope);

View File

@ -4587,7 +4587,7 @@ struct pair_fn_data
/* Called from for_each_template_parm via walk_tree. */
static tree
for_each_template_parm_r (tree* tp, int* walk_subtrees, void* d)
for_each_template_parm_r (tree *tp, int *walk_subtrees, void *d)
{
tree t = *tp;
struct pair_fn_data *pfd = (struct pair_fn_data *) d;
@ -7764,12 +7764,12 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
args, complain, in_decl));
break;
case DECL_STMT:
case DECL_EXPR:
{
tree decl;
tree init;
decl = DECL_STMT_DECL (t);
decl = DECL_EXPR_DECL (t);
if (TREE_CODE (decl) == LABEL_DECL)
finish_label_decl (DECL_NAME (decl));
else if (TREE_CODE (decl) == USING_DECL)
@ -7825,7 +7825,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
}
}
/* A DECL_STMT can also be used as an expression, in the condition
/* A DECL_EXPR can also be used as an expression, in the condition
clause of an if/for/while construct. */
return decl;
}

View File

@ -316,9 +316,9 @@ maybe_cleanup_point_expr (tree expr)
/* Create a declaration statement for the declaration given by the DECL. */
void
add_decl_stmt (tree decl)
add_decl_expr (tree decl)
{
tree r = build_stmt (DECL_STMT, decl);
tree r = build_stmt (DECL_EXPR, decl);
if (DECL_INITIAL (decl))
r = maybe_cleanup_point_expr (r);
add_stmt (r);
@ -382,7 +382,7 @@ push_cleanup (tree decl, tree cleanup, bool eh_only)
/* Begin a conditional that might contain a declaration. When generating
normal code, we want the declaration to appear before the statement
containing the conditional. When generating template code, we want the
conditional to be rendered as the raw DECL_STMT. */
conditional to be rendered as the raw DECL_EXPR. */
static void
begin_cond (tree *cond_p)
@ -399,7 +399,7 @@ finish_cond (tree *cond_p, tree expr)
if (processing_template_decl)
{
tree cond = pop_stmt_list (*cond_p);
if (TREE_CODE (cond) == DECL_STMT)
if (TREE_CODE (cond) == DECL_EXPR)
expr = cond;
}
*cond_p = expr;
@ -1141,7 +1141,7 @@ void
finish_label_decl (tree name)
{
tree decl = declare_local_label (name);
add_decl_stmt (decl);
add_decl_expr (decl);
}
/* When DECL goes out of scope, make sure that CLEANUP is executed. */
@ -2950,10 +2950,10 @@ finalize_nrv_r (tree* tp, int* walk_subtrees, void* data)
else if (TREE_CODE (*tp) == CLEANUP_STMT
&& CLEANUP_DECL (*tp) == dp->var)
CLEANUP_EH_ONLY (*tp) = 1;
/* Replace the DECL_STMT for the NRV with an initialization of the
/* Replace the DECL_EXPR for the NRV with an initialization of the
RESULT_DECL, if needed. */
else if (TREE_CODE (*tp) == DECL_STMT
&& DECL_STMT_DECL (*tp) == dp->var)
else if (TREE_CODE (*tp) == DECL_EXPR
&& DECL_EXPR_DECL (*tp) == dp->var)
{
tree init;
if (DECL_INITIAL (dp->var)

View File

@ -1962,14 +1962,11 @@ cp_build_type_attribute_variant (tree type, tree attributes)
}
/* Apply FUNC to all language-specific sub-trees of TP in a pre-order
traversal. Called from walk_tree(). */
traversal. Called from walk_tree. */
tree
cp_walk_subtrees (tree* tp,
int* walk_subtrees_p,
walk_tree_fn func,
void* data,
void* htab)
cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func,
void *data, void *htab)
{
enum tree_code code = TREE_CODE (*tp);
location_t save_locus;
@ -2030,7 +2027,7 @@ cp_walk_subtrees (tree* tp,
default:
input_location = save_locus;
return c_walk_subtrees (tp, walk_subtrees_p, func, data, htab);
return NULL_TREE;
}
/* We didn't find what we were looking for. */
@ -2201,7 +2198,7 @@ init_tree (void)
list_hash_table = htab_create_ggc (31, list_hash, list_hash_eq, NULL);
}
/* Called via walk_tree. If *TP points to a DECL_STMT for a local
/* Called via walk_tree. If *TP points to a DECL_EXPR for a local
declaration, copies the declaration and enters it in the splay_tree
pointed to by DATA (which is really a `splay_tree *'). */
@ -2215,9 +2212,9 @@ mark_local_for_remap_r (tree* tp,
tree decl;
if (TREE_CODE (t) == DECL_STMT
&& nonstatic_local_decl_p (DECL_STMT_DECL (t)))
decl = DECL_STMT_DECL (t);
if (TREE_CODE (t) == DECL_EXPR
&& nonstatic_local_decl_p (DECL_EXPR_DECL (t)))
decl = DECL_EXPR_DECL (t);
else if (TREE_CODE (t) == LABEL_EXPR)
decl = LABEL_EXPR_LABEL (t);
else if (TREE_CODE (t) == TARGET_EXPR

View File

@ -6002,6 +6002,14 @@ safe_from_p (rtx x, tree exp, int top_p)
else
return 0;
case 's':
/* The only case we look at here is the DECL_INITIAL inside a
DECL_EXPR. */
return (TREE_CODE (exp) != DECL_EXPR
|| TREE_CODE (DECL_EXPR_DECL (exp)) != VAR_DECL
|| !DECL_INITIAL (DECL_EXPR_DECL (exp))
|| safe_from_p (x, DECL_INITIAL (DECL_EXPR_DECL (exp)), 0));
case '2':
case '<':
if (!safe_from_p (x, TREE_OPERAND (exp, 1), 0))

View File

@ -660,7 +660,7 @@ copy_if_shared_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
/* Special-case BIND_EXPR. We should never be copying these, therefore
we can omit examining BIND_EXPR_VARS. Which also avoids problems with
double processing of the DECL_INITIAL, which could be seen via both
the BIND_EXPR_VARS and a DECL_STMT. */
the BIND_EXPR_VARS and a DECL_EXPR. */
else if (code == BIND_EXPR)
{
if (TREE_VISITED (t))
@ -1004,6 +1004,72 @@ gimplify_return_expr (tree stmt, tree *pre_p)
return GS_ALL_DONE;
}
/* Gimplifies a DECL_EXPR node *STMT_P by making any necessary allocation
and initialization explicit. */
static enum gimplify_status
gimplify_decl_expr (tree *stmt_p)
{
tree stmt = *stmt_p;
tree decl = DECL_EXPR_DECL (stmt);
*stmt_p = NULL_TREE;
if (TREE_TYPE (decl) == error_mark_node)
return GS_ERROR;
else if (TREE_CODE (decl) == TYPE_DECL)
gimplify_type_sizes (TREE_TYPE (decl), stmt_p);
else if (TREE_CODE (decl) == VAR_DECL && !DECL_EXTERNAL (decl))
{
tree init = DECL_INITIAL (decl);
if (!TREE_CONSTANT (DECL_SIZE (decl)))
{
/* This is a variable-sized decl. Simplify its size and mark it
for deferred expansion. Note that mudflap depends on the format
of the emitted code: see mx_register_decls(). */
tree t, args;
gimplify_type_sizes (TREE_TYPE (decl), stmt_p);
gimplify_one_sizepos (&DECL_SIZE (decl), stmt_p);
gimplify_one_sizepos (&DECL_SIZE_UNIT (decl), stmt_p);
args = tree_cons (NULL, DECL_SIZE_UNIT (decl), NULL);
t = build_fold_addr_expr (decl);
args = tree_cons (NULL, t, args);
t = implicit_built_in_decls[BUILT_IN_STACK_ALLOC];
t = build_function_call_expr (t, args);
gimplify_and_add (t, stmt_p);
DECL_DEFER_OUTPUT (decl) = 1;
}
if (init && init != error_mark_node)
{
if (!TREE_STATIC (decl))
{
DECL_INITIAL (decl) = NULL_TREE;
init = build (MODIFY_EXPR, void_type_node, decl, init);
gimplify_and_add (init, stmt_p);
}
else
/* We must still examine initializers for static variables
as they may contain a label address. */
walk_tree (&init, force_labels_r, NULL, NULL);
}
/* This decl isn't mentioned in the enclosing block, so add it to the
list of temps. FIXME it seems a bit of a kludge to say that
anonymous artificial vars aren't pushed, but everything else is. */
if (DECL_ARTIFICIAL (decl) && DECL_NAME (decl) == NULL_TREE)
gimple_add_tmp_var (decl);
}
return GS_ALL_DONE;
}
/* Gimplify a LOOP_EXPR. Normally this just involves gimplifying the body
and replacing the LOOP_EXPR with goto, but if the loop contains an
EXIT_EXPR, we need to append a label for it to jump to. */
@ -3521,6 +3587,10 @@ gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p,
*expr_p = DECL_INITIAL (*expr_p);
break;
case DECL_EXPR:
ret = gimplify_decl_expr (expr_p);
break;
case EXC_PTR_EXPR:
/* FIXME make this a decl. */
ret = GS_ALL_DONE;

View File

@ -53,8 +53,6 @@ enum c_language_kind c_language = clk_objc;
#define LANG_HOOKS_POST_OPTIONS c_common_post_options
#undef LANG_HOOKS_GET_ALIAS_SET
#define LANG_HOOKS_GET_ALIAS_SET c_common_get_alias_set
#undef LANG_HOOKS_SAFE_FROM_P
#define LANG_HOOKS_SAFE_FROM_P c_safe_from_p
#undef LANG_HOOKS_PARSE_FILE
#define LANG_HOOKS_PARSE_FILE c_common_parse_file
#undef LANG_HOOKS_CLEAR_BINDING_STACK

View File

@ -2032,10 +2032,63 @@ walk_tree (tree *tp, walk_tree_fn func, void *data, void *htab_)
if (result || ! walk_subtrees)
return result;
if (code != EXIT_BLOCK_EXPR
&& code != SAVE_EXPR
&& code != BIND_EXPR
&& IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code)))
/* If this is a DECL_EXPR, walk into various fields of the type or variable
that it's defining. We only want to walk into these fields of a decl
or type in this case.
??? Precisely which fields of types that we are supposed to walk in
this case vs. the normal case aren't well defined. */
if (code == DECL_EXPR
&& TREE_CODE (DECL_EXPR_DECL (*tp)) != ERROR_MARK
&& TREE_CODE (TREE_TYPE (DECL_EXPR_DECL (*tp))) != ERROR_MARK)
{
tree decl = DECL_EXPR_DECL (*tp);
tree type = TREE_TYPE (decl);
/* Walk into fields of the DECL if it's not a type, then into fields
of the type in both cases. */
if (TREE_CODE (decl) != TYPE_DECL
&& TREE_CODE (decl) != FIELD_DECL && TREE_CODE (decl) != PARM_DECL)
{
WALK_SUBTREE (DECL_INITIAL (decl));
WALK_SUBTREE (DECL_SIZE (decl));
WALK_SUBTREE (DECL_SIZE_UNIT (decl));
}
/* First do the common fields via recursion, then the fields we only
do when we are declaring the type or object. */
WALK_SUBTREE (type);
WALK_SUBTREE (TYPE_SIZE (type));
WALK_SUBTREE (TYPE_SIZE_UNIT (type));
/* If this is a record type, also walk the fields. */
if (TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE
|| TREE_CODE (type) == QUAL_UNION_TYPE)
{
tree field;
for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
{
/* We'd like to look at the type of the field, but we can easily
get infinite recursion. So assume it's pointed to elsewhere
in the tree. Also, ignore things that aren't fields. */
if (TREE_CODE (field) != FIELD_DECL)
continue;
WALK_SUBTREE (DECL_FIELD_OFFSET (field));
WALK_SUBTREE (DECL_SIZE (field));
WALK_SUBTREE (DECL_SIZE_UNIT (field));
if (TREE_CODE (type) == QUAL_UNION_TYPE)
WALK_SUBTREE (DECL_QUALIFIER (field));
}
}
}
else if (code != EXIT_BLOCK_EXPR
&& code != SAVE_EXPR
&& code != BIND_EXPR
&& IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code)))
{
int i, len;
@ -2068,24 +2121,8 @@ walk_tree (tree *tp, walk_tree_fn func, void *data, void *htab_)
#endif
}
/* Look inside the sizes of decls, but we don't ever use the values for
FIELD_DECL and RESULT_DECL, so ignore them. */
else if (TREE_CODE_CLASS (code) == 'd'
&& code != FIELD_DECL && code != RESULT_DECL)
{
WALK_SUBTREE (DECL_SIZE (*tp));
WALK_SUBTREE (DECL_SIZE_UNIT (*tp));
WALK_SUBTREE_TAIL (TREE_TYPE (*tp));
}
else
{
if (TREE_CODE_CLASS (code) == 't')
{
WALK_SUBTREE (TYPE_SIZE (*tp));
WALK_SUBTREE (TYPE_SIZE_UNIT (*tp));
/* Also examine various special fields, below. */
}
/* Not one of the easy cases. We must explicitly go through the
children. */
switch (code)
@ -2107,12 +2144,6 @@ walk_tree (tree *tp, walk_tree_fn func, void *data, void *htab_)
above. */
break;
case POINTER_TYPE:
case REFERENCE_TYPE:
case COMPLEX_TYPE:
WALK_SUBTREE_TAIL (TREE_TYPE (*tp));
break;
case TREE_LIST:
WALK_SUBTREE (TREE_VALUE (*tp));
WALK_SUBTREE_TAIL (TREE_CHAIN (*tp));
@ -2140,66 +2171,6 @@ walk_tree (tree *tp, walk_tree_fn func, void *data, void *htab_)
case CONSTRUCTOR:
WALK_SUBTREE_TAIL (CONSTRUCTOR_ELTS (*tp));
case METHOD_TYPE:
WALK_SUBTREE (TYPE_METHOD_BASETYPE (*tp));
/* Fall through. */
case FUNCTION_TYPE:
WALK_SUBTREE (TREE_TYPE (*tp));
{
tree arg = TYPE_ARG_TYPES (*tp);
/* We never want to walk into default arguments. */
for (; arg; arg = TREE_CHAIN (arg))
WALK_SUBTREE (TREE_VALUE (arg));
}
break;
case RECORD_TYPE:
case UNION_TYPE:
case QUAL_UNION_TYPE:
{
tree field;
for (field = TYPE_FIELDS (*tp); field; field = TREE_CHAIN (field))
{
/* We would like to look at the type of the field, but we
can easily get infinite recursion. So assume it's
pointed to elsewhere in the tree. Also, ignore things that
aren't fields. */
if (TREE_CODE (field) != FIELD_DECL)
continue;
WALK_SUBTREE (DECL_FIELD_OFFSET (field));
WALK_SUBTREE (DECL_SIZE (field));
WALK_SUBTREE (DECL_SIZE_UNIT (field));
if (code == QUAL_UNION_TYPE)
WALK_SUBTREE (DECL_QUALIFIER (field));
}
}
break;
case ARRAY_TYPE:
/* Don't follow this nodes's type if a pointer for fear that we'll
have infinite recursion. Those types are uninteresting anyway. */
if (!POINTER_TYPE_P (TREE_TYPE (*tp))
&& TREE_CODE (TREE_TYPE (*tp)) != OFFSET_TYPE)
WALK_SUBTREE (TREE_TYPE (*tp));
WALK_SUBTREE_TAIL (TYPE_DOMAIN (*tp));
case BOOLEAN_TYPE:
case ENUMERAL_TYPE:
case INTEGER_TYPE:
case CHAR_TYPE:
case REAL_TYPE:
WALK_SUBTREE (TYPE_MIN_VALUE (*tp));
WALK_SUBTREE_TAIL (TYPE_MAX_VALUE (*tp));
case OFFSET_TYPE:
WALK_SUBTREE (TREE_TYPE (*tp));
WALK_SUBTREE_TAIL (TYPE_OFFSET_BASETYPE (*tp));
case EXIT_BLOCK_EXPR:
WALK_SUBTREE_TAIL (TREE_OPERAND (*tp, 1));
@ -2232,6 +2203,48 @@ walk_tree (tree *tp, walk_tree_fn func, void *data, void *htab_)
}
break;
case POINTER_TYPE:
case REFERENCE_TYPE:
case COMPLEX_TYPE:
WALK_SUBTREE_TAIL (TREE_TYPE (*tp));
break;
case METHOD_TYPE:
WALK_SUBTREE (TYPE_METHOD_BASETYPE (*tp));
/* Fall through. */
case FUNCTION_TYPE:
WALK_SUBTREE (TREE_TYPE (*tp));
{
tree arg;
/* We never want to walk into default arguments. */
for (arg = TYPE_ARG_TYPES (*tp); arg; arg = TREE_CHAIN (arg))
WALK_SUBTREE (TREE_VALUE (arg));
}
break;
case ARRAY_TYPE:
/* Don't follow this nodes's type if a pointer for fear that we'll
have infinite recursion. Those types are uninteresting anyway. */
if (!POINTER_TYPE_P (TREE_TYPE (*tp))
&& TREE_CODE (TREE_TYPE (*tp)) != OFFSET_TYPE)
WALK_SUBTREE (TREE_TYPE (*tp));
WALK_SUBTREE_TAIL (TYPE_DOMAIN (*tp));
case BOOLEAN_TYPE:
case ENUMERAL_TYPE:
case INTEGER_TYPE:
case CHAR_TYPE:
case REAL_TYPE:
WALK_SUBTREE (TYPE_MIN_VALUE (*tp));
WALK_SUBTREE_TAIL (TYPE_MAX_VALUE (*tp));
case OFFSET_TYPE:
WALK_SUBTREE (TREE_TYPE (*tp));
WALK_SUBTREE_TAIL (TYPE_OFFSET_BASETYPE (*tp));
default:
/* ??? This could be a language-defined node. We really should make
a hook for it, but right now just ignore it. */
@ -2358,34 +2371,20 @@ static tree
mark_local_for_remap_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
void *data)
{
tree t = *tp;
inline_data *id = (inline_data *) data;
tree decl;
/* Don't walk into types. */
if (TYPE_P (t))
if (TYPE_P (*tp))
*walk_subtrees = 0;
else if (TREE_CODE (*tp) == LABEL_EXPR)
{
*walk_subtrees = 0;
return NULL_TREE;
}
tree decl = TREE_OPERAND (*tp, 0);
if (TREE_CODE (t) == LABEL_EXPR)
decl = TREE_OPERAND (t, 0);
else
/* We don't need to handle anything else ahead of time. */
decl = NULL_TREE;
if (decl)
{
tree copy;
/* Make a copy. */
copy = copy_decl_for_inlining (decl,
DECL_CONTEXT (decl),
DECL_CONTEXT (decl));
/* Remember the copy. */
insert_decl_map (id, decl, copy);
/* Copy the decl and remember the copy. */
insert_decl_map (id, decl,
copy_decl_for_inlining (decl, DECL_CONTEXT (decl),
DECL_CONTEXT (decl)));
}
return NULL_TREE;

View File

@ -1763,7 +1763,7 @@ discover_nonconstant_array_refs_r (tree * tp, int *walk_subtrees,
if (TYPE_P (t) || DECL_P (t))
*walk_subtrees = 0;
if (TREE_CODE (t) == ARRAY_REF || TREE_CODE (t) == ARRAY_RANGE_REF)
else if (TREE_CODE (t) == ARRAY_REF || TREE_CODE (t) == ARRAY_RANGE_REF)
{
while (((TREE_CODE (t) == ARRAY_REF || TREE_CODE (t) == ARRAY_RANGE_REF)
&& is_gimple_min_invariant (TREE_OPERAND (t, 1))

View File

@ -1856,6 +1856,10 @@ has_cleanups (tree exp)
}
return 0;
case DECL_EXPR:
return (DECL_INITIAL (DECL_EXPR_DECL (exp))
&& has_cleanups (DECL_INITIAL (DECL_EXPR_DECL (exp))));
default:
break;
}

View File

@ -805,6 +805,9 @@ DEFTREECODE (TRY_FINALLY_EXPR, "try_finally", 's', 2)
/* These types of expressions have no useful value,
and always have side effects. */
/* Used to represent a local declaration. The operand is DECL_EXPR_DECL. */
DEFTREECODE (DECL_EXPR, "decl_expr", 's', 1)
/* A label definition, encapsulated as a statement.
Operand 0 is the LABEL_DECL node for the label that appears here.
The type should be void and the value should be ignored. */

View File

@ -1065,6 +1065,10 @@ struct tree_vec GTY(())
#define TARGET_EXPR_INITIAL(NODE) TREE_OPERAND_CHECK_CODE (NODE, TARGET_EXPR, 1)
#define TARGET_EXPR_CLEANUP(NODE) TREE_OPERAND_CHECK_CODE (NODE, TARGET_EXPR, 2)
/* DECL_EXPR accessor. This gives access to the DECL associated with
the given declaration statement. */
#define DECL_EXPR_DECL(NODE) TREE_OPERAND (DECL_EXPR_CHECK (NODE), 0)
#define EXIT_EXPR_COND(NODE) TREE_OPERAND (EXIT_EXPR_CHECK (NODE), 0)
/* SWITCH_EXPR accessors. These give access to the condition, body and