This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH to avoid template crash
- To: egcs-patches at cygnus dot com
- Subject: C++ PATCH to avoid template crash
- From: Mark Mitchell <mark at markmitchell dot com>
- Date: Fri, 26 Feb 1999 12:06:43 -0800
- Reply-to: mark at markmitchell dot com
Here's a patch to fix a case where we attempted to instantiate a
declaration more than once, and confused ourselves in the process.
--
Mark Mitchell mark@markmitchell.com
Mark Mitchell Consulting http://www.markmitchell.com
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: testsuite/g++.old-deja/g++.pt/crash29.C
===================================================================
RCS file: crash29.C
diff -N crash29.C
*** /dev/null Sat Dec 5 20:30:03 1998
--- crash29.C Fri Feb 26 11:46:41 1999
***************
*** 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> ;
+
Index: testsuite/cp/decl.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/decl.c,v
retrieving revision 1.312
diff -c -p -r1.312 decl.c
*** decl.c 1999/02/21 16:38:14 1.312
--- decl.c 1999/02/26 19:46:54
*************** duplicate_decls (newdecl, olddecl)
*** 3319,3324 ****
--- 3319,3326 ----
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: testsuite/cp/pt.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/pt.c,v
retrieving revision 1.264
diff -c -p -r1.264 pt.c
*** pt.c 1999/02/21 16:38:19 1.264
--- pt.c 1999/02/26 19:47:05
*************** regenerate_decl_from_template (decl, tmp
*** 9047,9054 ****
/* Pop the class context we pushed above. */
popclass (1);
}
!
! if (TREE_CODE (decl) == FUNCTION_DECL)
{
/* Convince duplicate_decls to use the DECL_ARGUMENTS from the
new decl. */
--- 9047,9053 ----
/* Pop the class context we pushed above. */
popclass (1);
}
! else if (TREE_CODE (decl) == FUNCTION_DECL)
{
/* Convince duplicate_decls to use the DECL_ARGUMENTS from the
new decl. */
*************** instantiate_decl (d)
*** 9243,9250 ****
goto out;
}
! regenerate_decl_from_template (d, td);
DECL_TEMPLATE_INSTANTIATED (d) = 1;
/* We already set the file and line above. Reset them now in case
they changed as a result of calling regenerate_decl_from_template. */
--- 9242,9255 ----
goto out;
}
! /* 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. */
Index: testsuite/cp/tree.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/tree.c,v
retrieving revision 1.96
diff -c -p -r1.96 tree.c
*** tree.c 1999/02/18 20:44:21 1.96
--- tree.c 1999/02/26 19:47:08
*************** mapcar (t, func)
*** 1846,1856 ****
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;
case PARM_DECL:
{
--- 1846,1858 ----
void g() { const int i = 7; f<i>(7); }
however, we must actually return the constant initializer. */
! 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:
{