[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