COFF targets currently do not support COMDAT groups. On MinGW targets
GCC instead puts symbols part of a COMDAT group inside of sections
annotated with the .linkonce GAS directive. This leads to GAS
generating a section so that the COMDAT name is the same as the name
of the actual symbol.

When using LTO however we never go through any of those mechanisms and
instead output the COMDAT into the LTO IR. This patch fixes this by
basically replicating the above chain by instead writing the name into
the IR file.

This case only occurs in cases where multiple inheritance is used and
non virtual thunks are created. This problem was found while trying to
compile Qt using LTO on a MinGW target. In the patch a minimal
reproducible testcase is added which fails to link without the patch
and links successfully with the patch. No regressions were observed in
the gcc and g++ testsuite after the patch has been added.

gcc/ChangeLog:

2020-07-16  Markus Böck  <markus.boec...@gmail.com>

    * lto-streamer-out.c (write_symol): Write symbol name instead of
COMDAT group
    on PE/COFF Targets

gcc/testsuite/ChangeLog:

2020-07-16  Markus Böck  <markus.boec...@gmail.com>

    * g++.dg/lto/virtual-thunk-comdat_0.C: New test.
    * g++.dg/lto/virtual-thunk-comdat.h: New test.
    * g++.dg/lto/virtual-thunk-comdat_1.C: New test.

------

Index: gcc/lto-streamer-out.c
===================================================================
--- gcc/lto-streamer-out.c (revision 932e9140d3268cf2033c1c3e93219541c53fcd29)
+++ gcc/lto-streamer-out.c (date 1594903384922)
@@ -2779,7 +2779,12 @@
     size = 0;

   if (DECL_ONE_ONLY (t))
+    {
+      if (TARGET_PECOFF)
+    comdat = name;
+      else
     comdat = IDENTIFIER_POINTER (decl_comdat_group_id (t));
+    }
   else
     comdat = "";

Index: gcc/testsuite/g++.dg/lto/virtual-thunk-comdat_0.C
===================================================================
--- gcc/testsuite/g++.dg/lto/virtual-thunk-comdat_0.C  (date 1594903164805)
+++ gcc/testsuite/g++.dg/lto/virtual-thunk-comdat_0.C  (date 1594903164805)
@@ -0,0 +1,15 @@
+// { dg-lto-do link }
+#include "virtual-thunk-comdat.h"
+
+QAccessibleInterface::~QAccessibleInterface() {}
+
+QAccessibleActionInterface::~QAccessibleActionInterface() {}
+
+QAccessibleEditableTextInterface::~QAccessibleEditableTextInterface() {}
+
+bool QAccessibleObject::isValid() const
+{
+  return false;
+}
+
+void QAccessibleLineEdit::deleteText(const char* string) {}
Index: gcc/testsuite/g++.dg/lto/virtual-thunk-comdat.h
===================================================================
--- gcc/testsuite/g++.dg/lto/virtual-thunk-comdat.h    (date 1594901724581)
+++ gcc/testsuite/g++.dg/lto/virtual-thunk-comdat.h    (date 1594901724581)
@@ -0,0 +1,39 @@
+
+class QAccessibleInterface
+{
+protected:
+  virtual ~QAccessibleInterface();
+
+public:
+  virtual bool isValid() const = 0;
+};
+
+class QAccessibleActionInterface
+{
+public:
+  virtual ~QAccessibleActionInterface();
+};
+
+class QAccessibleEditableTextInterface
+{
+public:
+  virtual ~QAccessibleEditableTextInterface();
+
+  virtual void deleteText(const char*) = 0;
+};
+
+class QAccessibleObject : public QAccessibleInterface
+{
+public:
+  bool isValid() const override;
+};
+
+class QAccessibleWidget : public QAccessibleObject, public
QAccessibleActionInterface
+{
+};
+
+class QAccessibleLineEdit : public QAccessibleWidget, public
QAccessibleEditableTextInterface
+{
+public:
+  void deleteText(const char* string) override;
+};
Index: gcc/testsuite/g++.dg/lto/virtual-thunk-comdat_1.C
===================================================================
--- gcc/testsuite/g++.dg/lto/virtual-thunk-comdat_1.C  (date 1594903161383)
+++ gcc/testsuite/g++.dg/lto/virtual-thunk-comdat_1.C  (date 1594903161383)
@@ -0,0 +1,3 @@
+#include "virtual-thunk-comdat.h"
+
+int main(int argc, char **argv) { QAccessibleLineEdit lineEdit; }

Reply via email to