Quuxplusone / LLVMBugzillaTest

0 stars 0 forks source link

Clang sometimes does not properly link classes inherited from dllimported classes #30799

Open Quuxplusone opened 7 years ago

Quuxplusone commented 7 years ago
Bugzilla Link PR31826
Status NEW
Importance P normal
Reported by marc@groundctl.com
Reported on 2017-01-31 13:18:43 -0800
Last modified on 2021-10-19 16:04:40 -0700
Version 3.9
Hardware PC other
CC cygnus@michiru.ru, jeremy@groundctl.com, llvm-bugs@lists.llvm.org, llvm-bugzilla@jdrake.com, martin@martin.st, rnk@google.com, zahira.ammarguellat@intel.com
Fixed by commit(s)
Attachments dllexportimport.tar.gz (809 bytes, application/x-gzip)
Blocks
Blocked by
See also https://github.com/msys2/MINGW-packages/issues/9804
Code is as follows:

==> x.cpp <==
#define DECL __declspec(dllexport)
#include "header.h"

==> y.cpp <==
#define DECL __declspec(dllimport)
#include "header.h"
int main() {
        t2 s;
}

==> header.h <==
struct DECL t {
        virtual void fun() = 0;
};
struct t2 : t {
        virtual void fun() {}
};

When using mingw64 6.2, if x.cpp is compiled as x.dll and y.cpp is compiled as
an executable linking x.dll, the linker fails with undefined references to
`_imp___ZTV1t' and `typeinfo for t'.  This code works fine with both gcc 6.2
and Visual Studio 2015.

Adding a virtual function to t defined in x.cpp causes this issue to go away.
Quuxplusone commented 7 years ago
Note that this code compiles without warnings when given "-Wall -Wextra", but
if given "-Weverything" produces the following warnings:

't' has virtual functions but non-virtual destructor [-Wnon-virtual-dtor]
't2' has virtual functions but non-virtual destructor [-Wnon-virtual-dtor]
't' has no out-of-line virtual method definitions; its vtable will be emitted
in every translation unit [-Wweak-vtables]
't2' has no out-of-line virtual method definitions; its vtable will be emitted
in every translation unit [-Wweak-vtables]
Quuxplusone commented 7 years ago
It looks like GCC gives special treatment to dllexported classes without key
functions. If you compile x.cpp in your example, GCC emits and exports a vtable
for t. Clang does not, but it should. If you change the definition of main like
so:

int main() { t2 *p = new t2; }

Then GCC will reference __imp__ZTV1t from y.obj as well.

By the way, this all works fine in MS ABI mode. We just need to enable some of
that logic on mingw.
Quuxplusone commented 7 years ago
I tried looking at this for a quick hack, but there's too much going on.

There are too many differences in how msys2-mingw64-g++ 7.1.0 and trunk clang
behave.
gcc does export typeinfo (_ZTI* symbols), while clang doesn't, gcc uses
.linkonce same_size in assembly, etc.

I've found an old attempt ( https://reviews.llvm.org/D1099 ) that actually
tested for proper typeinfo export, but trunk has diverged too much for me to
make any sense of this.

I've reduced a Qt link error to this bug, and boost fails to link apparently
for the same reason, which makes clang not very usable on mingw at the moment.
Quuxplusone commented 3 years ago

Attached dllexportimport.tar.gz (809 bytes, application/x-gzip): test case

Quuxplusone commented 3 years ago

This was with clang 13.0.0 targeting windows-gnu