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:
parent
38a843911d
commit
cec24319c6
@ -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.
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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))
|
||||
|
@ -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.
|
||||
|
||||
|
25
gcc/testsuite/g++.dg/template/static3.C
Normal file
25
gcc/testsuite/g++.dg/template/static3.C
Normal 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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user