decl.c (duplicate_decls): Copy DECL_TEMPLATE_INSTANTIATED when merging decls.
authorMark Mitchell <mark@markmitchell.com>
Fri, 26 Feb 1999 12:11:43 +0000 (12:11 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Fri, 26 Feb 1999 12:11:43 +0000 (12:11 +0000)
* decl.c (duplicate_decls): Copy DECL_TEMPLATE_INSTANTIATED when
merging decls.
* pt.c (regenerate_decl_from_template): Tweak for clarity.
(instantiate_decl): Mark a decl instantiated before regenerating
it to avoid recursion.
* tree.c (mapcar): Don't call decl_constant_value unless we know
something is TREE_READONLY_DECL_P.

From-SVN: r25458

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

index e9f87d7..4424a32 100644 (file)
@@ -1,5 +1,13 @@
 1999-02-26  Mark Mitchell  <mark@markmitchell.com>
 
+       * decl.c (duplicate_decls): Copy DECL_TEMPLATE_INSTANTIATED when
+       merging decls.
+       * pt.c (regenerate_decl_from_template): Tweak for clarity.
+       (instantiate_decl): Mark a decl instantiated before regenerating
+       it to avoid recursion.
+       * tree.c (mapcar): Don't call decl_constant_value unless we know
+       something is TREE_READONLY_DECL_P.
+
        * class.c (check_for_override): Don't stop checking when we find
        the first overridden function.  Delete #if 0'd code.
        * search.c (get_matching_virtual): Likewise.
index 4cd37a7..c18eab7 100644 (file)
@@ -3319,6 +3319,8 @@ duplicate_decls (newdecl, olddecl)
       DECL_INTERFACE_KNOWN (newdecl) |= DECL_INTERFACE_KNOWN (olddecl);
       DECL_NOT_REALLY_EXTERN (newdecl) |= DECL_NOT_REALLY_EXTERN (olddecl);
       DECL_COMDAT (newdecl) |= DECL_COMDAT (olddecl);
+      DECL_TEMPLATE_INSTANTIATED (newdecl) 
+       |= DECL_TEMPLATE_INSTANTIATED (olddecl);
       /* Don't really know how much of the language-specific
         values we should copy from old to new.  */
       DECL_IN_AGGR_P (newdecl) = DECL_IN_AGGR_P (olddecl);
index b13a8c8..0f6d228 100644 (file)
@@ -9053,8 +9053,7 @@ regenerate_decl_from_template (decl, tmpl)
       /* Pop the class context we pushed above.  */
       popclass (1);
     }
-
-  if (TREE_CODE (decl) == FUNCTION_DECL)
+  else if (TREE_CODE (decl) == FUNCTION_DECL)
     {
       /* Convince duplicate_decls to use the DECL_ARGUMENTS from the
         new decl.  */ 
@@ -9249,9 +9248,15 @@ instantiate_decl (d)
       goto out;
     }
 
-  regenerate_decl_from_template (d, td);
+  /* We're now committed to instantiating this template.  Mark it as
+     instantiated so that recursive calls to instantiate_decl do not
+     try to instantiate it again.  */
   DECL_TEMPLATE_INSTANTIATED (d) = 1;
 
+  /* Regenerate the declaration in case the template has been modified
+     by a subsequent redeclaration.  */
+  regenerate_decl_from_template (d, td);
+
   /* We already set the file and line above.  Reset them now in case
      they changed as a result of calling regenerate_decl_from_template.  */
   lineno = DECL_SOURCE_LINE (d);
index 323532a..6d6fc43 100644 (file)
@@ -1846,11 +1846,13 @@ mapcar (t, func)
            void g() { const int i = 7; f<i>(7); }
 
         however, we must actually return the constant initializer.  */
-      tmp = decl_constant_value (t);
-      if (tmp != t)
-       return mapcar (tmp, func);
-      else
-       return error_mark_node;
+      if (TREE_READONLY_DECL_P (t))
+       {
+         tmp = decl_constant_value (t);
+         if (tmp != t)
+           return mapcar (tmp, func);
+       }
+      return error_mark_node;
 
     case PARM_DECL:
       {
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/crash29.C b/gcc/testsuite/g++.old-deja/g++.pt/crash29.C
new file mode 100644 (file)
index 0000000..5910064
--- /dev/null
@@ -0,0 +1,69 @@
+// Build don't link:
+// Origin: Steven Parkes <parkes@sierravista.com>
+
+typedef unsigned int size_t;
+
+class UUId {};
+
+template <class T> class MetaClass;
+
+class TypeInfo;
+
+struct MetaClassGeneric 
+{
+                                MetaClassGeneric( TypeInfo& );
+};
+
+struct TypeInfo 
+{
+                        void    (*constructor)( void* );
+                        void    initialize( void* );
+};
+
+template <class T>
+class TypeIDInit {
+public:
+                                TypeIDInit();
+                 static void    initialize();
+             static TypeInfo    info;
+                  static int    storage[];
+                 static void    metaclassConstructor( void* );
+};
+
+template <class T>
+TypeInfo TypeIDInit<T>::info = 
+{
+  TypeIDInit<T>::metaclassConstructor
+};
+
+template <class T>
+inline
+TypeIDInit<T>::TypeIDInit()
+{
+  info.initialize(storage);
+}
+
+template <class T>
+class NameInfo : public MetaClassGeneric {
+public:
+                                NameInfo() 
+                               : MetaClassGeneric( TypeIDInit<T>::info ) {}
+};
+
+class MetaClass<UUId>
+: public NameInfo<UUId>
+{
+};
+
+extern "C++"
+inline void *operator new(size_t, void *place) throw() { return place; }
+
+template <class T>
+void
+TypeIDInit<T>::metaclassConstructor( void* place )
+{
+  new ( place ) MetaClass<T>;
+}
+
+template class   TypeIDInit<UUId>   ;
+