[libc++] link errors on Windows

I’ve built libc++ on Windows as shown in the documentation, but I’m having trouble linking a simple program.

#include <string>
int main() {
  std::string s = “Hello world”;
  const char *data = s.data();
}

LLD fails to link with the following error: undefined symbol: __imp_?data@?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@QEAAPEADXZ.
MSVC link.exe errors in the same way.

Interestingly it works fine if s.data() is changed to s.c_str().

Am I doing something wrong or is this a bug?
It looks like the string header marks basic_string::data as having inline visibility, so I’m not sure why this doesn’t work.

Even though basic_string::data is marked __forceinline, clang (and I believe
it emulates cl's behavior here) won't inline dllimport functions which call
non-dllimport functions [1]. Over here, the call to _VSTD::__to_raw_pointer
will prevent inlining. (This is a pretty unnecessary pessimization in this
case, since __to_raw_pointer is a trivial inline function, and we can try to
make it better, but that's a different topic.)

The function you're getting a link error against demangles to the *non-const*
data overload, which is only enabled when _LIBCPP_STD_VER > 14. I believe
what's happening is that you compiled libc++ with _LIBCPP_STD_VER <= 14, so
the non-const overload won't be present in the library, but then you're using
the headers with _LIBCPP_STD_VER > 14, so the compiler will attempt to use the
non-const overload, which won't be inlined as discussed above, and also won't
be present in the library, hence the link error. There's no non-const overload
of c_str, and c_str will call the const overload of data, which is why it
fixes the issue you're seeing.

You should ensure your C++ standard version is consistent across the build of
libc++ and its uses. I'm adding Marshall and Eric in case they have thoughts
on libc++ headers being used with a different C++ standard version than the
library was compiled with, since the problem over here is a Windows-specific
issue.

[1] https://reviews.llvm.org/diffusion/L/browse/cfe/trunk/lib/CodeGen/CodeGenModule.cpp;311991$1871

That was exactly it, thanks!

What’s the supported way of compiling libc++ with a higher std version number?
I couldn’t find anything in the documentation about needing to compile with std version in mind.

I got it working by adding -D_LIBCPP_STD_VER=17 to CMAKE_CXX_FLAGS, but I’m not sure if that’s the correct way. E.g. I got a bunch of warnings in <variant> about static_assert without messages being a C++17 extension, so it looks like the build configuration wasn't adjusted accordingly.

If you're running a recent clang, adding /std:c++17 to the compiler flags
should work. If you're on an older clang, adding `-Xclang -std=c++1y` should
do the trick.

    That was exactly it, thanks!
    
    What’s the supported way of compiling libc++ with a higher std version number?
    I couldn’t find anything in the documentation about needing to compile with std version in mind.
    
    I got it working by adding -D_LIBCPP_STD_VER=17 to CMAKE_CXX_FLAGS, but I’m not sure if that’s the correct way. E.g. I got a bunch of warnings in <variant> about static_assert without messages being a C++17 extension, so it looks like the build configuration wasn't adjusted accordingly.