[libc++] Disentangle std::pointer_safety
authorLouis Dionne <ldionne.2@gmail.com>
Tue, 13 Apr 2021 20:43:42 +0000 (16:43 -0400)
committerLouis Dionne <ldionne.2@gmail.com>
Mon, 3 May 2021 18:33:49 +0000 (14:33 -0400)
This patch gets rid of technical debt around std::pointer_safety which,
I claim, is entirely unnecessary. I don't think anybody has used
std::pointer_safety in actual code because we do not implement the
underlying garbage collection support. In fact, P2186 even proposes
removing these facilities entirely from a future C++ version. As such,
I think it's entirely fine to get rid of complex workarounds whose goals
were to avoid breaking the ABI back in 2017.

I'm putting this up both to get reviews and to discuss this proposal for
a breaking change. I think we should be comfortable with making these
tiny breaks if we are confident they won't hurt anyone, which I'm fairly
confident is the case here.

Differential Revision: https://reviews.llvm.org/D100410

12 files changed:
libcxx/docs/ReleaseNotes.rst
libcxx/include/__config
libcxx/include/__memory/pointer_safety.h
libcxx/include/memory
libcxx/lib/abi/x86_64-apple-darwin.libcxxabi.v1.stable.exceptions.no_new_in_libcxx.abilist
libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.no_new_in_libcxx.abilist
libcxx/src/memory.cpp
libcxx/test/libcxx/utilities/memory/util.dynamic.safety/get_pointer_safety_cxx03.pass.cpp [deleted file]
libcxx/test/libcxx/utilities/memory/util.dynamic.safety/get_pointer_safety_new_abi.pass.cpp [deleted file]
libcxx/test/std/utilities/memory/util.dynamic.safety/declare_no_pointers.pass.cpp
libcxx/test/std/utilities/memory/util.dynamic.safety/declare_reachable.pass.cpp
libcxx/test/std/utilities/memory/util.dynamic.safety/get_pointer_safety.pass.cpp

index 1bcb26d..0cc8c00 100644 (file)
@@ -55,3 +55,13 @@ API Changes
 
   Also, the extension allowing a tuple to be constructed from an array has been
   removed. See https://godbolt.org/z/5esqbW.
+
+- The ``std::pointer_safety`` utility and related functions are not available
+  in C++03 anymore. Furthermore, in other standard modes, it has changed from
+  a struct to a scoped enumeration, which is an ABI break. Finally, the
+  ``std::get_pointer_safety`` function was previously in the dylib, but it
+  is now defined as inline in the headers.
+
+  While this is technically both an API and an ABI break, we do not expect
+  ``std::pointer_safety`` to have been used at all in real code, since we
+  never implemented the underlying support for garbage collection.
index 431893f..49255a8 100644 (file)
 // provided under the alternate keyword __nullptr, which changes the mangling
 // of nullptr_t. This option is ABI incompatible with GCC in C++03 mode.
 #  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
 // Define a key function for `bad_function_call` in the library, to centralize
 // its vtable and typeinfo to libc++ rather than having all other libraries
 // using that class define their own copies.
index a32ffc4..bdfed3f 100644 (file)
@@ -21,50 +21,18 @@ _LIBCPP_PUSH_MACROS
 
 _LIBCPP_BEGIN_NAMESPACE_STD
 
-//enum class
-#if defined(_LIBCPP_ABI_POINTER_SAFETY_ENUM_TYPE)
-# ifndef _LIBCPP_CXX03_LANG
+#if !defined(_LIBCPP_CXX03_LANG)
+
 enum class pointer_safety : unsigned char {
   relaxed,
   preferred,
   strict
 };
-# endif
-#else
-struct _LIBCPP_TYPE_VIS pointer_safety
-{
-    enum __lx
-    {
-        relaxed,
-        preferred,
-        strict
-    };
-
-    __lx __v_;
-
-    _LIBCPP_INLINE_VISIBILITY
-    pointer_safety() : __v_() {}
-
-    _LIBCPP_INLINE_VISIBILITY
-    pointer_safety(__lx __v) : __v_(__v) {}
-    _LIBCPP_INLINE_VISIBILITY
-    operator int() const {return __v_;}
-};
-#endif
 
-#if !defined(_LIBCPP_ABI_POINTER_SAFETY_ENUM_TYPE) && \
-    defined(_LIBCPP_BUILDING_LIBRARY)
-_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_no_pointers(char* __p, size_t __n);
@@ -79,6 +47,8 @@ undeclare_reachable(_Tp* __p)
     return static_cast<_Tp*>(__undeclare_reachable(__p));
 }
 
+#endif // !C++03
+
 _LIBCPP_END_NAMESPACE_STD
 
 _LIBCPP_POP_MACROS
index 74a430d..586bd14 100644 (file)
@@ -651,12 +651,12 @@ template <class T, class Alloc>
   inline constexpr bool uses_allocator_v = uses_allocator<T, Alloc>::value;
 
 // Pointer safety
-enum class pointer_safety { relaxed, preferred, strict };
-void declare_reachable(void *p);
-template <class T> T *undeclare_reachable(T *p);
-void declare_no_pointers(char *p, size_t n);
-void undeclare_no_pointers(char *p, size_t n);
-pointer_safety get_pointer_safety() noexcept;
+enum class pointer_safety { relaxed, preferred, strict }; // since C++11
+void declare_reachable(void *p);                          // since C++11
+template <class T> T *undeclare_reachable(T *p);          // since C++11
+void declare_no_pointers(char *p, size_t n);              // since C++11
+void undeclare_no_pointers(char *p, size_t n);            // since C++11
+pointer_safety get_pointer_safety() noexcept;             // since C++11
 
 void* align(size_t alignment, size_t size, void*& ptr, size_t& space);
 
index c472a3a..17739ea 100644 (file)
 {'is_defined': True, 'name': '__ZNSt3__118condition_variable4waitERNS_11unique_lockINS_5mutexEEE', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__118condition_variableD1Ev', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__118condition_variableD2Ev', 'type': 'FUNC'}
-{'is_defined': True, 'name': '__ZNSt3__118get_pointer_safetyEv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__118shared_timed_mutex11lock_sharedEv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__118shared_timed_mutex13unlock_sharedEv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__118shared_timed_mutex15try_lock_sharedEv', 'type': 'FUNC'}
index 46e3ef7..927b36f 100644 (file)
 {'is_defined': True, 'name': '_ZNSt3__118condition_variable4waitERNS_11unique_lockINS_5mutexEEE', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__118condition_variableD1Ev', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__118condition_variableD2Ev', 'type': 'FUNC'}
-{'is_defined': True, 'name': '_ZNSt3__118get_pointer_safetyEv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__118shared_timed_mutex11lock_sharedEv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__118shared_timed_mutex13unlock_sharedEv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__118shared_timed_mutex15try_lock_sharedEv', 'type': 'FUNC'}
index cb10b69..9bd27df 100644 (file)
@@ -198,13 +198,6 @@ undeclare_no_pointers(char*, size_t)
 {
 }
 
-#if !defined(_LIBCPP_ABI_POINTER_SAFETY_ENUM_TYPE)
-pointer_safety get_pointer_safety() noexcept
-{
-    return pointer_safety::relaxed;
-}
-#endif
-
 void*
 __undeclare_reachable(void* p)
 {
diff --git a/libcxx/test/libcxx/utilities/memory/util.dynamic.safety/get_pointer_safety_cxx03.pass.cpp b/libcxx/test/libcxx/utilities/memory/util.dynamic.safety/get_pointer_safety_cxx03.pass.cpp
deleted file mode 100644 (file)
index deab436..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-// <memory>
-
-// pointer_safety get_pointer_safety();
-
-#include <memory>
-#include <cassert>
-
-#include "test_macros.h"
-
-// libc++ doesn't offer std::pointer_safety in C++03 under the new ABI
-#if TEST_STD_VER < 11 && defined(_LIBCPP_ABI_POINTER_SAFETY_ENUM_TYPE)
-#define TEST_IS_UNSUPPORTED
-#endif
-
-#ifndef TEST_IS_UNSUPPORTED
-void test_pr26961() {
-  std::pointer_safety d;
-  d = std::get_pointer_safety();
-  assert(d == std::get_pointer_safety());
-}
-#endif
-
-int main(int, char**)
-{
-#ifndef TEST_IS_UNSUPPORTED
-  {
-    // Test that std::pointer_safety is still offered in C++03 under the old ABI.
-    std::pointer_safety r = std::get_pointer_safety();
-    assert(r == std::pointer_safety::relaxed ||
-           r == std::pointer_safety::preferred ||
-           r == std::pointer_safety::strict);
-  }
-  {
-    test_pr26961();
-  }
-#endif
-
-  return 0;
-}
diff --git a/libcxx/test/libcxx/utilities/memory/util.dynamic.safety/get_pointer_safety_new_abi.pass.cpp b/libcxx/test/libcxx/utilities/memory/util.dynamic.safety/get_pointer_safety_new_abi.pass.cpp
deleted file mode 100644 (file)
index 44d336f..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-// <memory>
-
-// pointer_safety get_pointer_safety();
-
-// The pointer_safety interface is no longer provided in C++03 in the new ABI.
-// XFAIL: c++03
-
-// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ABI_POINTER_SAFETY_ENUM_TYPE
-
-#include <memory>
-#include <cassert>
-
-#include "test_macros.h"
-
-int main(int, char**)
-{
-  {
-    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);
-  }
-
-  return 0;
-}
index 892479f..562f005 100644 (file)
@@ -6,6 +6,8 @@
 //
 //===----------------------------------------------------------------------===//
 
+// UNSUPPORTED: c++03
+
 // <memory>
 
 // void declare_no_pointers(char* p, size_t n);
index 2d880ef..08d06d5 100644 (file)
@@ -6,6 +6,8 @@
 //
 //===----------------------------------------------------------------------===//
 
+// UNSUPPORTED: c++03
+
 // <memory>
 
 // void declare_reachable(void* p);
index b12ff90..e612572 100644 (file)
 
 #include "test_macros.h"
 
-
-void test_pr26961() {
-  std::pointer_safety d;
-  d = std::get_pointer_safety();
-  assert(d == std::get_pointer_safety());
-}
-
 int main(int, char**)
 {
   {
+    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);
   }
+  // Regression test for https://llvm.org/PR26961
   {
-    test_pr26961();
+    std::pointer_safety d;
+    d = std::get_pointer_safety();
+    assert(d == std::get_pointer_safety());
   }
 
   return 0;