aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>1999-09-12 01:12:59 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>1999-09-12 01:12:59 +0000
commit24bef15854919b1b36f74ea8208c71b146975a0b (patch)
tree21262e14b6ea734d629371b88b3f1eeb361b27dc /gcc
parentfcf6eeb628b0df816f962c5185641325de7d5f6e (diff)
downloadgcc-24bef15854919b1b36f74ea8208c71b146975a0b.zip
gcc-24bef15854919b1b36f74ea8208c71b146975a0b.tar.gz
gcc-24bef15854919b1b36f74ea8208c71b146975a0b.tar.bz2
cp-tree.def (CLEANUP_STMT): New node.
* cp-tree.def (CLEANUP_STMT): New node. * cp-tree.h (language_function): Add name_declared. (current_function_name_declared): New macro. (CLEANUP_DECL): New macro. (CLEANUP_EXPR): Likewise. (emit_local_var): Likewise. (finish_decl_cleanup): New function. * cvt.c (build_up_reference): Simplify. (ocp_convert): Remove dead code. * decl.c (start_decl): Remove call to add_decl_stmt. (grok_reference_init): Adjust, to handle bindings temporaries to references. Remove dead code. (initialize_local_var): Don't generate RTL for declarations here, or build cleanups here. Don't fuss with obstacks. Replace expand_start_target_temps calls with explicit setting of stms_are_full_exprs_p. (destroy_local_var): New function. (emit_local_var): Likewise. (cp_finish_decl): Use them, as appropriate. (start_function): Announce template functions. (store_parm_decls): Don't call declare_function_name here. (finish_stmt): Don't start emit base-initialization code when just building the statement-tree. * init.c (create_temporary_var): Move add_decl_stmt call ... (get_temp_regvar): Here. * pt.c (tsubst_expr): Make DECL_INITIAL look like what cp_finish_decl would expect. Don't call add_decl_stmt. * semantics.c (begin_compound_stmt): Call declare_function_name, if appropriate. (finish_decl_cleanup): New function. (expand_stmt): Use emit_local_var to output variables. (expand_body): Set current_funtion_name_declared. From-SVN: r29348
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog35
-rw-r--r--gcc/cp/cp-tree.def4
-rw-r--r--gcc/cp/cp-tree.h11
-rw-r--r--gcc/cp/cvt.c29
-rw-r--r--gcc/cp/decl.c139
-rw-r--r--gcc/cp/init.c5
-rw-r--r--gcc/cp/pt.c6
-rw-r--r--gcc/cp/semantics.c32
8 files changed, 169 insertions, 92 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 06c874f..ab9ece6 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,38 @@
+1999-09-11 Mark Mitchell <mark@codesourcery.com>
+
+ * cp-tree.def (CLEANUP_STMT): New node.
+ * cp-tree.h (language_function): Add name_declared.
+ (current_function_name_declared): New macro.
+ (CLEANUP_DECL): New macro.
+ (CLEANUP_EXPR): Likewise.
+ (emit_local_var): Likewise.
+ (finish_decl_cleanup): New function.
+ * cvt.c (build_up_reference): Simplify.
+ (ocp_convert): Remove dead code.
+ * decl.c (start_decl): Remove call to add_decl_stmt.
+ (grok_reference_init): Adjust, to handle bindings temporaries to
+ references. Remove dead code.
+ (initialize_local_var): Don't generate RTL for
+ declarations here, or build cleanups here. Don't fuss with
+ obstacks. Replace expand_start_target_temps calls with explicit
+ setting of stms_are_full_exprs_p.
+ (destroy_local_var): New function.
+ (emit_local_var): Likewise.
+ (cp_finish_decl): Use them, as appropriate.
+ (start_function): Announce template functions.
+ (store_parm_decls): Don't call declare_function_name here.
+ (finish_stmt): Don't start emit base-initialization code when just
+ building the statement-tree.
+ * init.c (create_temporary_var): Move add_decl_stmt call ...
+ (get_temp_regvar): Here.
+ * pt.c (tsubst_expr): Make DECL_INITIAL look like what
+ cp_finish_decl would expect. Don't call add_decl_stmt.
+ * semantics.c (begin_compound_stmt): Call declare_function_name,
+ if appropriate.
+ (finish_decl_cleanup): New function.
+ (expand_stmt): Use emit_local_var to output variables.
+ (expand_body): Set current_funtion_name_declared.
+
1999-09-10 Mark Mitchell <mark@codesourcery.com>
* cp-tree.h (finish_cleanup_try_block): New function.
diff --git a/gcc/cp/cp-tree.def b/gcc/cp/cp-tree.def
index 3322786..53e3e1a 100644
--- a/gcc/cp/cp-tree.def
+++ b/gcc/cp/cp-tree.def
@@ -235,6 +235,10 @@ DEFTREECODE (ASM_STMT, "asm_stmt", 'e', 5)
run if an exception is thrown before the end of the enclosing
function. */
DEFTREECODE (SUBOBJECT, "subobject", 'e', 1)
+/* A CLEANUP_STMT marks the point at which a declaration is fully
+ constructed. If, after this point, the CLEANUP_DECL goes out of
+ scope, the CLEANUP_EXPR must be run. */
+DEFTREECODE (CLEANUP_STMT, "cleanup", 'e', 2)
DEFTREECODE (CTOR_INITIALIZER, "ctor_initializer", 'e', 2)
DEFTREECODE (CASE_LABEL, "case_label", 'e', 2)
DEFTREECODE (RETURN_INIT, "return_init", 'e', 2)
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index d40fe75..5b43829 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -636,6 +636,7 @@ struct language_function
int in_function_try_handler;
int x_expanding_p;
int stmts_are_full_exprs_p;
+ int name_declared;
struct named_label_list *x_named_label_uses;
struct binding_level *bindings;
@@ -708,6 +709,12 @@ struct language_function
#define current_function_parms_stored \
cp_function_chain->parms_stored
+/* Non-zero if we have already declared __FUNCTION__ (and related
+ variables) in the current function. */
+
+#define current_function_name_declared \
+ cp_function_chain->name_declared
+
/* Used to help generate temporary names which are unique within
a function. Reset to 0 by start_function. */
@@ -2437,6 +2444,8 @@ extern int flag_new_for_scope;
#define DECL_STMT_DECL(NODE) TREE_OPERAND (NODE, 0)
#define STMT_EXPR_STMT(NODE) TREE_OPERAND (NODE, 0)
#define SUBOBJECT_CLEANUP(NODE) TREE_OPERAND (NODE, 0)
+#define CLEANUP_DECL(NODE) TREE_OPERAND (NODE, 0)
+#define CLEANUP_EXPR(NODE) TREE_OPERAND (NODE, 1)
#define LABEL_STMT_LABEL(NODE) TREE_OPERAND (NODE, 0)
/* Nonzero for an ASM_STMT if the assembly statement is volatile. */
@@ -3237,6 +3246,7 @@ extern int wrapup_globals_for_namespace PROTO((tree, void *));
extern tree cp_namespace_decls PROTO((tree));
extern tree create_implicit_typedef PROTO((tree, tree));
extern tree maybe_push_decl PROTO((tree));
+extern void emit_local_var PROTO((tree));
/* in decl2.c */
extern void init_decl2 PROTO((void));
@@ -3651,6 +3661,7 @@ extern void finish_member_declaration PROTO((tree));
extern void check_multiple_declarators PROTO((void));
extern tree finish_typeof PROTO((tree));
extern void add_decl_stmt PROTO((tree));
+extern void finish_decl_cleanup PROTO((tree, tree));
extern void finish_named_return_value PROTO((tree, tree));
extern tree expand_stmt PROTO((tree));
extern void expand_body PROTO((tree));
diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
index 7ea55bd..382a9b2 100644
--- a/gcc/cp/cvt.c
+++ b/gcc/cp/cvt.c
@@ -345,8 +345,6 @@ build_up_reference (type, arg, flags)
if ((flags & DIRECT_BIND) && ! real_lvalue_p (arg))
{
- tree compound_stmt;
-
/* Create a new temporary variable. */
tree targ = arg;
if (toplevel_bindings_p ())
@@ -355,25 +353,12 @@ build_up_reference (type, arg, flags)
{
arg = pushdecl (build_decl (VAR_DECL, NULL_TREE, argtype));
DECL_ARTIFICIAL (arg) = 1;
- /* Generate code to initialize it. We wrap it in a
- statement-expression so that when we are building a
- statement-tree we will have a representation of this
- declaration. */
- begin_init_stmts (&stmt_expr, &compound_stmt);
}
/* Process the initializer for the declaration. */
DECL_INITIAL (arg) = targ;
cp_finish_decl (arg, targ, NULL_TREE, 0,
LOOKUP_ONLYCONVERTING|DIRECT_BIND);
-
- /* And wrap up the statement-expression, if necessary. */
- if (!toplevel_bindings_p ())
- {
- if (building_stmt_tree ())
- add_decl_stmt (arg);
- stmt_expr = finish_init_stmts (stmt_expr, compound_stmt);
- }
}
else if (!(flags & DIRECT_BIND) && ! lvalue_p (arg))
{
@@ -719,13 +704,6 @@ ocp_convert (type, expr, convtype, flags)
return e;
}
-#if 0
- /* This is incorrect. A truncation can't be stripped this way.
- Extensions will be stripped by the use of get_unwidened. */
- if (TREE_CODE (e) == NOP_EXPR)
- return cp_convert (type, TREE_OPERAND (e, 0));
-#endif
-
/* Just convert to the type of the member. */
if (code == OFFSET_TYPE)
{
@@ -733,13 +711,6 @@ ocp_convert (type, expr, convtype, flags)
code = TREE_CODE (type);
}
-#if 0
- if (code == REFERENCE_TYPE)
- return fold (convert_to_reference (type, e, convtype, flags, NULL_TREE));
- else if (TREE_CODE (TREE_TYPE (e)) == REFERENCE_TYPE)
- e = convert_from_reference (e);
-#endif
-
if (TREE_CODE (e) == OFFSET_REF)
e = resolve_offset_ref (e);
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index ee68023..547f7c6 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -179,6 +179,7 @@ static void mark_cp_function_context PROTO((struct function *));
static void mark_saved_scope PROTO((void *));
static void check_function_type PROTO((tree));
static void destroy_local_static PROTO((tree));
+static void destroy_local_var PROTO((tree));
#if defined (DEBUG_CP_BINDING_LEVELS)
static void indent PROTO((void));
@@ -6843,15 +6844,9 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
{
if (at_function_scope_p ())
push_permanent_obstack ();
-
tem = push_template_decl (tem);
- /* In a a local scope, add a representation of this declaration
- to the statement tree. */
if (at_function_scope_p ())
- {
- add_decl_stmt (decl);
- pop_obstacks ();
- }
+ pop_obstacks ();
}
@@ -6987,7 +6982,14 @@ grok_reference_init (decl, type, init)
/* Note: default conversion is only called in very special cases. */
init = default_conversion (init);
}
-
+
+ /* Convert INIT to the reference type TYPE. This may involve the
+ creation of a temporary, whose lifetime must be the same as that
+ of the reference. If so, a DECL_STMT for the temporary will be
+ added just after the DECL_STMT for DECL. That's why we don't set
+ DECL_INITIAL for local references (instead assigning to them
+ explicitly); we need to allow the temporary to be initialized
+ first. */
tmp = convert_to_reference
(type, init, CONV_IMPLICIT,
LOOKUP_SPECULATIVELY|LOOKUP_NORMAL|DIRECT_BIND, decl);
@@ -6997,7 +6999,18 @@ grok_reference_init (decl, type, init)
else if (tmp != NULL_TREE)
{
init = tmp;
- DECL_INITIAL (decl) = save_expr (init);
+ tmp = save_expr (tmp);
+ if (building_stmt_tree ())
+ {
+ /* Initialize the declaration. */
+ tmp = build (INIT_EXPR, TREE_TYPE (decl), decl, tmp);
+ /* Setting TREE_SIDE_EFFECTS prevents expand_expr from
+ omitting this expression entirely. */
+ TREE_SIDE_EFFECTS (tmp) = 1;
+ finish_expr_stmt (tmp);
+ }
+ else
+ DECL_INITIAL (decl) = tmp;
}
else
{
@@ -7005,11 +7018,6 @@ grok_reference_init (decl, type, init)
return;
}
- /* ?? Can this be optimized in some cases to
- hand back the DECL_INITIAL slot?? */
- if (TYPE_SIZE (TREE_TYPE (type)))
- init = convert_from_reference (decl);
-
if (TREE_STATIC (decl) && ! TREE_CONSTANT (DECL_INITIAL (decl)))
{
expand_static_init (decl, DECL_INITIAL (decl));
@@ -7526,12 +7534,9 @@ initialize_local_var (decl, init, flags)
int flags;
{
tree type;
- tree cleanup;
type = complete_type (TREE_TYPE (decl));
- cleanup = build_cleanup_on_safe_obstack (decl);
-
if (DECL_SIZE (decl) == NULL_TREE && !TREE_STATIC (decl))
{
/* If we used it already as memory, it must stay in memory. */
@@ -7539,16 +7544,6 @@ initialize_local_var (decl, init, flags)
TREE_ADDRESSABLE (decl) = TREE_USED (decl);
}
- if (DECL_RTL (decl))
- /* Only a RESULT_DECL should have non-NULL RTL when arriving here.
- All other local variables are assigned RTL in this function. */
- my_friendly_assert (TREE_CODE (decl) == RESULT_DECL, 19990828);
- else
- /* Create RTL for this variable. */
- expand_decl (decl);
-
- expand_start_target_temps ();
-
if (DECL_SIZE (decl) && type != error_mark_node)
{
int already_used;
@@ -7558,21 +7553,15 @@ initialize_local_var (decl, init, flags)
if (init || TYPE_NEEDS_CONSTRUCTING (type))
{
+ int saved_stmts_are_full_exprs_p;
+
emit_line_note (DECL_SOURCE_FILE (decl),
DECL_SOURCE_LINE (decl));
- /* We call push_momentary here so that when
- finish_expr_stmt clears the momentary obstack it
- doesn't destory any momentary expressions we may
- have lying around. Although cp_finish_decl is
- usually called at the end of a declaration
- statement, it may also be called for a temporary
- object in the middle of an expression. */
- push_momentary ();
+ saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p;
+ stmts_are_full_exprs_p = 1;
finish_expr_stmt (build_aggr_init (decl, init, flags));
- pop_momentary ();
+ stmts_are_full_exprs_p = saved_stmts_are_full_exprs_p;
}
- else
- expand_decl_init (decl);
/* Set this to 0 so we can tell whether an aggregate which was
initialized was ever used. Don't do this if it has a
@@ -7582,22 +7571,48 @@ initialize_local_var (decl, init, flags)
marked used. (see TREE_USED, above.) */
if (TYPE_NEEDS_CONSTRUCTING (type)
&& ! already_used
- && cleanup == NULL_TREE
+ && !TYPE_NEEDS_DESTRUCTOR (type)
&& DECL_NAME (decl))
TREE_USED (decl) = 0;
else if (already_used)
TREE_USED (decl) = 1;
}
+}
- /* Cleanup any temporaries needed for the initial value. */
- expand_end_target_temps ();
+/* Generate code to destroy DECL (a local variable). */
+
+void
+destroy_local_var (decl)
+ tree decl;
+{
+ tree cleanup = build_cleanup_on_safe_obstack (decl);
/* Record the cleanup required for this declaration. */
- if (DECL_SIZE (decl)
- && type != error_mark_node
- && cleanup
- && !expand_decl_cleanup (decl, cleanup))
- cp_error ("parser lost in parsing declaration of `%D'", decl);
+ if (DECL_SIZE (decl) && TREE_TYPE (decl) != error_mark_node
+ && cleanup)
+ finish_decl_cleanup (decl, cleanup);
+}
+
+/* Let the back-end know about DECL. */
+
+void
+emit_local_var (decl)
+ tree decl;
+{
+ /* Create RTL for this variable. */
+ if (DECL_RTL (decl))
+ /* Only a RESULT_DECL should have non-NULL RTL when
+ arriving here. All other local variables are
+ assigned RTL in this function. */
+ my_friendly_assert (TREE_CODE (decl) == RESULT_DECL,
+ 19990828);
+ else
+ expand_decl (decl);
+
+ /* Actually do the initialization. */
+ expand_start_target_temps ();
+ expand_decl_init (decl);
+ expand_end_target_temps ();
}
/* Finish processing of a declaration;
@@ -7680,9 +7695,14 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
return;
}
+ /* Add this declaration to the statement-tree. */
+ if (building_stmt_tree ()
+ && TREE_CODE (current_scope ()) == FUNCTION_DECL)
+ add_decl_stmt (decl);
+
if (TYPE_HAS_MUTABLE_P (type))
TREE_READONLY (decl) = 0;
-
+
if (processing_template_decl)
{
if (init && DECL_INITIAL (decl))
@@ -7808,10 +7828,19 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
/* Initialize the local variable. But, if we're building a
statement-tree, we'll do the initialization when we
expand the tree. */
- if (!building_stmt_tree ())
- initialize_local_var (decl, init, flags);
- else if (init || DECL_INITIAL (decl) == error_mark_node)
- DECL_INITIAL (decl) = init;
+ if (processing_template_decl)
+ {
+ if (init || DECL_INITIAL (decl) == error_mark_node)
+ DECL_INITIAL (decl) = init;
+ }
+ else
+ {
+ if (!building_stmt_tree ())
+ emit_local_var (decl);
+ initialize_local_var (decl, init, flags);
+ /* Clean up the variable. */
+ destroy_local_var (decl);
+ }
}
finish_end0:
@@ -12900,7 +12929,7 @@ start_function (declspecs, declarator, attrs, flags)
get_pending_sizes ();
/* Let the user know we're compiling this function. */
- if (!building_stmt_tree ())
+ if (processing_template_decl || !building_stmt_tree ())
announce_function (decl1);
/* Record the decl so that the function name is defined.
@@ -13210,9 +13239,6 @@ store_parm_decls ()
storedecls (chainon (nonparms, DECL_ARGUMENTS (fndecl)));
- /* Declare __FUNCTION__ and __PRETTY_FUNCTION__ for this function. */
- declare_function_name ();
-
/* Initialize the RTL code for the function. */
DECL_SAVED_INSNS (fndecl) = 0;
if (! building_stmt_tree ())
@@ -14222,7 +14248,8 @@ finish_stmt ()
if (!current_function_assigns_this
&& current_function_just_assigned_this)
{
- if (DECL_CONSTRUCTOR_P (current_function_decl))
+ if (DECL_CONSTRUCTOR_P (current_function_decl)
+ && !building_stmt_tree ())
{
/* Constructors must wait until we are out of control
zones before calling base constructors. */
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 46e207b1..a5b2417 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -2668,9 +2668,6 @@ create_temporary_var (type)
DECL_SOURCE_LINE (decl) = lineno;
DECL_IGNORED_P (decl) = 1;
- if (building_stmt_tree ())
- add_decl_stmt (decl);
-
return decl;
}
@@ -2688,6 +2685,8 @@ get_temp_regvar (type, init)
tree decl;
decl = create_temporary_var (type);
+ if (building_stmt_tree ())
+ add_decl_stmt (decl);
DECL_REGISTER (decl) = 1;
if (!building_stmt_tree ())
DECL_RTL (decl) = assign_temp (type, 2, 0, 1);
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index a214317..1cb315d 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -7284,7 +7284,8 @@ tsubst_expr (t, args, complain, in_decl)
init = DECL_INITIAL (decl);
decl = tsubst (decl, args, complain, in_decl);
init = tsubst_expr (init, args, complain, in_decl);
- DECL_INITIAL (decl) = init;
+ if (init)
+ DECL_INITIAL (decl) = error_mark_node;
/* By marking the declaration as instantiated, we avoid
trying to instantiate it. Since instantiate_decl can't
handle local variables, and since we've already done
@@ -7293,8 +7294,7 @@ tsubst_expr (t, args, complain, in_decl)
if (TREE_CODE (decl) == VAR_DECL)
DECL_TEMPLATE_INSTANTIATED (decl) = 1;
maybe_push_decl (decl);
- cp_finish_decl (decl, DECL_INITIAL (decl), NULL_TREE, 0, 0);
- add_decl_stmt (decl);
+ cp_finish_decl (decl, init, NULL_TREE, 0, 0);
}
resume_momentary (i);
return decl;
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index eaa5354..657c3dd 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -869,6 +869,14 @@ begin_compound_stmt (has_no_scope)
to accidentally keep a block *inside* the scopeless block. */
keep_next_level (0);
+ /* If this is the outermost block of the function, declare the
+ variables __FUNCTION__, __PRETTY_FUNCTION__, and so forth. */
+ if (!current_function_name_declared && !processing_template_decl)
+ {
+ declare_function_name ();
+ current_function_name_declared = 1;
+ }
+
return r;
}
@@ -1027,6 +1035,19 @@ finish_subobject (cleanup)
add_partial_entry (cleanup);
}
+/* When DECL goes out of scope, make sure that CLEANUP is executed. */
+
+void
+finish_decl_cleanup (decl, cleanup)
+ tree decl;
+ tree cleanup;
+{
+ if (building_stmt_tree ())
+ add_tree (build_min_nt (CLEANUP_STMT, decl, cleanup));
+ else if (DECL_SIZE (decl) && TREE_TYPE (decl) != error_mark_node)
+ expand_decl_cleanup (decl, cleanup);
+}
+
/* Bind a name and initialization to the return value of
the current function. */
@@ -2153,13 +2174,17 @@ expand_stmt (t)
compatibility. */
maybe_inject_for_scope_var (decl);
/* Let the back-end know about this variable. */
- initialize_local_var (decl, DECL_INITIAL (decl), 0);
+ emit_local_var (decl);
}
}
resume_momentary (i);
}
break;
+ case CLEANUP_STMT:
+ finish_decl_cleanup (CLEANUP_DECL (t), CLEANUP_EXPR (t));
+ break;
+
case FOR_STMT:
{
tree tmp;
@@ -2338,6 +2363,11 @@ expand_body (fn)
start_function (NULL_TREE, fn, NULL_TREE, SF_PRE_PARSED | SF_EXPAND);
store_parm_decls ();
+ /* We don't need to redeclare __FUNCTION__, __PRETTY_FUNCTION__, or
+ any of the other magic variables we set up when starting a
+ function body. */
+ current_function_name_declared = 1;
+
/* There are a few things that we do not handle recursively. For
example, a function try-block is handled differently from an
ordinary try-block, so we must handle it here. */