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