jakub and richi analyzed this bug; normally we set DECL_EXTERNAL on all functions with vague linkage, but we were failing to do so for the synthesized destructor, which caused problems with devirtualization. Fixed thus.

Jakub tested the patch. Applying to trunk; will apply to 4.7 branch after 4.7.0.
commit a5e3b73aaee13ed672641faee53989785cffed83
Author: Jason Merrill <ja...@redhat.com>
Date:   Wed Mar 14 14:24:22 2012 -0400

    	PR c++/52582
    	* method.c (implicitly_declare_fn): Set DECL_EXTERNAL.

diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index 0718916..0d4793e 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -1593,6 +1593,7 @@ implicitly_declare_fn (special_function_kind kind, tree type, bool const_p)
       DECL_DELETED_FN (fn) = deleted_p;
       DECL_DECLARED_CONSTEXPR_P (fn) = constexpr_p;
     }
+  DECL_EXTERNAL (fn) = true;
   DECL_NOT_REALLY_EXTERN (fn) = 1;
   DECL_DECLARED_INLINE_P (fn) = 1;
   gcc_assert (!TREE_USED (fn));
diff --git a/gcc/testsuite/g++.dg/torture/pr52582.C b/gcc/testsuite/g++.dg/torture/pr52582.C
new file mode 100644
index 0000000..1b93fc4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr52582.C
@@ -0,0 +1,23 @@
+// PR c++/52582
+
+inline void *operator new (__SIZE_TYPE__, void *p) throw ()
+{
+  return p;
+}
+struct B
+{
+  virtual ~B ();
+  B ();
+};
+struct A : B
+{
+  A () : B () {}
+  virtual void bar ();
+};
+void
+foo ()
+{
+  char a[64];
+  B *b = new (&a) A ();
+  b->~B ();
+}

Reply via email to