Where does the __1 symbol come from when using LLVM's libc++?
Asked Answered
C

1

21

I see a fair amount of questions like Apple Mach-O Linker (Id) Error and Undefined symbols in cryptopp at IOS 64-bit project. The problem is usually described as:

Undefined symbols for architecture i386:
  "std::__1::basic_ostream<char, std::__1::char_traits<char> >::flush()", referenced from:
      cv::gpu::error(char const*, char const*, int, char const*) in opencv2(gpumat.o)

The problem often reduces to mixing/matching -stdlib=libc++ (LLVM C++ runtime) and -stdlib=libstdc++ (GNU C++ runtime). The LLVM C++ runtime (libc++) has an __1 decoration symbol, but the GNU C++ runtime libstdc++ lacks the __1 symbol in its name. It causes linker problems for symbols that appears to have the same name (like std::string).

Where does the __1 symbol come from when using LLVM's libc++?

Why was the problem not solved with a gnu namespace and an llvm namespace?


Here's a related question: libc++ - stop std renaming to std::__1?. But it kind of misses the point in that a rename does not occur.

Crouch answered 27/3, 2015 at 4:37 Comment(1)
It's an inline namespace that libc++ uses for versioning.Nullification
I
16

It is from C++11 inlined namespaces

libc++ has something like

namespace std {
    inline namespace __1 {
        ....

more at What are inline namespaces for?

Identical answered 27/3, 2015 at 4:45 Comment(5)
Thanks @Severin. That's an interesting link. So if I used a C++11 compiler, the the problems with std::string and std::__1::string would go away becuase the compiler would understand the inline namespace? Or the problem would go away if I used -std=c++03 because inline namespaces would not be used? (Up until now, I've been telling people to compile everything with either the LLVM runtime or the GNU runtime).Crouch
@Crouch I believe both compilers (GCC and clang) understand inlined namspaces. Problem is with declaration vs definition. If you're using libc++ headers, you'll get declarations picked with std::__1:: prefix, something like std::__1::string etc. If you're using GNU libstdc++ header, you'll get declaration std::string etc. But then you have to pick up definitions from either libstdc++.a/.so or from libc++.a/.so. Due to the fact, that each library is compiled with it's own headers, definitions also carry the same prefix. To be continued...Identical
Thus, if you pick declarations from libc++ headers (with std::__1:: prefix) but try to use definitions from libstdc++ (with std:: prefix), you're getting linker error - definitions don't much. Good thing, I think, debugging might be a nightmare. So I would say if you're using GNU toolchain, link against libstdc++, if clang - link against libc++Identical
Just to be clear - those prefixes are in mangled names in compiled code in .o/.a/.so. In source code you see/use std::string.Identical
It would be nice to have a solution to the resulting compilation problem, though.Reiko

© 2022 - 2024 — McMap. All rights reserved.