From 2b0a63a35b58c529363c6ed6db01f26d9cfa737f Mon Sep 17 00:00:00 2001 From: Mark Mitchell Date: Fri, 26 Feb 1999 12:11:43 +0000 Subject: [PATCH] decl.c (duplicate_decls): Copy DECL_TEMPLATE_INSTANTIATED when merging decls. * 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 | 8 +++ gcc/cp/decl.c | 2 + gcc/cp/pt.c | 11 +++- gcc/cp/tree.c | 12 ++-- gcc/testsuite/g++.old-deja/g++.pt/crash29.C | 69 +++++++++++++++++++++ 5 files changed, 94 insertions(+), 8 deletions(-) create mode 100644 gcc/testsuite/g++.old-deja/g++.pt/crash29.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index e9f87d733c7..4424a3230f2 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,13 @@ 1999-02-26 Mark Mitchell + * 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. diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 4cd37a7a3ff..c18eab7fc3b 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -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); diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index b13a8c832eb..0f6d228a92a 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -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); diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 323532a3ea0..6d6fc43cccf 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -1846,11 +1846,13 @@ mapcar (t, func) void g() { const int i = 7; f(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 index 00000000000..59100649cb8 --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.pt/crash29.C @@ -0,0 +1,69 @@ +// Build don't link: +// Origin: Steven Parkes + +typedef unsigned int size_t; + +class UUId {}; + +template class MetaClass; + +class TypeInfo; + +struct MetaClassGeneric +{ + MetaClassGeneric( TypeInfo& ); +}; + +struct TypeInfo +{ + void (*constructor)( void* ); + void initialize( void* ); +}; + +template +class TypeIDInit { +public: + TypeIDInit(); + static void initialize(); + static TypeInfo info; + static int storage[]; + static void metaclassConstructor( void* ); +}; + +template +TypeInfo TypeIDInit::info = +{ + TypeIDInit::metaclassConstructor +}; + +template +inline +TypeIDInit::TypeIDInit() +{ + info.initialize(storage); +} + +template +class NameInfo : public MetaClassGeneric { +public: + NameInfo() + : MetaClassGeneric( TypeIDInit::info ) {} +}; + +class MetaClass +: public NameInfo +{ +}; + +extern "C++" +inline void *operator new(size_t, void *place) throw() { return place; } + +template +void +TypeIDInit::metaclassConstructor( void* place ) +{ + new ( place ) MetaClass; +} + +template class TypeIDInit ; + -- 2.30.2