107 lines
3.0 KiB
Diff
107 lines
3.0 KiB
Diff
From: Mark Mitchell <mark@codesourcery.com>
|
|
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 <mark@codesourcery.com>
|
|
# 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 <mark@codesourcery.com>
|
|
# 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:
|
|
|