]> gcc.gnu.org Git - gcc.git/commitdiff
cp-tree.def (CLEANUP_STMT): New node.
authorMark Mitchell <mark@codesourcery.com>
Sun, 12 Sep 1999 01:12:59 +0000 (01:12 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Sun, 12 Sep 1999 01:12:59 +0000 (01:12 +0000)
* 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

gcc/cp/ChangeLog
gcc/cp/cp-tree.def
gcc/cp/cp-tree.h
gcc/cp/cvt.c
gcc/cp/decl.c
gcc/cp/init.c
gcc/cp/pt.c
gcc/cp/semantics.c

index 06c874f3b31268c3405296eb2b5d9670aad85666..ab9ece6270f6419c4bd6b856946ef9b73fef470e 100644 (file)
@@ -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.
index 3322786ce2c53722befc29de87bb7419bc31de37..53e3e1a3bf0b607099ef975df0d2d03a891cb953 100644 (file)
@@ -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)
index d40fe7533eaf885cd3eead49500f7191e159e681..5b438290bae835c47214152a0497f329f106fb91 100644 (file)
@@ -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));
index 7ea55bd85959b1d7d8d8851b42c116564a5e39a2..382a9b2660d044c472ed0296fc22a4b7e4cec79d 100644 (file)
@@ -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);
 
index ee680230b1e44188e9974e62d2e8cb07faab7cfd..547f7c6af50e0868dd15745d580deb1133704112 100644 (file)
@@ -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.  */
index 46e207b1d88d31cd03ddc49b3f3034f451f2d8c2..a5b2417e9fa72815965dcf2b7da021f4db60bc43 100644 (file)
@@ -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);
index a21431796837bc5447c3c4eb45d4f65f6f7db2aa..1cb315d3059196d745096bfce5d07efefc4e2085 100644 (file)
@@ -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;
index eaa5354b9c7c56c2800f99f73917249d30ccc1fa..657c3dd6a238f71300972ea5fcdcfad47cba89a3 100644 (file)
@@ -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.  */
This page took 0.092688 seconds and 5 git commands to generate.