diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index bb8678e774a..8ae05c0e4ec 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2004-10-14 Mark Mitchell + + PR c++/17976 + * decl.c (cp_finish_decl): Do not call expand_static_init more + than once for a single variable. + 2004-10-14 Matt Austern * Make-lang.in (pt.o): depends on pointer-set.h diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index f0775662d26..ee7e48143f8 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -4763,6 +4763,7 @@ cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags) tree cleanup; const char *asmspec = NULL; int was_readonly = 0; + bool var_definition_p = false; if (decl == error_mark_node) return; @@ -4904,6 +4905,11 @@ cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags) /* Remember that the initialization for this variable has taken place. */ DECL_INITIALIZED_P (decl) = 1; + /* This declaration is the definition of this variable, + unless we are initializing a static data member within + the class specifier. */ + if (!DECL_EXTERNAL (decl)) + var_definition_p = true; /* The variable is being defined, so determine its visibility. */ determine_visibility (decl); @@ -4969,10 +4975,18 @@ cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags) else if (!TREE_STATIC (decl)) initialize_local_var (decl, init); } - - if (TREE_STATIC (decl)) - expand_static_init (decl, init); - } + + /* If a variable is defined, and then a subsequent + definintion with external linkage is encountered, we will + get here twice for the same variable. We want to avoid + calling expand_static_init more than once. For variables + that are not static data members, we can call + expand_static_init only when we actually process the + initializer. It is not legal to redeclare a static data + member, so this issue does not arise in that case. */ + if (var_definition_p && TREE_STATIC (decl)) + expand_static_init (decl, init); + } } /* If a CLEANUP_STMT was created to destroy a temporary bound to a diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 5840d8e9116..1acfe77ab56 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2004-10-14 Mark Mitchell + + PR c++/17976 + * g++.dg/init/dtor3.C: New test. + 2004-10-15 Ben Elliston * gcc.dg/ppc-stackalign-1.c: Set dg-options to {}. diff --git a/gcc/testsuite/g++.dg/init/dtor3.C b/gcc/testsuite/g++.dg/init/dtor3.C new file mode 100644 index 00000000000..2af1ffe4634 --- /dev/null +++ b/gcc/testsuite/g++.dg/init/dtor3.C @@ -0,0 +1,21 @@ +// PR c++/17976 +// { dg-do run } + +extern "C" void abort(); +struct A +{ + static int i; + A(){} + ~A(){i++;if(i>1)abort();} +}; + +int A::i = 0; + +A a; +extern A a; + +int main() +{ + return 0; +} +