[libcxx-commits] [libcxx] 678dd9a - [libc++] Improve the implementation of std::unreachable

Louis Dionne via libcxx-commits libcxx-commits at lists.llvm.org
Wed Jan 11 07:15:44 PST 2023


Author: Louis Dionne
Date: 2023-01-11T10:15:25-05:00
New Revision: 678dd9a589d62159c76886d22fa9ccbd1222e1f2

URL: https://github.com/llvm/llvm-project/commit/678dd9a589d62159c76886d22fa9ccbd1222e1f2
DIFF: https://github.com/llvm/llvm-project/commit/678dd9a589d62159c76886d22fa9ccbd1222e1f2.diff

LOG: [libc++] Improve the implementation of std::unreachable

First, use __builtin_unreachable unconditionally. It is implemented by
all the compilers that we support. Clang started supporting it around
Clang 4, and GCC around GCC 4.10.

Also add _LIBCPP_ASSERT so that we will actually get a guaranteed crash
if we reached `std::unreachable()` and assertions have been enabled,
since that's UB that's extremely easy to catch.

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

Added: 
    libcxx/test/std/utilities/utility/utility.unreachable/assert.unreachable.pass.cpp
    libcxx/test/std/utilities/utility/utility.unreachable/unreachable.pass.cpp

Modified: 
    libcxx/include/__utility/unreachable.h
    libcxx/include/utility
    libcxx/test/libcxx/transitive_includes/cxx2b.csv

Removed: 
    libcxx/test/std/utilities/utility/utility.unreachable/unreachable.compile.pass.cpp


################################################################################
diff  --git a/libcxx/include/__utility/unreachable.h b/libcxx/include/__utility/unreachable.h
index 485edb227c92c..d93e60b10b869 100644
--- a/libcxx/include/__utility/unreachable.h
+++ b/libcxx/include/__utility/unreachable.h
@@ -9,8 +9,8 @@
 #ifndef _LIBCPP___UTILITY_UNREACHABLE_H
 #define _LIBCPP___UTILITY_UNREACHABLE_H
 
+#include <__assert>
 #include <__config>
-#include <cstdlib>
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
 #  pragma GCC system_header
@@ -18,21 +18,17 @@
 
 _LIBCPP_BEGIN_NAMESPACE_STD
 
-_LIBCPP_NORETURN _LIBCPP_HIDE_FROM_ABI inline void __libcpp_unreachable()
-{
-#if __has_builtin(__builtin_unreachable)
-  __builtin_unreachable();
-#else
-  std::abort();
-#endif
+_LIBCPP_NORETURN _LIBCPP_HIDE_FROM_ABI inline void __libcpp_unreachable() {
+    _LIBCPP_ASSERT(false, "std::unreachable() was reached");
+    __builtin_unreachable();
 }
 
 #if _LIBCPP_STD_VER > 20
 
 [[noreturn]] _LIBCPP_HIDE_FROM_ABI inline void unreachable() { __libcpp_unreachable(); }
 
-#endif // _LIBCPP_STD_VER > 20
+#endif
 
 _LIBCPP_END_NAMESPACE_STD
 
-#endif
+#endif // _LIBCPP___UTILITY_UNREACHABLE_H

diff  --git a/libcxx/include/utility b/libcxx/include/utility
index 4de69f7bdea85..1d56759310f92 100644
--- a/libcxx/include/utility
+++ b/libcxx/include/utility
@@ -274,6 +274,7 @@ template <class T>
 #endif
 
 #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20
+#  include <cstdlib>
 #  include <iosfwd>
 #  include <type_traits>
 #endif

diff  --git a/libcxx/test/libcxx/transitive_includes/cxx2b.csv b/libcxx/test/libcxx/transitive_includes/cxx2b.csv
index 3f98abd77120c..0e6f3780b8675 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx2b.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx2b.csv
@@ -693,7 +693,6 @@ unordered_set type_traits
 unordered_set version
 utility compare
 utility cstddef
-utility cstdlib
 utility initializer_list
 utility limits
 utility version

diff  --git a/libcxx/test/std/utilities/utility/utility.unreachable/assert.unreachable.pass.cpp b/libcxx/test/std/utilities/utility/utility.unreachable/assert.unreachable.pass.cpp
new file mode 100644
index 0000000000000..cfb3606805e2b
--- /dev/null
+++ b/libcxx/test/std/utilities/utility/utility.unreachable/assert.unreachable.pass.cpp
@@ -0,0 +1,25 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
+
+// REQUIRES: has-unix-headers
+// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11.0|12.0}}
+// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1
+
+// Make sure that reaching std::unreachable() with assertions enabled triggers an assertion.
+
+#include <utility>
+
+#include "check_assertion.h"
+
+int main(int, char**) {
+    TEST_LIBCPP_ASSERT_FAILURE(std::unreachable(), "std::unreachable() was reached");
+
+    return 0;
+}

diff  --git a/libcxx/test/std/utilities/utility/utility.unreachable/unreachable.compile.pass.cpp b/libcxx/test/std/utilities/utility/utility.unreachable/unreachable.pass.cpp
similarity index 53%
rename from libcxx/test/std/utilities/utility/utility.unreachable/unreachable.compile.pass.cpp
rename to libcxx/test/std/utilities/utility/utility.unreachable/unreachable.pass.cpp
index 017fa305d9c82..290c61f41c520 100644
--- a/libcxx/test/std/utilities/utility/utility.unreachable/unreachable.compile.pass.cpp
+++ b/libcxx/test/std/utilities/utility/utility.unreachable/unreachable.pass.cpp
@@ -8,7 +8,20 @@
 
 // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
 
-#include <utility>
+// Make sure we can use `std::unreachable()`. We can't actually execute it cause that would be
+// UB, but we can make sure that it doesn't cause a linker error or something like that.
+
+#include <cassert>
 #include <type_traits>
+#include <utility>
+
+int main(int argc, char**) {
+    assert(argc == 1);
+    if (argc != 1) {
+        std::unreachable();
+    }
+
+    static_assert(std::is_same_v<decltype(std::unreachable()), void>);
 
-static_assert(std::is_same_v<decltype(std::unreachable()), void>);
+    return 0;
+}


        


More information about the libcxx-commits mailing list