cp-tree.h (TYPE_NEEDS_CONSTRUCTING): Remove #if 0'd definition.
authorMark Mitchell <mark@codesourcery.com>
Sun, 29 Aug 1999 19:03:31 +0000 (19:03 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Sun, 29 Aug 1999 19:03:31 +0000 (19:03 +0000)
* cp-tree.h (TYPE_NEEDS_CONSTRUCTING): Remove #if 0'd definition.
(maybe_inject_for_scope_var): Declare it.
(initialize_local_var): Likewise.
* decl.c (maybe_inject_for_scope_var): Make it global.
(initialize_local_var): Likewise.  Move cleanup handling here,
from cp_finish_decl.
(make_rtl_for_nonlocal_decl): Use
push_obstacks_nochange/pop_obstacks, rather than
end_temporary_allocation/resume_temporary_allocation.
(cp_finish_decl): Try to complete the type of a variable when it
is declared.  Move cleanup-handling to initialize_local_var.
(expand_static_init): Use tree-building code, rather than
RTL-building code.
* decl2.c (get_temp_name): Assert non-initializedness of
temporaries.
* init.c (create_temporary_var): Move RTL-assigning code to ...
(get_temp_regvar): Here.
* pt.c (tsbust_expr): Fix indentation.  Call cp_finish_decl here.
* semantics.c (expand_stmt): Don't call cp_finish_decl here.  Just
call initialize_local_var to generate initialization code.

From-SVN: r28973

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/init.c
gcc/cp/pt.c
gcc/cp/semantics.c
gcc/testsuite/g++.old-deja/g++.pt/crash52.C [new file with mode: 0644]

index 61cee8c03b3b5b26261762e2837d7b416a2beb5e..0fa5c607127618b90cbb53b98def6f6105d7382f 100644 (file)
@@ -1,3 +1,26 @@
+1999-08-29  Mark Mitchell  <mark@codesourcery.com>
+
+       * cp-tree.h (TYPE_NEEDS_CONSTRUCTING): Remove #if 0'd definition.
+       (maybe_inject_for_scope_var): Declare it.
+       (initialize_local_var): Likewise.
+       * decl.c (maybe_inject_for_scope_var): Make it global.
+       (initialize_local_var): Likewise.  Move cleanup handling here,
+       from cp_finish_decl.
+       (make_rtl_for_nonlocal_decl): Use
+       push_obstacks_nochange/pop_obstacks, rather than
+       end_temporary_allocation/resume_temporary_allocation.
+       (cp_finish_decl): Try to complete the type of a variable when it
+       is declared.  Move cleanup-handling to initialize_local_var.
+       (expand_static_init): Use tree-building code, rather than
+       RTL-building code.
+       * decl2.c (get_temp_name): Assert non-initializedness of
+       temporaries.
+       * init.c (create_temporary_var): Move RTL-assigning code to ...
+       (get_temp_regvar): Here.
+       * pt.c (tsbust_expr): Fix indentation.  Call cp_finish_decl here.
+       * semantics.c (expand_stmt): Don't call cp_finish_decl here.  Just
+       call initialize_local_var to generate initialization code.
+       
 1999-08-29  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
 
        * cp-tree.h (fndecl_as_string, type_as_string,
index 2761324d18537803ef69769bdaeac705da0fca38..9fca5954794a6152bfe906dc28aef106797e5186 100644 (file)
@@ -1690,13 +1690,6 @@ extern int flag_new_for_scope;
 /* Nonzero for _TYPE means that the _TYPE defines a destructor.  */
 #define TYPE_HAS_DESTRUCTOR(NODE) (TYPE_LANG_FLAG_2(NODE))
 
-#if 0
-/* Nonzero for _TYPE node means that creating an object of this type
-   will involve a call to a constructor.  This can apply to objects
-   of ARRAY_TYPE if the type of the elements needs a constructor.  */
-#define TYPE_NEEDS_CONSTRUCTING(NODE) ... defined in ../tree.h ...
-#endif
-
 /* Nonzero means that an object of this type can not be initialized using
    an initializer list.  */
 #define CLASSTYPE_NON_AGGREGATE(NODE) \
@@ -2936,6 +2929,8 @@ extern tree start_decl                            PROTO((tree, tree, int, tree, tree));
 extern void start_decl_1                       PROTO((tree));
 extern void cp_finish_decl                     PROTO((tree, tree, tree, int, int));
 extern void finish_decl                                PROTO((tree, tree, tree));
+extern void maybe_inject_for_scope_var          PROTO((tree));
+extern void initialize_local_var                PROTO((tree, tree, int));
 extern void expand_static_init                 PROTO((tree, tree));
 extern int complete_array_type                 PROTO((tree, tree, int));
 extern tree build_ptrmemfunc_type              PROTO((tree));
index 8ca2f57a7ecc77592fe4e14bc7b377ed1847affd..c7b511c4a16146148aa816a74079f9153d805f6e 100644 (file)
@@ -196,8 +196,6 @@ static void pop_labels PROTO((tree));
 static void maybe_deduce_size_from_array_init PROTO((tree, tree));
 static void layout_var_decl PROTO((tree, tree *));
 static void maybe_commonize_var PROTO((tree));
-static void maybe_inject_for_scope_var PROTO((tree));
-static void initialize_local_var PROTO((tree, tree, tree, int));
 static tree build_cleanup_on_safe_obstack PROTO((tree));
 static void check_initializer PROTO((tree, tree *));
 static void make_rtl_for_nonlocal_decl PROTO((tree, tree, const char *));
@@ -7669,16 +7667,16 @@ make_rtl_for_nonlocal_decl (decl, init, asmspec)
      tree init;
      const char *asmspec;
 {
-  int was_temp;
   int toplev;
   tree type;
 
   type = TREE_TYPE (decl);
   toplev = toplevel_bindings_p ();
-  was_temp = (TREE_STATIC (decl) && TYPE_NEEDS_DESTRUCTOR (type)
-             && allocation_temporary_p ());
-  if (was_temp)
-    end_temporary_allocation ();
+  push_obstacks_nochange ();
+  if (TREE_STATIC (decl) 
+      && TYPE_NEEDS_DESTRUCTOR (type)
+      && allocation_temporary_p ())
+    end_temporary_allocation  ();
 
   if (TREE_CODE (decl) == VAR_DECL && DECL_VIRTUAL_P (decl))
     make_decl_rtl (decl, NULL_PTR, toplev);
@@ -7747,8 +7745,7 @@ make_rtl_for_nonlocal_decl (decl, init, asmspec)
   else
     rest_of_decl_compilation (decl, asmspec, toplev, at_eof);
 
-  if (was_temp)
-    resume_temporary_allocation ();
+  pop_obstacks ();
 }
 
 /* The old ARM scoping rules injected variables declared in the
@@ -7757,7 +7754,7 @@ make_rtl_for_nonlocal_decl (decl, init, asmspec)
    DECL is a just-declared VAR_DECL; if necessary inject its
    declaration into the surrounding scope.  */
 
-static void
+void
 maybe_inject_for_scope_var (decl)
      tree decl;
 {
@@ -7794,16 +7791,34 @@ maybe_inject_for_scope_var (decl)
 
 /* Generate code to initialized DECL (a local variable).  */
 
-static void
-initialize_local_var (decl, init, cleanup, flags)
+void
+initialize_local_var (decl, init, flags)
      tree decl;
      tree init;
-     tree cleanup;
      int flags;
 {
   tree type;
+  tree cleanup;
 
   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.  */
+      DECL_INITIAL (decl) = NULL_TREE;
+      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)
@@ -7811,7 +7826,6 @@ initialize_local_var (decl, init, cleanup, flags)
       int already_used;
   
       /* Compute and store the initial value.  */
-      expand_decl_init (decl);
       already_used = TREE_USED (decl) || TREE_USED (type);
 
       if (init || TYPE_NEEDS_CONSTRUCTING (type))
@@ -7829,39 +7843,33 @@ initialize_local_var (decl, init, cleanup, flags)
          finish_expr_stmt (build_aggr_init (decl, init, flags));
          pop_momentary ();
        }
+      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
         destructor, so we don't complain about the 'resource
-        allocation is initialization' idiom.  */
-      /* Now set attribute((unused)) on types so decls of that type
-        will be marked used. (see TREE_USED, above.)  This avoids the
-        warning problems this particular code tried to work
-        around. */
-
+        allocation is initialization' idiom.  Now set
+        attribute((unused)) on types so decls of that type will be
+        marked used. (see TREE_USED, above.)  */
       if (TYPE_NEEDS_CONSTRUCTING (type)
          && ! already_used
          && cleanup == NULL_TREE
          && DECL_NAME (decl))
        TREE_USED (decl) = 0;
-
-      if (already_used)
+      else if (already_used)
        TREE_USED (decl) = 1;
     }
 
   /* Cleanup any temporaries needed for the initial value.  */
   expand_end_target_temps ();
 
-  if (DECL_SIZE (decl) && type != error_mark_node)
-    {
-      /* Store the cleanup, if there was one.  */
-      if (cleanup)
-       {
-         if (! expand_decl_cleanup (decl, cleanup))
-           cp_error ("parser lost in parsing declaration of `%D'",
-                     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);
 }
 
 /* Finish processing of a declaration;
@@ -7895,7 +7903,6 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
 {
   register tree type;
   tree ttype = NULL_TREE;
-  int was_incomplete;
   int temporary = allocation_temporary_p ();
   const char *asmspec = NULL;
   int was_readonly = 0;
@@ -7935,13 +7942,7 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
       pop_decl_namespace ();
     }
 
-  /* If the type of the thing we are declaring either has
-     a constructor, or has a virtual function table pointer,
-     AND its initialization was accepted by `start_decl',
-     then we stayed on the permanent obstack through the
-     declaration, otherwise, changed obstacks as GCC would.  */
-
-  type = TREE_TYPE (decl);
+  type = complete_type (TREE_TYPE (decl));
 
   if (type == error_mark_node)
     {
@@ -8039,9 +8040,6 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
   /* Output the assembler code and/or RTL code for variables and functions,
      unless the type is an undefined structure or union.
      If not, it will get done when the type is completed.  */
-
-  was_incomplete = (DECL_SIZE (decl) == NULL_TREE);
-
   if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL
       || TREE_CODE (decl) == RESULT_DECL)
     {
@@ -8078,44 +8076,15 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
        }
       else if (! toplev)
        {
-         tree cleanup = build_cleanup_on_safe_obstack (decl);
-
-         /* This is a declared decl which must live until the
-            end of the binding contour.  It may need a cleanup.  */
-
-         /* Recompute the RTL of a local array now
-            if it used to be an incomplete type.  */
-         if (was_incomplete && ! TREE_STATIC (decl))
-           {
-             /* If we used it already as memory, it must stay in memory.  */
-             TREE_ADDRESSABLE (decl) = TREE_USED (decl);
-             /* If it's still incomplete now, no init will save it.  */
-             if (DECL_SIZE (decl) == NULL_TREE)
-               DECL_INITIAL (decl) = NULL_TREE;
-             expand_decl (decl);
-           }
-         else if (! TREE_ASM_WRITTEN (decl)
-                  && (TYPE_SIZE (type) != NULL_TREE
-                      || TREE_CODE (type) == ARRAY_TYPE))
-           {
-             /* Do this here, because we did not expand this decl's
-                rtl in start_decl.  */
-             if (DECL_RTL (decl) == NULL_RTX)
-               expand_decl (decl);
-             else if (cleanup)
-               {
-                 /* XXX: Why don't we use decl here?  */
-                 /* Ans: Because it was already expanded? */
-                 if (! expand_decl_cleanup (NULL_TREE, cleanup))
-                   cp_error ("parser lost in parsing declaration of `%D'",
-                             decl);
-                 /* Cleanup used up here.  */
-                 cleanup = NULL_TREE;
-               }
-           }
-
+         /* This is a local declaration.  */
          maybe_inject_for_scope_var (decl);
-         initialize_local_var (decl, init, cleanup, 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;
        }
     finish_end0:
 
@@ -8195,6 +8164,7 @@ expand_static_init (decl, init)
     {
       /* Emit code to perform this initialization but once.  */
       tree temp;
+      tree if_stmt;
       tree assignment;
       tree temp_init;
 
@@ -8229,8 +8199,10 @@ expand_static_init (decl, init)
       rest_of_decl_compilation (temp, NULL_PTR, 0, 0);
 
       /* Begin the conditional initialization.  */
-      expand_start_cond (build_binary_op (EQ_EXPR, temp,
-                                         integer_zero_node), 0);
+      if_stmt = begin_if_stmt ();
+      finish_if_stmt_cond (build_binary_op (EQ_EXPR, temp,
+                                           integer_zero_node), 
+                          if_stmt);
 
       /* Do the initialization itself.  */
       if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))
@@ -8325,10 +8297,12 @@ expand_static_init (decl, init)
                                       expr_tree_cons (NULL_TREE, 
                                                       cleanup, 
                                                       NULL_TREE));
-         expand_expr_stmt (fcall);
+         finish_expr_stmt (fcall);
        }
 
-      expand_end_cond ();
+      finish_then_clause (if_stmt);
+      finish_if_stmt ();
+
       /* Resume old (possibly temporary) allocation.  */
       pop_obstacks ();
     }
index b36abf2bd106c6a346108f3458d69b9e46fc9bc3..5eb4a673f29ca1cca8432394abdf3e7352f58e78 100644 (file)
@@ -2070,7 +2070,8 @@ get_temp_name (type, staticp)
   if (! toplev)
     {
       expand_decl (decl);
-      expand_decl_init (decl);
+      my_friendly_assert (DECL_INITIAL (decl) == NULL_TREE,
+                         19990826);
     }
   pop_obstacks ();
 
index eba001cfe207a5bf2c35cf0c36567b533533472a..9265ff9fe8d1cda9f98adff36ef13d0090a7ddb8 100644 (file)
@@ -2706,8 +2706,6 @@ create_temporary_var (type)
 
   if (building_stmt_tree ())
     add_decl_stmt (decl);
-  else
-    DECL_RTL (decl) = assign_temp (type, 2, 0, 1);
 
   return decl;
 }
@@ -2727,6 +2725,8 @@ get_temp_regvar (type, init)
 
   decl = create_temporary_var (type);
   DECL_REGISTER (decl) = 1;
+  if (!building_stmt_tree ())
+    DECL_RTL (decl) = assign_temp (type, 2, 0, 1);
   finish_expr_stmt (build_modify_expr (decl, INIT_EXPR, init));
 
   return decl;
index bb3429612076c15b50d4bc10a8cfaf231afc0b8c..e321c348e9b994701d6d6c9387127b1c607040da 100644 (file)
@@ -7272,13 +7272,15 @@ tsubst_expr (t, args, complain, in_decl)
            decl = tsubst (decl, args, complain, in_decl);
            init = tsubst_expr (init, args, complain, in_decl);
            DECL_INITIAL (decl) = init;
-           /* 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 all that
-          needs to be done, that's the right thing to do.  */
+           /* 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
+              all that needs to be done, that's the right thing to
+              do.  */
            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);
          }
        resume_momentary (i);
index 382258b3b89fd31d9bbeba70097f160b3de4fe1a..6e0c5b23afc8e25635414d4b82bfa83363950585 100644 (file)
@@ -2046,7 +2046,11 @@ expand_stmt (t)
            if (TREE_CODE (decl) == VAR_DECL)
              DECL_DEAD_FOR_LOCAL (decl) = 0;
            maybe_push_decl (decl);
-           cp_finish_decl (decl, DECL_INITIAL (decl), NULL_TREE, 0, 0);
+           if (TREE_CODE (decl) == VAR_DECL && !TREE_STATIC (decl))
+             {
+               maybe_inject_for_scope_var (decl);
+               initialize_local_var (decl, DECL_INITIAL (decl), 0);
+             }
          }
        resume_momentary (i);
       }
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/crash52.C b/gcc/testsuite/g++.old-deja/g++.pt/crash52.C
new file mode 100644 (file)
index 0000000..4d2de61
--- /dev/null
@@ -0,0 +1,25 @@
+// Build don't link:
+// Origin: Mark Mitchell <mark@codesourcery.com>
+
+template <class T>
+struct S1
+{
+  template <class U>
+  struct S2
+  { 
+    S2(U);
+  };
+
+  template <class U>
+  void f(U u)
+    {
+      S2<U> s2u(u);
+    }
+};
+
+void g()
+{
+  S1<int> s1;
+  s1.f(3.0);
+}
+