From: Mark Mitchell Sender: gcc-patches-owner@gcc.gnu.org To: gcc-patches@gcc.gnu.org Subject: C++ PATCH: PR 17976 Date: Thu, 14 Oct 2004 21:24:41 -0700 This was a case where we generated multiple destructor calls for the same global variable, in the (probably rare) situation that an "extern" declaration followed the definition. Tested on i686-pc-linux-gnu, applied on the mainline and on the 3.4 branch. -- Mark Mitchell CodeSourcery, LLC mark@codesourcery.com # DP: 2004-10-14 Mark Mitchell # DP: # DP: PR c++/17976 # DP: * decl.c (cp_finish_decl): Do not call expand_static_init more # DP: than once for a single variable. # DP: # DP: 2004-10-14 Mark Mitchell # DP: # DP: PR c++/17976 # DP: * g++.dg/init/dtor3.C: New test. Index: testsuite/g++.dg/init/dtor3.C =================================================================== RCS file: testsuite/g++.dg/init/dtor3.C diff -N testsuite/g++.dg/init/dtor3.C *** /dev/null 1 Jan 1970 00:00:00 -0000 --- gcc/gcc/testsuite/g++.dg/init/dtor3.C 15 Oct 2004 04:02:22 -0000 *************** *** 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; + } + =================================================================== RCS file: /cvs/gcc/gcc/gcc/cp/decl.c,v retrieving revision 1.1174.2.26 retrieving revision 1.1174.2.27 diff -u -r1.1174.2.26 -r1.1174.2.27 --- gcc/gcc/cp/decl.c 2004/10/10 21:54:59 1.1174.2.26 +++ gcc/gcc/cp/decl.c 2004/10/15 04:23:46 1.1174.2.27 @@ -4778,6 +4778,7 @@ tree cleanup; const char *asmspec = NULL; int was_readonly = 0; + bool var_definition_p = false; if (decl == error_mark_node) return; @@ -4930,6 +4931,11 @@ /* 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; } /* If the variable has an array type, lay out the type, even if there is no initializer. It is valid to index through the @@ -5004,8 +5010,16 @@ 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); } finish_end0: