aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>2003-02-26 05:39:01 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>2003-02-26 05:39:01 +0000
commitcec24319c61d616dc10f918187a72a9622180821 (patch)
treec5c90ab38ff9bf5549a387a267d1e8f572227552 /gcc
parent38a843911d49becd4f01c6b8badebe19fb25682a (diff)
downloadgcc-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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog8
-rw-r--r--gcc/cp/decl2.c39
-rw-r--r--gcc/cp/pt.c8
-rw-r--r--gcc/testsuite/ChangeLog3
-rw-r--r--gcc/testsuite/g++.dg/template/static3.C25
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;
+}