Issue 135910
Summary clang++ incompatibility with libstdc++ gcc4-compatible ABI on Windows
Labels clang
Assignees
Reporter 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:
```c++
#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](https://github.com/user-attachments/files/19770539/test.clang.s.txt)

output of `g++ -O2 -S -o test.gcc.s test.cpp`
[test.gcc.s.txt](https://github.com/user-attachments/files/19770543/test.gcc.s.txt)

relevant difference:
```asm
	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
	.p2align	4, 0x0
_ZNSs4_Rep20_S_empty_rep_storageE:
	.zero	32
```
vs
```asm
	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:
```c++
  // 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 
_______________________________________________
llvm-bugs mailing list
llvm-bugs@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to