skeeto / w64devkit

Portable C and C++ Development Kit for x64 (and x86) Windows
The Unlicense
3k stars 211 forks source link

ld error: multiple definition of `std::type_info::operator==(std::type_info const&) const` #86

Closed xparq closed 8 months ago

xparq commented 1 year ago

w64devkit 1.20.0, both 32/64 bit (Tried to check with gcc12 in an older w64devkit which I also have here, but the project that triggers it depends on <format>.)

g++ -Wall --std=c++23 test.cpp
.../ld.exe: .../w64devkit/gcc13/64/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/libstdc++.a(tinfo.o):tinfo.cc:
(.text$_ZNKSt9type_infoeqERKS_+0x0): multiple definition of `std::type_info::operator==(std::type_info const&) const';
...\Temp\ccOVUCq4.o:test.cpp:(.text$_ZNKSt9type_infoeqERKS_[_ZNKSt9type_infoeqERKS_]+0x0): first defined here
collect2.exe: error: ld returned 1 exit status

  (Edited for readability.)

xparq commented 1 year ago

Yup, confirmed; this single line can trigger it:

std::regex("");

Probably the regex compiler. (Just std::regex(); is not enough.)

Ahh, and I guess the Debian version is only immune to it for the extensive shared linking by default.

skeeto commented 1 year ago

This appears to be a bug in libstdc++, perhaps related to static linking, which would explain why it's mostly gone unnoticed. (w64devkit's static linking libstdc++ is unusual.) I can reproduce it from the cppreference std::type_info::operator== example, even when reduced to:

include

int main() { return typeid(0) == typeid(0); }

It only occurs with -std=c++23, e.g. no problem with -std=c++20. Same goes for your std::regex example.

libstdc++ tinfo.cpp refuses to compile when "__cplusplus > 202002L" added in 3633cc54, which is also present in GCC 12. And indeed, the same bug occurs in GCC 12 (w64devkit 1.18.0). It also occurs from the w64devkit bootstrap cross-compiler. I can't find any upstream reports for this bug.

xparq commented 1 year ago

Thanks for the investigation. I wonder why the same static-linking command with c++23 can still work on Debian for the (~same) g++ version (lib32stdc++6 (13.2.0-2)).

(Tried to find something in /usr/share/doc/gcc-13-base/*Debian*, but couldn't.)

Peter0x44 commented 1 year ago

I can't find any upstream reports for this bug.

I believe this has been reported upstream, albeit in a different context I noticed it when I went to open a bug myself https://gcc.gnu.org/PR110572

skeeto commented 1 year ago

Ah, wonderful, thanks @Peter0x44! That looks to be exactly this issue.

skeeto commented 1 year ago

One of the benefits of running your own distribution is that you can easily patch anything to your heart's content, so we can nip this in the bud before the GCC project gets around to fixing it. 731cbdb is a keyhole solution to always enable "new" inline semantics for this operator, not only under C++23. It fixes the problem here as far as I can tell. The cost is breaking C++ ABI compatibility with object files from older w64devkit releases that did not use -std=c++23. C++ ABI breakage is generally true across w64devkit releases spanning major GCC releases, so I don't view that as a big deal.

Before I merge it, more testing would be nice. If there's some important detail I'm missing, definitely let me know. (I am simply not intelligent enough to be confident about the correctness of anything involving C++, so there's always some guesswork.)

xparq commented 1 year ago

I'm not even intelligent enough to build it from source. ;) But if you can link me up with a download, I'd happily start using it.

Peter0x44 commented 1 year ago

I'm not even intelligent enough to build it from source.

If you have docker, check the README. It's not difficult, it does not require "intelligence".

xparq commented 1 year ago

I know it's not difficult; that smiley for "intelligence" was meant to refer to the fact that I don't really have Docker.

xparq commented 8 months ago

Oh, just noticed the (no longer that) new release! <3

Confirming that it has indeed fixed the issue for me, too.

(I don't know about your issue workflow preferences, but the fact that it has been kept open long after even releasing the fix suggests to me that it may be my job to verify it -- and then possibly even closing the thing? (Would be cool if GitHub supported issue workflow policies, at least in the form of just a link to the repo wiki; whatever... I'm just rambling, because I should be working otherwise. :) Thanks for the release!))

skeeto commented 8 months ago

Thanks for the followup, @xparq! I'll close this out.