Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clang fails to export a single default destructor (out of thousands) #143

Closed
bog-dan-ro opened this issue Jun 30, 2016 · 10 comments
Closed
Labels

Comments

@bog-dan-ro
Copy link

What happens is so strange and very hard to reproduce and debug. Basically clang fails to export a single default destructor and I had to do this https://codereview.qt-project.org/#/c/160374/ workarround. Qt has probably hundreds or even thousands of default destructors which are exported correctly by clang, but somehow, only this one fails to export it.

Sadly, it was impossible for me to come with a simple example ... so in order to reproduce it you'll have to compile the entire Qt. Because there are a few pending patches that you need to apply first, please let me know when you want to start working on this bug to tell you the steps.
If I'll write them now, probably in a few weeks they will be outdated.

@DanAlbert DanAlbert added the clang label Jul 1, 2016
qtprojectorg pushed a commit to qt/qtconnectivity that referenced this issue Jul 19, 2016
Somehow clang fails to properly export the default destructor.

Should be revered when android/ndk#143 is fixed.

Change-Id: I842f4141f249181ec871634b947e1c08470ddb83
Reviewed-by: Eskil Abrahamsen Blomfeldt <[email protected]>
@pirama-arumuga-nainar
Copy link
Collaborator

@bog-dan-ro Can you provide instructions to reproduce the issue?

@bog-dan-ro
Copy link
Author

Yep, you must compile the entire Qt in order to reproduce it.
To do that you'll need a linux box and to run the following commands:

$ git clone -b 5.7 git://code.qt.io/qt/qt5.git
$ cd qt5

Next command will clone all qt submodules and might take some time, we're skipping qtwebkit qtwebkit-examples qtwebengine
$ ./init-repository -f --ignore-submodules qtwebkit qtwebkit-examples qtwebengine

After the above command succeeds you need to go to qtconnectivity and revert the workaround
$ cd qtconectivity 
$ git revert 19e3ad566f77a5040781
$ cd ..

Next step is to configure Qt, by running configure script from top qt5 folder (not from qtbase)
Qt needs an NDK and an SDK with  API 16(or better), latest tools & platform tools installed.

$ ./configure -xplatform android-clang -nomake tests -nomake examples -android-ndk /home/taipan/android/android-ndk -android-sdk /home/taipan/android/android-sdk -skip qtwebkit -skip qtserialport -skip qtwebkit-examples -skip qttranslations -developer-build -release

Replace /home/taipan/android/android-ndk/sdk with your paths

If the configure script succeeds, you can start to build it:
$ make -j10
The build take some time to complete (well in our case to fail), and should stop in qtconnectivity complaining that there is no QLlcpServerPrivate::~QLlcpServerPrivate.


*IF* you want to compile Qt using gcc, you need to clean everything (or clone it in another folder) and rerun configure script, with -xplatform android-g++ instead of -xplatform android-clang:

$ ./configure -xplatform android-g++ -nomake tests -nomake examples -android-ndk /home/taipan/android/android-ndk -android-sdk /home/taipan/android/android-sdk -skip qtwebkit -skip qtserialport -skip qtwebkit-examples -skip qttranslations -developer-build -release

compiling with gcc will also show you how big are the binaries produced by clang comparing with the ones produced by gcc

@pirama-arumuga-nainar If you need more info on this matter, please feel free to contact me (or other folks) on freenode #necessitas channel, or here.

@pirama-arumuga-nainar
Copy link
Collaborator

Is this with r12b? My build with r12b completed succesfully. I am doing a clean rebuild to double check.

@bog-dan-ro
Copy link
Author

Can you double check if you've reverted my patch?
Also please try to run make (with no -jX) in qtconectivity folder to be sure there is no error ?
I tried it with r12a, I thought r12b just have minor fixes to scripts not to clang compiler...

@pirama-arumuga-nainar
Copy link
Collaborator

I am able to see that error if I run make in qtconnectivity. Not sure why the top-level build succeeds.

I am trying to drop-in a newer Clang and reproduce.

@bog-dan-ro
Copy link
Author

It doesn't succeed, it's just hidden by themake -j10 which doesn't stop all jobs at first error. If you'll run only make (with no -jX) it will stop ;-)

BTW I created two more patches for clang:

You need to apply these two patches to qtbase, and you don't need to rebuild everything!
If you want to change the compiler/linker flags for clang, you need to edit qtbase/mkspecs/android-clang/qmake.conf . There are two more conf files (qtbase/mkspecs/common/android-base-head.conf and qtbase/mkspecs/common/android-base-tail.conf but most probably you'll not need to change them).

@pirama-arumuga-nainar
Copy link
Collaborator

There is an ODR violation here.

qllcpserver.cpp gets definition of class QLlcpServerPrivate from qllcpserver_p_p.h, which declares a (possibly) non-trivial destructor. So Clang generates an explicit call to the destructor in ~QLlcpServer.

OTOH, the definition of QLlcpServerPrivate in qllcpserver_android_p.h doesn't specify a destructor. Clang doesn't generate an explicit destructor probably because the trivial destructor can be inlined.

One possible design here seems to be for the class in qllcpserver_android_p.h to be a subclass of the one defined in qllcpserver_p_p.h

@pirama-arumuga-nainar
Copy link
Collaborator

PS: Not sure why gcc generates the destructor. Finding which object file among the gcc-built qllcpserver.o and qllcpserver_android.o has the destructor may shed some light.

@DanAlbert
Copy link
Member

Thanks for tracking that down, @pirama-arumuga-nainar!

@bog-dan-ro
Copy link
Author

Thanks a lot @pirama-arumuga-nainar, it was my fault because I didn't checked the code properly, sorry...
Indeed that part of the code is very wrong, the reviewers didn't spot the problems when it was contributed long time ago....

bjornmu pushed a commit to mysql/mysql-server that referenced this issue Jul 13, 2020
Post-push fix with workaround for clang 6.0.0 and clang 7.0.0 linking errors such as:
```
/usr/bin/ld.lld: error: undefined symbol: locksys::Latches::~Latches()
>>> referenced by lock0lock.cc:322 (/home/mhansson/gitroot/worktrees/with_time_zone/mysql-trunk/storage/innobase/lock/lock0lock.cc:322)
>>>               lock0lock.cc.o:(lock_sys_create(unsigned long)) in archive storage/innobase/libinnobase.a/usr/bin/ld.lld: error: undefined symbol: locksys::Latches::~Latches()
>>> referenced by lock0lock.h:942 (/home/mhansson/gitroot/worktrees/with_time_zone/mysql-trunk/storage/innobase/include/lock0lock.h:942)
>>>               lock0lock.cc.o:(lock_sys_t::~lock_sys_t()) in archive storage/innobase/libinnobase.a
clang: error: linker command failed with exit code 1 (use -v to see invocation)
```
These versions of clang (but not 8.0.0) do not handle `Latches::~Latches = default;` declaration correctly.
Removing it does not help either.
Adding explicit `inline` keyword does not help.
What apparently helps is to provide a destructor with an empty body.
This might be somehow connected to one of these:
     https://bugs.llvm.org/show_bug.cgi?id=28280
     android/ndk#143
     https://reviews.llvm.org/D45898
As there are minimal differences between "implicit", "defaulted" and "empty" destructor
(see https://stackoverflow.com/questions/56799129/when-to-make-a-destructor-defaulted-using-default for summary),
and certainly none that we care about here, we will cater to clang's needs and provide empty body instead of `= default`.

This patch also removes the declaration of explicitly defaulted default constructor, as simply omitting it should have same effect in our context.

Reviewed by: Nikša Skeledžija <[email protected]>
Reviewed by: Martin Hansson <[email protected]>
RB:24167
kamil-holubicki pushed a commit to kamil-holubicki/percona-xtradb-cluster that referenced this issue Jun 2, 2023
Post-push fix with workaround for clang 6.0.0 and clang 7.0.0 linking errors such as:
```
/usr/bin/ld.lld: error: undefined symbol: locksys::Latches::~Latches()
>>> referenced by lock0lock.cc:322 (/home/mhansson/gitroot/worktrees/with_time_zone/mysql-trunk/storage/innobase/lock/lock0lock.cc:322)
>>>               lock0lock.cc.o:(lock_sys_create(unsigned long)) in archive storage/innobase/libinnobase.a/usr/bin/ld.lld: error: undefined symbol: locksys::Latches::~Latches()
>>> referenced by lock0lock.h:942 (/home/mhansson/gitroot/worktrees/with_time_zone/mysql-trunk/storage/innobase/include/lock0lock.h:942)
>>>               lock0lock.cc.o:(lock_sys_t::~lock_sys_t()) in archive storage/innobase/libinnobase.a
clang: error: linker command failed with exit code 1 (use -v to see invocation)
```
These versions of clang (but not 8.0.0) do not handle `Latches::~Latches = default;` declaration correctly.
Removing it does not help either.
Adding explicit `inline` keyword does not help.
What apparently helps is to provide a destructor with an empty body.
This might be somehow connected to one of these:
     https://bugs.llvm.org/show_bug.cgi?id=28280
     android/ndk#143
     https://reviews.llvm.org/D45898
As there are minimal differences between "implicit", "defaulted" and "empty" destructor
(see https://stackoverflow.com/questions/56799129/when-to-make-a-destructor-defaulted-using-default for summary),
and certainly none that we care about here, we will cater to clang's needs and provide empty body instead of `= default`.

This patch also removes the declaration of explicitly defaulted default constructor, as simply omitting it should have same effect in our context.

Reviewed by: Nikša Skeledžija <[email protected]>
Reviewed by: Martin Hansson <[email protected]>
RB:24167
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants