1 // Copyright 2021 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef LIB_STDCOMPAT_INTERNAL_EXCEPTION_H_
6 #define LIB_STDCOMPAT_INTERNAL_EXCEPTION_H_
7
8 #include <exception>
9
10 #include "../type_traits.h"
11
12 namespace cpp17 {
13 namespace internal {
14
15 // When exceptions are enabled, will generate an exception of the right type, when disabled will
16 // simply abort execution.
17 //
18 // Note: both clang and gcc support gnu::unused, which makes it a portable alternative for
19 // [[maybe_unused]].
20 template <typename T,
21 typename std::enable_if<std::is_base_of<std::exception, T>::value, bool>::type = true>
throw_or_abort(const char * reason)22 [[noreturn]] inline constexpr void throw_or_abort([[gnu::unused]] const char* reason) {
23 #if defined(__cpp_exceptions) && __cpp_exceptions >= 199711L
24 throw T(reason);
25 #else
26 __builtin_abort();
27 #endif
28 }
29
30 template <typename T>
throw_or_abort_if_any_impl(const char * reason,bool should_abort)31 inline constexpr void throw_or_abort_if_any_impl(const char* reason, bool should_abort) {
32 if (should_abort) {
33 throw_or_abort<T>(reason);
34 }
35 }
36
37 template <typename T, typename... AbortIf>
throw_or_abort_if_any_impl(const char * reason,bool head,AbortIf...tail)38 inline constexpr void throw_or_abort_if_any_impl(const char* reason, bool head, AbortIf... tail) {
39 if (head) {
40 throw_or_abort<T>(reason);
41 }
42 throw_or_abort_if_any_impl<T>(reason, tail...);
43 }
44
45 template <typename T, typename... AbortIf>
throw_or_abort_if_any(const char * reason,AbortIf...abort_if)46 inline constexpr void throw_or_abort_if_any(const char* reason, AbortIf... abort_if) {
47 static_assert(sizeof...(AbortIf) > 0, "Must provide an |abort_if| clause.");
48 static_assert(cpp17::conjunction_v<std::is_same<bool, AbortIf>...>,
49 "|abort_if| arguments must be boolean.");
50 throw_or_abort_if_any_impl<T>(reason, abort_if...);
51 }
52
53 } // namespace internal
54 } // namespace cpp17
55
56 #endif // LIB_STDCOMPAT_INTERNAL_EXCEPTION_H_
57