While chasing two testsuite fails for -Os this wrong-code bug surfaced.
Fix tested on x86_64-linux/darwin. OK for trunk / backports?
thanks
Iain
--- 8< ---
For Darwin, at least, when -Os is selected we attempt to declone cdtors
since the platform does not support strong symbol aliases the clones
are emitted verbatim, leading to larger binaries.
The unified cdtor is a private implementational detail local to a TU
and so we should not emit a thunk if that will not be emitted.
Likewise, a thunk and the unified body must be selected together at
link time; for a vague-linkage cdtor COMDAT groups support this but,
without COMDAT, there is no guarantee and so we have to decline the
declone and emit ordinary clones instead.
gcc/cp/ChangeLog:
* optimize.cc (maybe_thunk_body): Decline declone for targets
without COMDAT when the item is vague-linkage.
gcc/testsuite/ChangeLog:
* g++.dg/opt/declone4.C: New test.
* g++.dg/opt/declone5.C: New test.
Signed-off-by: Iain Sandoe <[email protected]>
---
gcc/cp/optimize.cc | 8 +++++++
gcc/testsuite/g++.dg/opt/declone4.C | 37 +++++++++++++++++++++++++++++
gcc/testsuite/g++.dg/opt/declone5.C | 33 +++++++++++++++++++++++++
3 files changed, 78 insertions(+)
create mode 100644 gcc/testsuite/g++.dg/opt/declone4.C
create mode 100644 gcc/testsuite/g++.dg/opt/declone5.C
diff --git a/gcc/cp/optimize.cc b/gcc/cp/optimize.cc
index 0afeefd5704..d81e8e4ba15 100644
--- a/gcc/cp/optimize.cc
+++ b/gcc/cp/optimize.cc
@@ -287,6 +287,14 @@ maybe_thunk_body (tree fn, bool force)
if (ctor_omit_inherited_parms (fns[0]))
return 0;
+ /* A thunk and the unified body must be selected together at link time;
+ for a vague-linkage cdtor COMDAT groups support this. Without COMDAT
+ there is no guarantee and so we have to decline and emit ordinary clones
+ instead. FORCE means the body must not be copied at all, so it is still
+ honoured. */
+ if (!force && DECL_WEAK (fn) && !HAVE_COMDAT_GROUP)
+ return 0;
+
/* Don't diagnose deprecated or unavailable cdtors just because they
have thunks emitted for them. */
auto du = make_temp_override (deprecated_state,
diff --git a/gcc/testsuite/g++.dg/opt/declone4.C
b/gcc/testsuite/g++.dg/opt/declone4.C
new file mode 100644
index 00000000000..1d3f87d3126
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/declone4.C
@@ -0,0 +1,37 @@
+// { dg-do run }
+// { dg-options "-fdeclone-ctor-dtor -save-temps" }
+
+// A cdtor whose unified body this translation unit does emit should be
+// decloned. The C1/C2 clones become thunks and the unified C4 body is
+// emitted either private to the translation unit here, or to the COMDAT
+// group on targets that support them.
+
+struct V { int v; V (); };
+V::V () : v (1) {}
+
+struct B : virtual V
+{
+ int n;
+ B (int);
+};
+
+B::B (int x) : n (x * 3 + 1) {}
+
+struct D : B // uses B::C2
+{
+ D (int x) : B (x) {}
+};
+
+B *p;
+D *q;
+
+int
+main ()
+{
+ p = new B (2); // uses B::C1
+ q = new D (5);
+ return !(p->n == 7 && q->n == 16 && p->v == 1 && q->v == 1);
+}
+
+// { dg-final { scan-assembler "_ZN1BC4Ei" } }
+// { dg-final { scan-assembler-not "globl\[^\n\]*_ZN1BC4Ei" } }
diff --git a/gcc/testsuite/g++.dg/opt/declone5.C
b/gcc/testsuite/g++.dg/opt/declone5.C
new file mode 100644
index 00000000000..d714f99de40
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/declone5.C
@@ -0,0 +1,33 @@
+// { dg-do run }
+// { dg-options "-fdeclone-ctor-dtor -save-temps" }
+
+// We cannot emit a thunk to a unified cdtor on targets without comdat
+// support, since the thunk and the target must be selected together for
+// vague linkage.
+
+struct V { int v; V () : v (1) {} };
+
+template <typename T>
+struct B : virtual V
+{
+ T n;
+ B (T x) : n (x * 3 + 1) {}
+};
+
+struct D : B<int> // uses B<int>::C2
+{
+ D (int x) : B<int> (x) {}
+};
+
+B<int> *p;
+D *q;
+
+int
+main ()
+{
+ p = new B<int> (2); // uses B<int>::C1
+ q = new D (5);
+ return !(p->n == 7 && q->n == 16 && p->v == 1 && q->v == 1);
+}
+
+// { dg-final { scan-assembler-not "_ZN1BIiEC4Ei" { target { ! comdat_group }
} } }
--
2.50.1 (Apple Git-155)