Where Does the _1 Symbol Come from When Using Llvm's Libc++

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

It is from C++11 inlined namespaces

libc++ has something like

namespace std {
inline namespace __1 {
....

more at What are inline namespaces for?

libc++ - stop std renaming to std::__1?

From the comments:

araqnid:
Your NetBeans invocation doesn't have -std=c++0x, is it not needed? std::map::emplace is a C++11 method.

DigitalMan (OP):
@araqnid That actually did it! Clang complained about that argument being unused - and still does, in fact, even when it's used and required - so I had taken it out of the NetBeans configuration. A faulty warning is better than a complete error, certainly.

How to link libc++ with debug symbols?

Portable workaround.

#include <optional>

// The same as std::optional, but
// throw and exception when ask for empty value.
// Use assert(0) when exceptions disabled.
template<typename T_>
struct Result : std::optional<T_>{
using T = T_;
using parent = std::optional<T_>;
using parent::parent;
using typename parent::value_type;
using parent::operator bool;

constexpr
const value_type&
operator*() const
{
ensure_is_engaged();
return this->value();
}

value_type&
operator*()
{
ensure_is_engaged();
return this->value();
}

private:
void ensure_is_engaged(){
if( bool is_disengaged = not bool(*this) )
#if __EXCEPTIONS
throw std::runtime_error("failed to get disengaged value from std::optional");
#else
assert(0 && "failed to get disengaged value from std::optional");
#endif
}
};

Test

int main()
{
using std::cout, std::cerr, std::endl;
Result<int> normal=1, fail;
cout<<*normal<<*fail;
}

c++ -std=c++17 -fno-exceptions test.cc && ./a.out

1
Assertion failed: (0 && "failed to get disengaged value from std::optional"), function ensure_is_engaged, file ./result.hh, line 38.
fish: './a.out' terminated by signal SIGABRT (Abort)

c++ -std=c++17 test.cc && ./a.out assume default -fexceptions

1
libc++abi.dylib: terminating with uncaught exception of type std::runtime_error: failed to get disengaged value from std::optional
fish: './a.out' terminated by signal SIGABRT (Abort)

Taking pointer to member std::string::size fails to link with libc++ but works with libstdc++

This looks like a libc++ bug by this thread: _LIBCPP_INLINE_VISIBILITY and std::string::length which doing something similar and Howard Hinnant's response is:

I believe this is due to a poor interaction in the compiler between
extern templates and __attribute__ ((__always_inline__)). If
std::string is not declared extern template, then the compiler will
outline a size() member and you won't get this link error.

In my opinion, clang should not assume that extern templates have
definitions for inlined members, especially those marked
always_inline, and the fact that it does is a clang bug resulting in
the link error you see.

The rationale for the use of always_inline in libc++ is to control the
ABI of libc++. In the past I have watched compilers use different
heuristics from release to release on making the inline/outline
decision. This can cause code to be silently added to and removed
from a dylib. With the use of always_inline, I am telling the
compiler to never add that code to the libc++.dylib binary.

Each of the macros defined and used by libc++ can be overridden.

_LIBCPP_INLINE_VISIBILITY controls how an inlined function is attributed and defaults to:

#ifndef _LIBCPP_INLINE_VISIBILITY
#define _LIBCPP_INLINE_VISIBILITY __attribute__ ((__visibility__("hidden"), __always_inline__))
#endif

You can turn this off with:

-D_LIBCPP_INLINE_VISIBILITY=""

And extern templates are done with:

#ifndef _LIBCPP_EXTERN_TEMPLATE
#define _LIBCPP_EXTERN_TEMPLATE(...) extern template __VA_ARGS__;
#endif

This latter one is more difficult to "turn off". The incantation is:

-D'_LIBCPP_EXTERN_TEMPLATE(...)='

Using either (or both) of these workarounds will silence your link
error. But a bug report against clang might be a better long term
solution.

I can not reproduce this on coliru but I can on wandbox and using optimization which uses the -O2 flag makes the problem go away. I was not able to make wandbox accept the -D options suggested above, so not sure if that works.

On my local machine Howard's solution works:

clang++ -D_LIBCPP_INLINE_VISIBILITY="" -D'_LIBCPP_EXTERN_TEMPLATE(...)='

I have not found a bug report, if I don't find one it may make sense to file one.

What is the portable way to forward-declare classes in an inline namespace in libc++?

but to my eyes, libc++ breaks the API defined by the C++ standard:

Actually, it does not. The standard specifies in [contents]:

It is unspecified whether names declared in a specific
namespace are declared directly in that namespace or in an inline namespace inside that namespace.

libc++ is allowed to put mutex in inline namespace __1. Note that there are good reasons for wanting inline namespaces, and typically as the user you don't even care if they exist or not.

To your specific question, you can still forward-declare std::mutex with libc++... you just have to include all the namespaces (see this question for how to detect -std=libc++):

namespace std {
#ifdef _LIBCPP_VERSION
inline namespace __1 {
struct mutex;
}
#else
struct mutex;
#endif
}

However, from [namespace.std]:

The behavior of a C++ program is undefined if it adds declarations or definitions to namespace std or to a
namespace within namespace std unless otherwise specified.

A forward-declaration is still a declaration, so even the above version which accounts for inline namespaces is undefined behavior. So prefer to do it the direct way:

#include <mutex>

Using Crypto++ with clang

This issue was relating to Crypto++ not having been ported over to llvm-clang++. The supported compilers are listed on Platforms; supported compilers for previous releases are listed on Compiling.

My solution was to instead use GCrypt.

Sorry I can't supply anymore details on the cause of the failure.



Related Topics



Leave a reply



Submit