Skip to content

clang++ incompatibility with libstdc++ gcc4-compatible ABI on Windows #135910

@jeremyd2019

Description

@jeremyd2019

This was first seen on Cygwin (x86_64-pc-windows-cygnus), where GCC is built with --with-default-libstdcxx-abi=gcc4-compatible, but I reproduced it on x86_64-pc-windows-gnu as well, so I decided to report here.

Start with a mingw-w64 gcc built without --enable-fully-dynamic-string configure argument, and possibly with --with-default-libstdcxx-abi=gcc4-compatible. It should be possible to switch to the gcc4-compatible ABI with -D_GLIBCXX_USE_CXX11_ABI=0 if not built with that option.

The following test program aborts when built with -O2, unless built with -std=c++20 or newer:

#include <stdio.h> #include <string> class foo { public: foo() { m_str.assign("hello"); } std::string m_str; } bar; int main() { printf("%ld - %s\n", __cplusplus, bar.m_str.c_str()); return 0; }

Output of clang++ -O2 -S -o test.clang.s test.cpp
test.clang.s.txt

output of g++ -O2 -S -o test.gcc.s test.cpp
test.gcc.s.txt

relevant difference:

leaq	_ZNSs4_Rep20_S_empty_rep_storageE(%rip), %rdx cmpq	%rdx, %rcx ... .section.bss$_ZNSs4_Rep20_S_empty_rep_storageE,"bw",discard,_ZNSs4_Rep20_S_empty_rep_storageE .globl	_ZNSs4_Rep20_S_empty_rep_storageE # @_ZNSs4_Rep20_S_empty_rep_storageE .p2align4, 0x0 _ZNSs4_Rep20_S_empty_rep_storageE: .zero32

vs

cmpq	.refptr._ZNSs4_Rep20_S_empty_rep_storageE(%rip), %rcx ... .section.rdata$.refptr._ZNSs4_Rep20_S_empty_rep_storageE, "dr" .globl	.refptr._ZNSs4_Rep20_S_empty_rep_storageE .linkonce	discard .refptr._ZNSs4_Rep20_S_empty_rep_storageE: .quad	_ZNSs4_Rep20_S_empty_rep_storageE

relevant bit of libstdc++ header:

 // Inhibit implicit instantiations for required instantiations, // which are defined via explicit instantiations elsewhere. #if _GLIBCXX_EXTERN_TEMPLATE // The explicit instantiation definitions in src/c++11/string-inst.cc and // src/c++17/string-inst.cc only instantiate the members required for C++17 // and earlier standards (so not C++20's starts_with and ends_with). // Suppress the explicit instantiation declarations for C++20, so C++20 // code will implicitly instantiate std::string and std::wstring as needed. # if __cplusplus <= 201703L && _GLIBCXX_EXTERN_TEMPLATE > 0 extern template class basic_string<char>; # elif ! _GLIBCXX_USE_CXX11_ABI // Still need to prevent implicit instantiation of the COW empty rep, // to ensure the definition in libstdc++.so is unique (PR 86138). extern template basic_string<char>::size_type basic_string<char>::_Rep::_S_empty_rep_storage[]; # elif _GLIBCXX_EXTERN_TEMPLATE > 0 // Export _M_replace_cold even for C++20. extern template void basic_string<char>::_M_replace_cold(char *, size_type, const char*, const size_type, const size_type); # endif

_GLIBCXX_EXTERN_TEMPLATE is 1, and the issue manifests when _GLIBCXX_USE_CXX11_ABI is 0 and __cplusplus is <= 201703.

see msys2/MSYS2-packages#5329 for history of the investigation.

/cc @mstorsjo

Metadata

Metadata

Assignees

No one assigned

    Labels

    ABIApplication Binary InterfaceclangClang issues not falling into any other categoryplatform:windows

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions