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
This commit is contained in:
Mark Mitchell 2003-02-26 05:39:01 +00:00 committed by Mark Mitchell
parent 38a843911d
commit cec24319c6
5 changed files with 68 additions and 15 deletions

View File

@ -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.

View File

@ -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)
{

View File

@ -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))

View File

@ -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.

View File

@ -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;
}