semantics.c (finish_stmt_expr): Fix typo in comment.
authorMark Mitchell <mark@codesourcery.com>
Fri, 20 Aug 1999 22:07:22 +0000 (22:07 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Fri, 20 Aug 1999 22:07:22 +0000 (22:07 +0000)
* semantics.c (finish_stmt_expr): Fix typo in comment.
* tree.c (search_tree): Handle EXIT_EXPR, LOOP_EXPR.
(mapcar): Likewise.
* init.c (build_vec_delete_1): Make the children of a permanent
BIND_EXPR permanent.
* pt.c (register_specialization): Don't register a specialization
more than once.

From-SVN: r28781

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

index dd846fdf5722c1436d067f9b29dfc7f4ef1856b1..527783ddbc87cb30c990fd26c7ff31674f330783 100644 (file)
@@ -1,3 +1,13 @@
+1999-08-20  Mark Mitchell  <mark@codesourcery.com>
+
+       * semantics.c (finish_stmt_expr): Fix typo in comment.
+       * tree.c (search_tree): Handle EXIT_EXPR, LOOP_EXPR.
+       (mapcar): Likewise.
+       * init.c (build_vec_delete_1): Make the children of a permanent
+       BIND_EXPR permanent.
+       * pt.c (register_specialization): Don't register a specialization
+       more than once.
+       
 1999-08-18  Andrew Haley  <aph@cygnus.com>
 
        * method.c (process_overload_item): Call build_mangled_C9x_name ()
index f8c1980d214a612f77d78d3c2e74507345b7923c..ac962f6032a07255a2687f5814d9f65949c26b81 100644 (file)
@@ -2673,6 +2673,15 @@ build_vec_delete_1 (base, maxindex, type, auto_delete_vec, auto_delete,
 
   if (controller)
     {
+      /* The CONTROLLER is a BIND_EXPR.  Such things are always
+        allocated on at least the saveable obstack.  Since we may
+        need to copy this expression to the permanent obstack, we
+        must make sure that the operand is on the same obstack as the
+        BIND_EXPR.  Otherwise, copy_to_permanent will not copy the
+        operand, since it will assume that anything under a permanent
+        node is permanent.  */
+      if (TREE_PERMANENT (controller))
+       body = copy_to_permanent (body);
       TREE_OPERAND (controller, 1) = body;
       return controller;
     }
index 1940cfe0d6f8f22db0568498b5290c52aba940d0..b62dc752885427c0d5cd17295a343e41f89a28b5 100644 (file)
@@ -842,59 +842,68 @@ register_specialization (spec, tmpl, args)
   for (s = DECL_TEMPLATE_SPECIALIZATIONS (tmpl);
        s != NULL_TREE;
        s = TREE_CHAIN (s))
-    if (comp_template_args (TREE_PURPOSE (s), args))
-      {
-       tree fn = TREE_VALUE (s);
+    {
+      tree fn = TREE_VALUE (s);
 
-       if (DECL_TEMPLATE_SPECIALIZATION (spec))
-         {
-           if (DECL_TEMPLATE_INSTANTIATION (fn))
-             {
-               if (TREE_USED (fn) 
-                   || DECL_EXPLICIT_INSTANTIATION (fn))
-                 {
-                   cp_error ("specialization of %D after instantiation",
-                             fn);
-                   return spec;
-                 }
-               else
-                 {
-                   /* This situation should occur only if the first
-                      specialization is an implicit instantiation,
-                      the second is an explicit specialization, and
-                      the implicit instantiation has not yet been
-                      used.  That situation can occur if we have
-                      implicitly instantiated a member function and
-                      then specialized it later.
-
-                      We can also wind up here if a friend
-                      declaration that looked like an instantiation
-                      turns out to be a specialization:
-
-                        template <class T> void foo(T);
-                        class S { friend void foo<>(int) };
-                        template <> void foo(int);  
-
-                      We transform the existing DECL in place so that
-                      any pointers to it become pointers to the
-                      updated declaration.  
-
-                      If there was a definition for the template, but
-                      not for the specialization, we want this to
-                      look as if there is no definition, and vice
-                      versa.  */
-                   DECL_INITIAL (fn) = NULL_TREE;
-                   duplicate_decls (spec, fn);
-
-                   return fn;
-                 }
-             }
-           else if (DECL_TEMPLATE_SPECIALIZATION (fn))
-             {
-               duplicate_decls (spec, fn);
-               return fn;
-             }
-         }
+      /* We can sometimes try to re-register a specialization that we've
+        already got.  In particular, regenerate_decl_from_template
+        calls duplicate_decls which will update the specialization
+        list.  But, we'll still get called again here anyhow.  It's
+        more convenient to simply allow this than to try to prevent it.  */
+      if (fn == spec)
+       return spec;
+      else if (comp_template_args (TREE_PURPOSE (s), args))
+       {
+         if (DECL_TEMPLATE_SPECIALIZATION (spec))
+           {
+             if (DECL_TEMPLATE_INSTANTIATION (fn))
+               {
+                 if (TREE_USED (fn) 
+                     || DECL_EXPLICIT_INSTANTIATION (fn))
+                   {
+                     cp_error ("specialization of %D after instantiation",
+                               fn);
+                     return spec;
+                   }
+                 else
+                   {
+                     /* This situation should occur only if the first
+                        specialization is an implicit instantiation,
+                        the second is an explicit specialization, and
+                        the implicit instantiation has not yet been
+                        used.  That situation can occur if we have
+                        implicitly instantiated a member function and
+                        then specialized it later.
+
+                        We can also wind up here if a friend
+                        declaration that looked like an instantiation
+                        turns out to be a specialization:
+
+                          template <class T> void foo(T);
+                          class S { friend void foo<>(int) };
+                          template <> void foo(int);  
+
+                        We transform the existing DECL in place so that
+                        any pointers to it become pointers to the
+                        updated declaration.  
+
+                        If there was a definition for the template, but
+                        not for the specialization, we want this to
+                        look as if there is no definition, and vice
+                        versa.  */
+                     DECL_INITIAL (fn) = NULL_TREE;
+                     duplicate_decls (spec, fn);
+
+                     return fn;
+                   }
+               }
+             else if (DECL_TEMPLATE_SPECIALIZATION (fn))
+               {
+                 duplicate_decls (spec, fn);
+                 return fn;
+               }
+           }
+       }
       }
 
   DECL_TEMPLATE_SPECIALIZATIONS (tmpl)
index def1276bffc489927ae05b062df8f67bca88106b..d11bb9058322ce064094015c68f632ff3318f9eb 100644 (file)
@@ -1057,7 +1057,7 @@ finish_stmt_expr (rtl_expr, expr)
 
   if (TREE_CODE (expr) == BLOCK)
     {
-      /* Make a CP_BIND_EXPR for the BLOCK already made.  */
+      /* Make a BIND_EXPR for the BLOCK already made.  */
       if (building_stmt_tree ())
        {
          result = build_min (STMT_EXPR, last_expr_type, last_tree);
index 8d367535ba06e67be42c8361c493094f4112fc11..808e829e8c0b1bb3e2cd48194343c9ecc155d5aa 100644 (file)
@@ -1668,6 +1668,8 @@ search_tree (t, func)
     case CLEANUP_POINT_EXPR:
     case LOOKUP_EXPR:
     case THROW_EXPR:
+    case EXIT_EXPR:
+    case LOOP_EXPR:
       TRY (TREE_OPERAND (t, 0));
       break;
 
@@ -2001,6 +2003,8 @@ mapcar (t, func)
       return t;
 
     case LOOKUP_EXPR:
+    case EXIT_EXPR:
+    case LOOP_EXPR:
       t = copy_node (t);
       TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func);
       return t;
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/crash49.C b/gcc/testsuite/g++.old-deja/g++.pt/crash49.C
new file mode 100644 (file)
index 0000000..b9f7801
--- /dev/null
@@ -0,0 +1,37 @@
+// Build don't link:
+// Origin: Loring Holden <lsh@cs.brown.edu> 
+
+template <class T>
+class REFptr {
+   public:
+      virtual ~REFptr();
+      REFptr<T> &operator =  (const REFptr<T>& p);
+};
+
+class STR { };
+class str_ptr : public REFptr<STR> { };
+
+template <class T>
+class ARRAY {
+ protected:
+   T      *_array; 
+   int     _num;   
+   int     _max;  
+ public:
+   virtual void realloc(int new_max) {
+       _max = new_max;
+       T *tmp = new T [_max];
+       if (tmp == 0) return;
+       for (int i=0; i<_num; i++) {
+          tmp[i] = _array[i];
+       }
+       delete [] _array;
+       _array = tmp;
+   }
+};
+
+int
+main()
+{
+   ARRAY<str_ptr> tags;
+}