Fix std::pointer_safety type in ABI v2
In the C++ standard `std::pointer_safety` is defined as a C++11 strongly typed enum. However libc++ currently defines it as a class type which simulates a C++11 enumeration. This can be detected in valid C++ code. This patch introduces an the _LIBCPP_ABI_POINTER_SAFETY_ENUM_TYPE ABI option. When defined `std::pointer_safety` is implemented as an enum type. Unfortunatly this also means it can no longer be provided as an extension in C++03. Additionally this patch moves the definition for `get_pointer_safety()` out of the dylib, and into the headers. New usages of `get_pointer_safety()` will now use the inline version instead of the dylib version. However in order to keep the dylib ABI compatible the old definition is explicitly compiled into it. git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@291046 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -52,6 +52,11 @@
|
|||||||
// provided under the alternate keyword __nullptr, which changes the mangling
|
// provided under the alternate keyword __nullptr, which changes the mangling
|
||||||
// of nullptr_t. This option is ABI incompatible with GCC in C++03 mode.
|
// of nullptr_t. This option is ABI incompatible with GCC in C++03 mode.
|
||||||
#define _LIBCPP_ABI_ALWAYS_USE_CXX11_NULLPTR
|
#define _LIBCPP_ABI_ALWAYS_USE_CXX11_NULLPTR
|
||||||
|
// Define the `pointer_safety` enum as a C++11 strongly typed enumeration
|
||||||
|
// instead of as a class simulating an enum. If this option is enabled
|
||||||
|
// `pointer_safety` and `get_pointer_safety()` will no longer be available
|
||||||
|
// in C++03.
|
||||||
|
#define _LIBCPP_ABI_POINTER_SAFETY_ENUM_TYPE
|
||||||
#elif _LIBCPP_ABI_VERSION == 1
|
#elif _LIBCPP_ABI_VERSION == 1
|
||||||
#if !defined(_WIN32)
|
#if !defined(_WIN32)
|
||||||
// Enable compiling a definition of error_category() into the libc++ dylib.
|
// Enable compiling a definition of error_category() into the libc++ dylib.
|
||||||
|
|||||||
@@ -5616,6 +5616,15 @@ atomic_compare_exchange_weak_explicit(shared_ptr<_Tp>* __p, shared_ptr<_Tp>* __v
|
|||||||
#endif // !defined(_LIBCPP_HAS_NO_ATOMIC_HEADER)
|
#endif // !defined(_LIBCPP_HAS_NO_ATOMIC_HEADER)
|
||||||
|
|
||||||
//enum class
|
//enum class
|
||||||
|
#if defined(_LIBCPP_ABI_POINTER_SAFETY_ENUM_TYPE)
|
||||||
|
# ifndef _LIBCPP_CXX03_LANG
|
||||||
|
enum class pointer_safety : unsigned char {
|
||||||
|
relaxed,
|
||||||
|
preferred,
|
||||||
|
strict
|
||||||
|
};
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
struct _LIBCPP_TYPE_VIS pointer_safety
|
struct _LIBCPP_TYPE_VIS pointer_safety
|
||||||
{
|
{
|
||||||
enum __lx
|
enum __lx
|
||||||
@@ -5632,11 +5641,25 @@ struct _LIBCPP_TYPE_VIS pointer_safety
|
|||||||
_LIBCPP_INLINE_VISIBILITY
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
operator int() const {return __v_;}
|
operator int() const {return __v_;}
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(_LIBCPP_ABI_POINTER_SAFETY_ENUM_TYPE) && \
|
||||||
|
defined(_LIBCPP_BUILDING_MEMORY)
|
||||||
|
_LIBCPP_FUNC_VIS pointer_safety get_pointer_safety() _NOEXCEPT;
|
||||||
|
#else
|
||||||
|
// This function is only offered in C++03 under ABI v1.
|
||||||
|
# if !defined(_LIBCPP_ABI_POINTER_SAFETY_ENUM_TYPE) || !defined(_LIBCPP_CXX03_LANG)
|
||||||
|
inline _LIBCPP_INLINE_VISIBILITY
|
||||||
|
pointer_safety get_pointer_safety() _NOEXCEPT {
|
||||||
|
return pointer_safety::relaxed;
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
_LIBCPP_FUNC_VIS void declare_reachable(void* __p);
|
_LIBCPP_FUNC_VIS void declare_reachable(void* __p);
|
||||||
_LIBCPP_FUNC_VIS void declare_no_pointers(char* __p, size_t __n);
|
_LIBCPP_FUNC_VIS void declare_no_pointers(char* __p, size_t __n);
|
||||||
_LIBCPP_FUNC_VIS void undeclare_no_pointers(char* __p, size_t __n);
|
_LIBCPP_FUNC_VIS void undeclare_no_pointers(char* __p, size_t __n);
|
||||||
_LIBCPP_FUNC_VIS pointer_safety get_pointer_safety() _NOEXCEPT;
|
|
||||||
_LIBCPP_FUNC_VIS void* __undeclare_reachable(void* __p);
|
_LIBCPP_FUNC_VIS void* __undeclare_reachable(void* __p);
|
||||||
|
|
||||||
template <class _Tp>
|
template <class _Tp>
|
||||||
|
|||||||
@@ -220,11 +220,12 @@ undeclare_no_pointers(char*, size_t)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
pointer_safety
|
#if !defined(_LIBCPP_ABI_POINTER_SAFETY_ENUM_TYPE)
|
||||||
get_pointer_safety() _NOEXCEPT
|
pointer_safety get_pointer_safety() _NOEXCEPT
|
||||||
{
|
{
|
||||||
return pointer_safety::relaxed;
|
return pointer_safety::relaxed;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void*
|
void*
|
||||||
__undeclare_reachable(void* p)
|
__undeclare_reachable(void* p)
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||||
|
// Source Licenses. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// <memory>
|
||||||
|
|
||||||
|
// pointer_safety get_pointer_safety();
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
// Test that std::pointer_safety is still offered in C++03 under the old ABI.
|
||||||
|
#ifndef _LIBCPP_ABI_POINTER_SAFETY_ENUM_TYPE
|
||||||
|
std::pointer_safety r = std::get_pointer_safety();
|
||||||
|
assert(r == std::pointer_safety::relaxed ||
|
||||||
|
r == std::pointer_safety::preferred ||
|
||||||
|
r == std::pointer_safety::strict);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||||
|
// Source Licenses. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// <memory>
|
||||||
|
|
||||||
|
// pointer_safety get_pointer_safety();
|
||||||
|
|
||||||
|
// The pointer_safety interface is no longer provided in C++03 in the new ABI.
|
||||||
|
// XFAIL: c++98, c++03
|
||||||
|
|
||||||
|
// MODULES_DEFINES: _LIBCPP_ABI_POINTER_SAFETY_ENUM_TYPE
|
||||||
|
#define _LIBCPP_ABI_POINTER_SAFETY_ENUM_TYPE
|
||||||
|
#include <memory>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
{
|
||||||
|
static_assert(std::is_enum<std::pointer_safety>::value, "");
|
||||||
|
static_assert(!std::is_convertible<std::pointer_safety, int>::value, "");
|
||||||
|
static_assert(std::is_same<
|
||||||
|
std::underlying_type<std::pointer_safety>::type,
|
||||||
|
unsigned char
|
||||||
|
>::value, "");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
std::pointer_safety r = std::get_pointer_safety();
|
||||||
|
assert(r == std::pointer_safety::relaxed ||
|
||||||
|
r == std::pointer_safety::preferred ||
|
||||||
|
r == std::pointer_safety::strict);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,6 +11,8 @@
|
|||||||
|
|
||||||
// pointer_safety get_pointer_safety();
|
// pointer_safety get_pointer_safety();
|
||||||
|
|
||||||
|
// UNSUPPORTED: c++98, c++03
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user