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; }