From: Mark Mitchell Date: Wed, 26 Feb 2003 05:39:01 +0000 (+0000) Subject: re PR c++/9683 (bug in initialization chains for static const variables from template... X-Git-Tag: releases/gcc-3.4.0~8404 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=cec24319c61d616dc10f918187a72a9622180821;p=thirdparty%2Fgcc.git re PR c++/9683 (bug in initialization chains for static const variables from template classes) PR c++/9683 * decl2.c (prune_vars_needing_no_initialization): Do not throw away initializations for DECL_EXTERNAL VAR_DECLs. (finish_file): Adjust accordingly. * pt.c (instantiate_decl): Do not defer VAR_DECLs. PR c++/9683 * g++.dg/template/static3.C: New test. From-SVN: r63455 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 3f4c7f69f24f..caa078c36493 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,11 @@ +2003-02-25 Mark Mitchell + + PR c++/9683 + * decl2.c (prune_vars_needing_no_initialization): Do not throw + away initializations for DECL_EXTERNAL VAR_DECLs. + (finish_file): Adjust accordingly. + * pt.c (instantiate_decl): Do not defer VAR_DECLs. + 2003-02-24 Gabriel Dos Reis * decl.c (add_binding): Time TV_NAME_LOOKUP. diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index ae174034c083..52170daff2fa 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -84,7 +84,7 @@ static void finish_static_initialization_or_destruction (tree); static void generate_ctor_or_dtor_function (bool, int); static int generate_ctor_and_dtor_functions_for_priority (splay_tree_node, void *); -static tree prune_vars_needing_no_initialization (tree); +static tree prune_vars_needing_no_initialization (tree *); static void write_out_vars (tree); static void import_export_class (tree); static tree get_guard_bits (tree); @@ -2400,21 +2400,23 @@ do_static_destruction (tree decl) i.e., the first variable should be initialized first. */ static tree -prune_vars_needing_no_initialization (tree vars) +prune_vars_needing_no_initialization (tree *vars) { - tree var; - tree result; + tree *var = vars; + tree result = NULL_TREE; - for (var = vars, result = NULL_TREE; - var; - var = TREE_CHAIN (var)) + while (*var) { - tree decl = TREE_VALUE (var); - tree init = TREE_PURPOSE (var); + tree t = *var; + tree decl = TREE_VALUE (t); + tree init = TREE_PURPOSE (t); /* Deal gracefully with error. */ if (decl == error_mark_node) - continue; + { + var = &TREE_CHAIN (t); + continue; + } /* The only things that can be initialized are variables. */ my_friendly_assert (TREE_CODE (decl) == VAR_DECL, 19990420); @@ -2422,17 +2424,25 @@ prune_vars_needing_no_initialization (tree vars) /* If this object is not defined, we don't need to do anything here. */ if (DECL_EXTERNAL (decl)) - continue; + { + var = &TREE_CHAIN (t); + continue; + } /* Also, if the initializer already contains errors, we can bail out now. */ if (init && TREE_CODE (init) == TREE_LIST && value_member (error_mark_node, init)) - continue; + { + var = &TREE_CHAIN (t); + continue; + } /* This variable is going to need initialization and/or finalization, so we add it to the list. */ - result = tree_cons (init, decl, result); + *var = TREE_CHAIN (t); + TREE_CHAIN (t) = result; + result = t; } return result; @@ -2625,8 +2635,7 @@ finish_file () aggregates added during the initialization of these will be initialized in the correct order when we next come around the loop. */ - vars = prune_vars_needing_no_initialization (static_aggregates); - static_aggregates = NULL_TREE; + vars = prune_vars_needing_no_initialization (&static_aggregates); if (vars) { diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index a5425f34b4ab..9336d96c09d3 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -10647,6 +10647,14 @@ instantiate_decl (d, defer_ok) my_friendly_assert (TREE_CODE (d) == FUNCTION_DECL || TREE_CODE (d) == VAR_DECL, 0); + /* Variables are never deferred; if instantiation is required, they + are instantiated right away. That allows for better code in the + case that an expression refers to the value of the variable -- + if the variable has a constant value the referring expression can + take advantage of that fact. */ + if (TREE_CODE (d) == VAR_DECL) + defer_ok = 0; + /* Don't instantiate cloned functions. Instead, instantiate the functions they cloned. */ if (TREE_CODE (d) == FUNCTION_DECL && DECL_CLONED_FUNCTION_P (d)) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 86887e8482d2..12fce54444db 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,8 @@ 2003-02-25 Mark Mitchell + PR c++/9683 + * g++.dg/template/static3.C: New test. + PR c++/9829 * g++.dg/parse/namespace6.C: New test. diff --git a/gcc/testsuite/g++.dg/template/static3.C b/gcc/testsuite/g++.dg/template/static3.C new file mode 100644 index 000000000000..65cf2c9e7b21 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/static3.C @@ -0,0 +1,25 @@ +template class foo +{ + public: + static const int a; + static const int b; + static const int c; + static const int d; +}; + +template const int foo::a = 1; +template const int foo::b = a; +template const int foo::c = b; +template const int foo::d = c; + +typedef foo fooInt; + +int main( void ) +{ + fooInt *f; + + f = new fooInt(); + + if (f->c != 1 || f->d != 1) + return 1; +}