This is an archive of the discontinued LLVM Phabricator instance.

[libc++] Work around dynamic linking of stringstream::str() on Windows
ClosedPublic

Authored by pfusik on Aug 10 2023, 4:48 AM.

Details

Summary

Also istringstream::str() and ostringstrem::str().

https://github.com/llvm/llvm-project/issues/40363 causes str()
to be dllimport'ed despite _LIBCPP_HIDE_FROM_ABI.
This is a temporary solution until #40363 is fixed.

Diff Detail

Event Timeline

pfusik created this revision.Aug 10 2023, 4:48 AM
Herald added a project: Restricted Project. · View Herald TranscriptAug 10 2023, 4:48 AM
pfusik requested review of this revision.Aug 10 2023, 4:48 AM
Herald added a project: Restricted Project. · View Herald TranscriptAug 10 2023, 4:48 AM
Herald added a reviewer: Restricted Project. · View Herald Transcript
thakis accepted this revision.Aug 10 2023, 6:49 AM

Thanks!

We should merge this (and D155185 if it isn't yet) to the LLVM 17 branch too.

(This needs approval from a libc++ owner as well.)

For libc++ owners: note that this is virtually the same change as 8ecb9591646d4b0326ea7547b99d300336c6c423

(and D155185 if it isn't yet) to the LLVM 17 branch too.

D155185 was merged before branching 17.x.

philnik accepted this revision.Aug 10 2023, 10:18 AM
This revision is now accepted and ready to land.Aug 10 2023, 10:18 AM
This revision was landed with ongoing or failed builds.Aug 10 2023, 11:47 AM
This revision was automatically updated to reflect the committed changes.

What differs in the real world deployments vs what's tested in the libcxx CI; what test config would be needed to catch this in the CI?

What differs in the real world deployments vs what's tested in the libcxx CI; what test config would be needed to catch this in the CI?

I think we'd just have to test older C++ versions on windows. Also note that this is fundamentally a Clang bug that we are working around here.

What differs in the real world deployments vs what's tested in the libcxx CI; what test config would be needed to catch this in the CI?

Good question! I can't reproduce it on my machine with:

clang version 16.0.5
Target: x86_64-w64-windows-gnu
Thread model: posix
InstalledDir: C:/msys64/mingw64/bin

@thakis What exact compiler and linker do you use? Can you post a minimal reproducer?

I think we'd just have to test older C++ versions on windows. Also note that this is fundamentally a Clang bug that we are working around here.

Do you mean pre-C++20 standards?

What differs in the real world deployments vs what's tested in the libcxx CI; what test config would be needed to catch this in the CI?

Good question! I can't reproduce it on my machine with:

clang version 16.0.5
Target: x86_64-w64-windows-gnu
Thread model: posix
InstalledDir: C:/msys64/mingw64/bin

@thakis What exact compiler and linker do you use?

clang-cl and lld as downloaded by https://source.chromium.org/chromium/chromium/src/+/main:tools/clang/scripts/update.py;l=12?q=update.py%20file:clang&ss=chromium (which are regular clang and lld as built at rev llvmorg-18-init-1174-g2532b68f).

Can you post a minimal reproducer?

Can you post the one you tried as starting point? I'll try to tweak it then.

thakis added a subscriber: hans.Aug 11 2023, 7:25 AM

Here's an unreduced compiler invocation: https://bugs.chromium.org/p/chromium/issues/detail?id=1463881#c9

@hans Hmm, I wonder if it's related to /Zc:dllexportInlines- (ref https://blog.llvm.org/2018/11/30-faster-windows-builds-with-clang-cl_14.html). We use that, and we build libc++ with -std=c++20 (since it wants that), and we built the client code that had problems with -std=c++17.

Thanks!

We should merge this (and D155185 if it isn't yet) to the LLVM 17 branch too.

@pfusik can you make a backport request or do you need assistance?

Can you post the one you tried as starting point? I'll try to tweak it then.

C:\0\src\llvm-project>git co 090996~1
HEAD is now at 1e22873ef4b2 [AMDGPU][NFC] Rename two LIT test files

C:\0\src\llvm-project>ninja -C build cxx
ninja: Entering directory `build'
ninja: no work to do.

C:\0\src\llvm-project>cd ..

C:\0\src>cat strwin.cpp
#include <iostream>
#include <sstream>

int main() {
  std::cout << std::stringstream("hi").str();
}

C:\0\src>clang++ -std=c++11 -fuse-ld=ld -o strwin.exe strwin.cpp -nostdinc++ -I llvm-project/build/include/c++/v1 llvm-project/build/lib/libc++.dll.a

C:\0\src>.\strwin.exe
hi

@pfusik can you make a backport request or do you need assistance?

My only concern is that we have no test. What's the schedule for the next 17.0 RC ?

@hans Hmm, I wonder if it's related to /Zc:dllexportInlines- (ref https://blog.llvm.org/2018/11/30-faster-windows-builds-with-clang-cl_14.html). We use that, and we build libc++ with -std=c++20 (since it wants that), and we built the client code that had problems with -std=c++17.

Right, this rings some bells.

I ran into similar issues before - see b048397db8027fedf9380e7cf9213239d558fa29 / https://reviews.llvm.org/D122718, for an issue caused by the fact that in the default config, the library is built with -std=c++20 but the tests are compiled with -std=c++2b. I guess we ideally should test with running the tests for a few c++ versions at least, to check for more instances of this issue.

hans added a comment.Aug 16 2023, 7:21 AM

@hans Hmm, I wonder if it's related to /Zc:dllexportInlines- (ref https://blog.llvm.org/2018/11/30-faster-windows-builds-with-clang-cl_14.html).

I don't think that's a factor here.

I can't reproduce it on my machine with

Is your libcxx configured with -DLIBCXX_ABI_UNSTABLE=ON? The explicit instantiations are gated by _LIBCPP_ABI_ENABLE_ADDITIONAL_IOSTREAM_EXPLICIT_INSTANTIATIONS_1

On my machine, the source code and revision you used reproduces the problem like this:

cmake -GNinja -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_ASSERTIONS=ON -DLLVM_ENABLE_PROJECTS='clang;lld' -DLLVM_ENABLE_RUNTIMES='libcxx' -DLLVM_TARGETS_TO_BUILD=X86 -DLIBCXX_ABI_UNSTABLE=ON ..\llvm
ninja cxx
bin\clang-cl /std:c++17 \src\temp\strwin.cpp -Iinclude\c++\v1 lib\c++.lib
strwin-b8a36d.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: class std::__2::basic_string<char,struct std::__2::char_traits<char>,class std::__2::allocator<char> > __cdecl std::__2::basic_stringstream<char,struct std::__2::char_traits<char>,class std::__2::allocator<char> >::str(void)const " (__imp_?str@?$basic_stringstream@DU?$char_traits@D@__2@std@@V?$allocator@D@23@@__2@std@@QEBA?AV?$basic_string@DU?$char_traits@D@__2@std@@V?$allocator@D@23@@23@XZ) referenced in function main
strwin.exe : fatal error LNK1120: 1 unresolved externals
clang-cl: error: linker command failed with exit code 1120 (use -v to see invocation)

Is your libcxx configured with -DLIBCXX_ABI_UNSTABLE=ON?

Tried this now. This alone does not trigger the problem in my config, but there are several other differences between my and your commands to check.

I will backport my fix later today.