xref: /aosp_15_r20/external/pigweed/third_party/fuchsia/repo/sdk/lib/stdcompat/include/lib/stdcompat/internal/exception.h (revision 61c4878ac05f98d0ceed94b57d316916de578985)
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