}
}
-/* 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
(*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
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)
#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)
#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,
#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
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);
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);
}
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))
{
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);
}
{
/* 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;
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;
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));
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
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;
}
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);
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;
#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
#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
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:
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
{
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));
}
}
;
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);
}
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;
+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
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
#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
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);
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);
/* 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. */
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
{
/* 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;
}
/* 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);
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);
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));
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);
/* 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);
/* 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;
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)
}
}
- /* 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;
}
/* 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);
/* 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)
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;
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. */
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)
}
/* 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;
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. */
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 *'). */
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
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))
/* 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))
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. */
*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;
#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
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;
#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)
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));
case CONSTRUCTOR:
WALK_SUBTREE_TAIL (CONSTRUCTOR_ELTS (*tp));
+ case EXIT_BLOCK_EXPR:
+ WALK_SUBTREE_TAIL (TREE_OPERAND (*tp, 1));
+
+ case SAVE_EXPR:
+ WALK_SUBTREE_TAIL (TREE_OPERAND (*tp, 0));
+
+ case BIND_EXPR:
+ {
+ tree decl;
+ for (decl = BIND_EXPR_VARS (*tp); decl; decl = TREE_CHAIN (decl))
+ {
+ /* 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));
+ WALK_SUBTREE (DECL_SIZE (decl));
+ WALK_SUBTREE (DECL_SIZE_UNIT (decl));
+ WALK_SUBTREE (TREE_TYPE (decl));
+ }
+ WALK_SUBTREE_TAIL (BIND_EXPR_BODY (*tp));
+ }
+
+ case STATEMENT_LIST:
+ {
+ tree_stmt_iterator i;
+ for (i = tsi_start (*tp); !tsi_end_p (i); tsi_next (&i))
+ WALK_SUBTREE (*tsi_stmt_ptr (i));
+ }
+ 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));
case FUNCTION_TYPE:
WALK_SUBTREE (TREE_TYPE (*tp));
{
- tree arg = TYPE_ARG_TYPES (*tp);
+ tree arg;
/* We never want to walk into default arguments. */
- for (; arg; arg = TREE_CHAIN (arg))
+ for (arg = TYPE_ARG_TYPES (*tp); 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. */
WALK_SUBTREE (TREE_TYPE (*tp));
WALK_SUBTREE_TAIL (TYPE_OFFSET_BASETYPE (*tp));
- case EXIT_BLOCK_EXPR:
- WALK_SUBTREE_TAIL (TREE_OPERAND (*tp, 1));
-
- case SAVE_EXPR:
- WALK_SUBTREE_TAIL (TREE_OPERAND (*tp, 0));
-
- case BIND_EXPR:
- {
- tree decl;
- for (decl = BIND_EXPR_VARS (*tp); decl; decl = TREE_CHAIN (decl))
- {
- /* 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));
- WALK_SUBTREE (DECL_SIZE (decl));
- WALK_SUBTREE (DECL_SIZE_UNIT (decl));
- WALK_SUBTREE (TREE_TYPE (decl));
- }
- WALK_SUBTREE_TAIL (BIND_EXPR_BODY (*tp));
- }
-
- case STATEMENT_LIST:
- {
- tree_stmt_iterator i;
- for (i = tsi_start (*tp); !tsi_end_p (i); tsi_next (&i))
- WALK_SUBTREE (*tsi_stmt_ptr (i));
- }
- break;
-
default:
/* ??? This could be a language-defined node. We really should make
a hook for it, but right now just ignore it. */
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))
- {
- *walk_subtrees = 0;
- return NULL_TREE;
- }
-
- 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 (TYPE_P (*tp))
+ *walk_subtrees = 0;
- if (decl)
+ else if (TREE_CODE (*tp) == LABEL_EXPR)
{
- tree copy;
-
- /* Make a copy. */
- copy = copy_decl_for_inlining (decl,
- DECL_CONTEXT (decl),
- DECL_CONTEXT (decl));
+ tree decl = TREE_OPERAND (*tp, 0);
- /* 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;
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))
}
return 0;
+ case DECL_EXPR:
+ return (DECL_INITIAL (DECL_EXPR_DECL (exp))
+ && has_cleanups (DECL_INITIAL (DECL_EXPR_DECL (exp))));
+
default:
break;
}
/* 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. */
#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