From 2725073463dfe4d70a5111f6723a2f4ea36ba875 Mon Sep 17 00:00:00 2001 From: Mark Mitchell Date: Sat, 3 Sep 2005 18:18:48 +0000 Subject: [PATCH] re PR c++/23699 (rejects static int as non constant after "extern template") PR c++/23699 * decl2.c (mark_used): Always instantiate static data members initialized by constant expressions. * pt.c (instantiate_decl): Instantiate the initializers for static data members initialized by constant expressions. PR c++/21687 * semantics.c (expand_or_defer_fn): Do not call ggc_collect when finishing processing for a template function in a local class. Revert: 2005-09-02 Mark Mitchell * parser.c (cp_parser_class_specifier): Push/pop GC contexts around functions in local classes. PR c++/23699 * g++.dg/ext/static1.C: New test. From-SVN: r103806 --- gcc/cp/ChangeLog | 16 ++++++++++++++++ gcc/cp/decl2.c | 7 ++++++- gcc/cp/parser.c | 16 ---------------- gcc/cp/semantics.c | 7 +++++-- gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/g++.dg/ext/static1.C | 18 ++++++++++++++++++ 6 files changed, 50 insertions(+), 19 deletions(-) create mode 100644 gcc/testsuite/g++.dg/ext/static1.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 69e62c4600a..e9d3b2b011b 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,19 @@ +2005-09-03 Mark Mitchell + + PR c++/23699 + * decl2.c (mark_used): Always instantiate static data members + initialized by constant expressions. + * pt.c (instantiate_decl): Instantiate the initializers for static + data members initialized by constant expressions. + + PR c++/21687 + * semantics.c (expand_or_defer_fn): Do not call ggc_collect when + finishing processing for a template function in a local class. + Revert: + 2005-09-02 Mark Mitchell + * parser.c (cp_parser_class_specifier): Push/pop GC contexts + around functions in local classes. + 2005-09-02 Mark Mitchell PR c++/21687 diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 3821ab01115..75ec65f85b8 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -3270,7 +3270,12 @@ mark_used (tree decl) && (!DECL_EXPLICIT_INSTANTIATION (decl) || (TREE_CODE (decl) == FUNCTION_DECL && DECL_INLINE (DECL_TEMPLATE_RESULT - (template_for_substitution (decl)))))) + (template_for_substitution (decl)))) + /* We need to instantiate static data members so that there + initializers are available in integral constant + expressions. */ + || (TREE_CODE (decl) == VAR_DECL + && DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl)))) /* We put off instantiating functions in order to improve compile times. Maintaining a stack of active functions is expensive, and the inliner knows to instantiate any functions it might diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index f06640305bd..6feb114436a 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -12673,9 +12673,6 @@ cp_parser_class_specifier (cp_parser* parser) tree fn; tree class_type = NULL_TREE; tree pushed_scope = NULL_TREE; - /* True if we have called ggc_push_context, and therefore need - to make a matching call to ggc_pop_context. */ - bool need_ggc_pop_context; /* In a first pass, parse default arguments to the functions. Then, in a second pass, parse the bodies of the functions. @@ -12712,7 +12709,6 @@ cp_parser_class_specifier (cp_parser* parser) } if (pushed_scope) pop_scope (pushed_scope); - need_ggc_pop_context = false; /* Now parse the body of the functions. */ for (TREE_VALUE (parser->unparsed_functions_queues) = nreverse (TREE_VALUE (parser->unparsed_functions_queues)); @@ -12722,21 +12718,9 @@ cp_parser_class_specifier (cp_parser* parser) { /* Figure out which function we need to process. */ fn = TREE_VALUE (queue_entry); - /* We call ggc_collect after processing a function body in - order to clean up garbage generated. If we're processing - a local class, however, then we must not clean up stuff - from the function containing the class, so we have to - push a new garbage-collection context. */ - if (function_depth && !need_ggc_pop_context) - { - need_ggc_pop_context = true; - ggc_push_context (); - } /* Parse the function. */ cp_parser_late_parsing_for_member (parser, fn); } - if (need_ggc_pop_context) - ggc_pop_context (); } /* Put back any saved access checks. */ diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 528d8b7e6d0..dbdf74d0a94 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -3044,8 +3044,11 @@ expand_or_defer_fn (tree fn) /* Normally, collection only occurs in rest_of_compilation. So, if we don't collect here, we never collect junk generated during the processing of templates until we hit a - non-template function. */ - ggc_collect (); + non-template function. It's not safe to do this inside a + nested class, though, as the parser may have local state that + is not a GC root. */ + if (!function_depth) + ggc_collect (); return; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index ab29708f893..0abc44f94f1 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2005-09-03 Mark Mitchell + + PR c++/23699 + * g++.dg/ext/static1.C: New test. + 2005-09-02 Richard Henderson * gcc.c-torture/execute/frame-address.c (check_fa_mid): Avoid diff --git a/gcc/testsuite/g++.dg/ext/static1.C b/gcc/testsuite/g++.dg/ext/static1.C new file mode 100644 index 00000000000..9298b1d573b --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/static1.C @@ -0,0 +1,18 @@ +// PR c++/23699 +// { dg-options "" } + +template class basic_string; +typedef basic_string string; +template +struct basic_string +{ + static const int npos = -1; +}; +template +const int basic_string<_CharT>::npos; + +extern template class basic_string; +struct A +{ + static const long npos = string::npos; +};