diff options
author | Mark Mitchell <mark@codesourcery.com> | 2003-02-26 05:39:01 +0000 |
---|---|---|
committer | Mark Mitchell <mmitchel@gcc.gnu.org> | 2003-02-26 05:39:01 +0000 |
commit | cec24319c61d616dc10f918187a72a9622180821 (patch) | |
tree | c5c90ab38ff9bf5549a387a267d1e8f572227552 | |
parent | 38a843911d49becd4f01c6b8badebe19fb25682a (diff) | |
download | gcc-cec24319c61d616dc10f918187a72a9622180821.zip gcc-cec24319c61d616dc10f918187a72a9622180821.tar.gz gcc-cec24319c61d616dc10f918187a72a9622180821.tar.bz2 |
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
-rw-r--r-- | gcc/cp/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 39 | ||||
-rw-r--r-- | gcc/cp/pt.c | 8 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 3 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/static3.C | 25 |
5 files changed, 68 insertions, 15 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 3f4c7f6..caa078c 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,11 @@ +2003-02-25 Mark Mitchell <mark@codesourcery.com> + + 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 <gdr@integrable-solutions.net> * decl.c (add_binding): Time TV_NAME_LOOKUP. diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index ae17403..52170da 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 a5425f3..9336d96 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 86887e8..12fce54 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,8 @@ 2003-02-25 Mark Mitchell <mark@codesourcery.com> + 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 0000000..65cf2c9 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/static3.C @@ -0,0 +1,25 @@ +template <class data> class foo +{ + public: + static const int a; + static const int b; + static const int c; + static const int d; +}; + +template <class data> const int foo<data>::a = 1; +template <class data> const int foo<data>::b = a; +template <class data> const int foo<data>::c = b; +template <class data> const int foo<data>::d = c; + +typedef foo<int> fooInt; + +int main( void ) +{ + fooInt *f; + + f = new fooInt(); + + if (f->c != 1 || f->d != 1) + return 1; +} |