1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * vim: sw=2 ts=4 et :
3 */
4 /* This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7
8 #ifndef mozilla_throw_gcc_h
9 #define mozilla_throw_gcc_h
10
11 #include "mozilla/Attributes.h"
12
13 #include <stdio.h> // snprintf
14 #include <string.h> // strerror
15
16 // For gcc, we define these inline to abort so that we're absolutely
17 // certain that (i) no exceptions are thrown from Gecko; (ii) these
18 // errors are always terminal and caught by breakpad.
19
20 #include "mozilla/mozalloc_abort.h"
21
22 // libc++ 4.0.0 and higher use C++11 [[noreturn]] attributes for the functions
23 // below, and since clang does not allow mixing __attribute__((noreturn)) and
24 // [[noreturn]], we have to explicitly use the latter here. See bug 1329520.
25 #if defined(__clang__)
26 # if __has_feature(cxx_attributes) && defined(_LIBCPP_VERSION) && \
27 _LIBCPP_VERSION >= 4000
28 # define MOZ_THROW_NORETURN [[noreturn]]
29 # endif
30 #endif
31 #ifndef MOZ_THROW_NORETURN
32 # define MOZ_THROW_NORETURN MOZ_NORETURN
33 #endif
34
35 // MinGW doesn't appropriately inline these functions in debug builds,
36 // so we need to do some extra coercion for it to do so. Bug 1332747
37 #ifdef __MINGW32__
38 # define MOZ_THROW_INLINE MOZ_ALWAYS_INLINE_EVEN_DEBUG
39 # define MOZ_THROW_EXPORT
40 #else
41 # define MOZ_THROW_INLINE MOZ_ALWAYS_INLINE
42 # define MOZ_THROW_EXPORT MOZ_EXPORT
43 #endif
44
45 namespace std {
46
47 // NB: user code is not supposed to touch the std:: namespace. We're
48 // doing this after careful review because we want to define our own
49 // exception throwing semantics. Don't try this at home!
50
__throw_bad_exception(void)51 MOZ_THROW_NORETURN MOZ_THROW_EXPORT MOZ_THROW_INLINE void __throw_bad_exception(
52 void) {
53 mozalloc_abort("fatal: STL threw bad_exception");
54 }
55
__throw_bad_alloc(void)56 MOZ_THROW_NORETURN MOZ_THROW_EXPORT MOZ_THROW_INLINE void __throw_bad_alloc(
57 void) {
58 mozalloc_abort("fatal: STL threw bad_alloc");
59 }
60
__throw_bad_cast(void)61 MOZ_THROW_NORETURN MOZ_THROW_EXPORT MOZ_THROW_INLINE void __throw_bad_cast(
62 void) {
63 mozalloc_abort("fatal: STL threw bad_cast");
64 }
65
__throw_bad_typeid(void)66 MOZ_THROW_NORETURN MOZ_THROW_EXPORT MOZ_THROW_INLINE void __throw_bad_typeid(
67 void) {
68 mozalloc_abort("fatal: STL threw bad_typeid");
69 }
70
71 // used by <functional>
72 MOZ_THROW_NORETURN MOZ_THROW_EXPORT MOZ_THROW_INLINE void
__throw_bad_function_call(void)73 __throw_bad_function_call(void) {
74 mozalloc_abort("fatal: STL threw bad_function_call");
75 }
76
77 #if !defined(_LIBCPP_VERSION)
__throw_logic_error(const char * msg)78 MOZ_THROW_NORETURN MOZ_THROW_EXPORT MOZ_THROW_INLINE void __throw_logic_error(
79 const char* msg) {
80 mozalloc_abort(msg);
81 }
82 #endif // _LIBCPP_VERSION
83
84 #if !defined(_LIBCPP_VERSION)
__throw_domain_error(const char * msg)85 MOZ_THROW_NORETURN MOZ_THROW_EXPORT MOZ_THROW_INLINE void __throw_domain_error(
86 const char* msg) {
87 mozalloc_abort(msg);
88 }
89 #endif // _LIBCPP_VERSION
90
91 #if !defined(_LIBCPP_VERSION)
92 MOZ_THROW_NORETURN MOZ_THROW_EXPORT MOZ_THROW_INLINE void
__throw_invalid_argument(const char * msg)93 __throw_invalid_argument(const char* msg) {
94 mozalloc_abort(msg);
95 }
96 #endif // _LIBCPP_VERSION
97
98 #if !defined(_LIBCPP_VERSION)
__throw_length_error(const char * msg)99 MOZ_THROW_NORETURN MOZ_THROW_EXPORT MOZ_THROW_INLINE void __throw_length_error(
100 const char* msg) {
101 mozalloc_abort(msg);
102 }
103 #endif // _LIBCPP_VERSION
104
105 #if !defined(_LIBCPP_VERSION)
__throw_out_of_range(const char * msg)106 MOZ_THROW_NORETURN MOZ_THROW_EXPORT MOZ_THROW_INLINE void __throw_out_of_range(
107 const char* msg) {
108 mozalloc_abort(msg);
109 }
110 #endif // _LIBCPP_VERSION
111
__throw_runtime_error(const char * msg)112 MOZ_THROW_NORETURN MOZ_THROW_EXPORT MOZ_THROW_INLINE void __throw_runtime_error(
113 const char* msg) {
114 mozalloc_abort(msg);
115 }
116
117 #if !defined(_LIBCPP_VERSION)
__throw_range_error(const char * msg)118 MOZ_THROW_NORETURN MOZ_THROW_EXPORT MOZ_THROW_INLINE void __throw_range_error(
119 const char* msg) {
120 mozalloc_abort(msg);
121 }
122 #endif // _LIBCPP_VERSION
123
124 #if !defined(_LIBCPP_VERSION)
125 MOZ_THROW_NORETURN MOZ_THROW_EXPORT MOZ_THROW_INLINE void
__throw_overflow_error(const char * msg)126 __throw_overflow_error(const char* msg) {
127 mozalloc_abort(msg);
128 }
129 #endif // _LIBCPP_VERSION
130
131 #if !defined(_LIBCPP_VERSION)
132 MOZ_THROW_NORETURN MOZ_THROW_EXPORT MOZ_THROW_INLINE void
__throw_underflow_error(const char * msg)133 __throw_underflow_error(const char* msg) {
134 mozalloc_abort(msg);
135 }
136 #endif // _LIBCPP_VERSION
137
__throw_ios_failure(const char * msg)138 MOZ_THROW_NORETURN MOZ_THROW_EXPORT MOZ_THROW_INLINE void __throw_ios_failure(
139 const char* msg) {
140 mozalloc_abort(msg);
141 }
142
__throw_system_error(int err)143 MOZ_THROW_NORETURN MOZ_THROW_EXPORT MOZ_THROW_INLINE void __throw_system_error(
144 int err) {
145 char error[128];
146 snprintf(error, sizeof(error) - 1, "fatal: STL threw system_error: %s (%d)",
147 strerror(err), err);
148 mozalloc_abort(error);
149 }
150
__throw_regex_error(int err)151 MOZ_THROW_NORETURN MOZ_EXPORT MOZ_ALWAYS_INLINE void __throw_regex_error(
152 int err) {
153 char error[128];
154 snprintf(error, sizeof(error) - 1, "fatal: STL threw regex_error: %s (%d)",
155 strerror(err), err);
156 mozalloc_abort(error);
157 }
158
159 } // namespace std
160
161 #undef MOZ_THROW_NORETURN
162 #undef MOZ_THROW_INLINE
163
164 #endif // mozilla_throw_gcc_h
165