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
#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
_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
#endif
#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20
+# include <cstdlib>
# include <iosfwd>
# include <type_traits>
#endif
unordered_set version
utility compare
utility cstddef
-utility cstdlib
utility initializer_list
utility limits
utility version
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// 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;
+}
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// 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
-
-#include <utility>
-#include <type_traits>
-
-static_assert(std::is_same_v<decltype(std::unreachable()), void>);
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// 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
+
+// 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>);
+
+ return 0;
+}