aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/decl.c22
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/init/dtor3.C21
4 files changed, 50 insertions, 4 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index bb8678e..8ae05c0 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,9 @@
+2004-10-14 Mark Mitchell <mark@codesourcery.com>
+
+ 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 <austern@apple.com>
* Make-lang.in (pt.o): depends on pointer-set.h
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index f077566..ee7e481 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 5840d8e..1acfe77 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2004-10-14 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/17976
+ * g++.dg/init/dtor3.C: New test.
+
2004-10-15 Ben Elliston <bje@au.ibm.com>
* 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 0000000..2af1ffe
--- /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;
+}
+