Split rank_one_type_parm_complex from rank_one_type
[deliverable/binutils-gdb.git] / gdb / common / common-exceptions.c
1 /* Exception (throw catch) mechanism, for GDB, the GNU debugger.
2
3 Copyright (C) 1986-2019 Free Software Foundation, Inc.
4
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19
20 #include "common-defs.h"
21 #include "common-exceptions.h"
22
23 const struct gdb_exception exception_none = { (enum return_reason) 0, GDB_NO_ERROR, NULL };
24
25 /* Possible catcher states. */
26 enum catcher_state {
27 /* Initial state, a new catcher has just been created. */
28 CATCHER_CREATED,
29 /* The catch code is running. */
30 CATCHER_RUNNING,
31 CATCHER_RUNNING_1,
32 /* The catch code threw an exception. */
33 CATCHER_ABORTING
34 };
35
36 /* Possible catcher actions. */
37 enum catcher_action {
38 CATCH_ITER,
39 CATCH_ITER_1,
40 CATCH_THROWING
41 };
42
43 struct catcher
44 {
45 enum catcher_state state;
46 /* Jump buffer pointing back at the exception handler. */
47 jmp_buf buf;
48 /* Status buffer belonging to the exception handler. */
49 struct gdb_exception exception;
50 /* Back link. */
51 struct catcher *prev;
52 };
53
54 /* Where to go for throw_exception(). */
55 static struct catcher *current_catcher;
56
57 #if GDB_XCPT == GDB_XCPT_SJMP
58
59 /* Return length of current_catcher list. */
60
61 static int
62 catcher_list_size (void)
63 {
64 int size;
65 struct catcher *catcher;
66
67 for (size = 0, catcher = current_catcher;
68 catcher != NULL;
69 catcher = catcher->prev)
70 ++size;
71
72 return size;
73 }
74
75 #endif
76
77 jmp_buf *
78 exceptions_state_mc_init (void)
79 {
80 struct catcher *new_catcher = XCNEW (struct catcher);
81
82 /* Start with no exception. */
83 new_catcher->exception = exception_none;
84
85 /* Push this new catcher on the top. */
86 new_catcher->prev = current_catcher;
87 current_catcher = new_catcher;
88 new_catcher->state = CATCHER_CREATED;
89
90 return &new_catcher->buf;
91 }
92
93 static void
94 catcher_pop (void)
95 {
96 struct catcher *old_catcher = current_catcher;
97
98 current_catcher = old_catcher->prev;
99
100 xfree (old_catcher);
101 }
102
103 /* Catcher state machine. Returns non-zero if the m/c should be run
104 again, zero if it should abort. */
105
106 static int
107 exceptions_state_mc (enum catcher_action action)
108 {
109 switch (current_catcher->state)
110 {
111 case CATCHER_CREATED:
112 switch (action)
113 {
114 case CATCH_ITER:
115 /* Allow the code to run the catcher. */
116 current_catcher->state = CATCHER_RUNNING;
117 return 1;
118 default:
119 internal_error (__FILE__, __LINE__, _("bad state"));
120 }
121 case CATCHER_RUNNING:
122 switch (action)
123 {
124 case CATCH_ITER:
125 /* No error/quit has occured. */
126 return 0;
127 case CATCH_ITER_1:
128 current_catcher->state = CATCHER_RUNNING_1;
129 return 1;
130 case CATCH_THROWING:
131 current_catcher->state = CATCHER_ABORTING;
132 /* See also throw_exception. */
133 return 1;
134 default:
135 internal_error (__FILE__, __LINE__, _("bad switch"));
136 }
137 case CATCHER_RUNNING_1:
138 switch (action)
139 {
140 case CATCH_ITER:
141 /* The did a "break" from the inner while loop. */
142 return 0;
143 case CATCH_ITER_1:
144 current_catcher->state = CATCHER_RUNNING;
145 return 0;
146 case CATCH_THROWING:
147 current_catcher->state = CATCHER_ABORTING;
148 /* See also throw_exception. */
149 return 1;
150 default:
151 internal_error (__FILE__, __LINE__, _("bad switch"));
152 }
153 case CATCHER_ABORTING:
154 switch (action)
155 {
156 case CATCH_ITER:
157 {
158 /* Exit normally if this catcher can handle this
159 exception. The caller analyses the func return
160 values. */
161 return 0;
162 }
163 default:
164 internal_error (__FILE__, __LINE__, _("bad state"));
165 }
166 default:
167 internal_error (__FILE__, __LINE__, _("bad switch"));
168 }
169 }
170
171 int
172 exceptions_state_mc_catch (struct gdb_exception *exception,
173 int mask)
174 {
175 *exception = current_catcher->exception;
176 catcher_pop ();
177
178 if (exception->reason < 0)
179 {
180 if (mask & RETURN_MASK (exception->reason))
181 {
182 /* Exit normally and let the caller handle the
183 exception. */
184 return 1;
185 }
186
187 /* The caller didn't request that the event be caught, relay the
188 event to the next exception_catch/CATCH_SJLJ. */
189 throw_exception_sjlj (*exception);
190 }
191
192 /* No exception was thrown. */
193 return 0;
194 }
195
196 int
197 exceptions_state_mc_action_iter (void)
198 {
199 return exceptions_state_mc (CATCH_ITER);
200 }
201
202 int
203 exceptions_state_mc_action_iter_1 (void)
204 {
205 return exceptions_state_mc (CATCH_ITER_1);
206 }
207
208 #if GDB_XCPT != GDB_XCPT_SJMP
209
210 /* How many nested TRY blocks we have. See exception_messages and
211 throw_it. */
212
213 static int try_scope_depth;
214
215 /* Called on entry to a TRY scope. */
216
217 void *
218 exception_try_scope_entry (void)
219 {
220 ++try_scope_depth;
221 return nullptr;
222 }
223
224 /* Called on exit of a TRY scope, either normal exit or exception
225 exit. */
226
227 void
228 exception_try_scope_exit (void *saved_state)
229 {
230 --try_scope_depth;
231 }
232
233 /* Called by the default catch block. IOW, we'll get here before
234 jumping out to the next outermost scope an exception if a GDB
235 exception is not caught. */
236
237 void
238 exception_rethrow (void)
239 {
240 throw;
241 }
242
243 /* Copy the 'gdb_exception' portion of FROM to TO. */
244
245 static void
246 gdb_exception_sliced_copy (struct gdb_exception *to, const struct gdb_exception *from)
247 {
248 *to = *from;
249 }
250
251 #endif /* !GDB_XCPT_SJMP */
252
253 /* Return EXCEPTION to the nearest containing CATCH_SJLJ block. */
254
255 void
256 throw_exception_sjlj (struct gdb_exception exception)
257 {
258 /* Jump to the nearest CATCH_SJLJ block, communicating REASON to
259 that call via setjmp's return value. Note that REASON can't be
260 zero, by definition in common-exceptions.h. */
261 exceptions_state_mc (CATCH_THROWING);
262 current_catcher->exception = exception;
263 longjmp (current_catcher->buf, exception.reason);
264 }
265
266 #if GDB_XCPT != GDB_XCPT_SJMP
267
268 /* Implementation of throw_exception that uses C++ try/catch. */
269
270 static ATTRIBUTE_NORETURN void
271 throw_exception_cxx (struct gdb_exception exception)
272 {
273 if (exception.reason == RETURN_QUIT)
274 {
275 gdb_exception_RETURN_MASK_QUIT ex;
276
277 gdb_exception_sliced_copy (&ex, &exception);
278 throw ex;
279 }
280 else if (exception.reason == RETURN_ERROR)
281 {
282 gdb_exception_RETURN_MASK_ERROR ex;
283
284 gdb_exception_sliced_copy (&ex, &exception);
285 throw ex;
286 }
287 else
288 gdb_assert_not_reached ("invalid return reason");
289 }
290
291 #endif
292
293 void
294 throw_exception (struct gdb_exception exception)
295 {
296 #if GDB_XCPT == GDB_XCPT_SJMP
297 throw_exception_sjlj (exception);
298 #else
299 throw_exception_cxx (exception);
300 #endif
301 }
302
303 /* A stack of exception messages.
304 This is needed to handle nested calls to throw_it: we don't want to
305 xfree space for a message before it's used.
306 This can happen if we throw an exception during a cleanup:
307 An outer TRY_CATCH may have an exception message it wants to print,
308 but while doing cleanups further calls to throw_it are made.
309
310 This is indexed by the size of the current_catcher list.
311 It is a dynamically allocated array so that we don't care how deeply
312 GDB nests its TRY_CATCHs. */
313 static char **exception_messages;
314
315 /* The number of currently allocated entries in exception_messages. */
316 static int exception_messages_size;
317
318 static void ATTRIBUTE_NORETURN ATTRIBUTE_PRINTF (3, 0)
319 throw_it (enum return_reason reason, enum errors error, const char *fmt,
320 va_list ap)
321 {
322 struct gdb_exception e;
323 char *new_message;
324 #if GDB_XCPT == GDB_XCPT_SJMP
325 int depth = catcher_list_size ();
326 #else
327 int depth = try_scope_depth;
328 #endif
329
330 gdb_assert (depth > 0);
331
332 /* Note: The new message may use an old message's text. */
333 new_message = xstrvprintf (fmt, ap);
334
335 if (depth > exception_messages_size)
336 {
337 int old_size = exception_messages_size;
338
339 exception_messages_size = depth + 10;
340 exception_messages = XRESIZEVEC (char *, exception_messages,
341 exception_messages_size);
342 memset (exception_messages + old_size, 0,
343 (exception_messages_size - old_size) * sizeof (char *));
344 }
345
346 xfree (exception_messages[depth - 1]);
347 exception_messages[depth - 1] = new_message;
348
349 /* Create the exception. */
350 e.reason = reason;
351 e.error = error;
352 e.message = new_message;
353
354 /* Throw the exception. */
355 throw_exception (e);
356 }
357
358 void
359 throw_verror (enum errors error, const char *fmt, va_list ap)
360 {
361 throw_it (RETURN_ERROR, error, fmt, ap);
362 }
363
364 void
365 throw_vquit (const char *fmt, va_list ap)
366 {
367 throw_it (RETURN_QUIT, GDB_NO_ERROR, fmt, ap);
368 }
369
370 void
371 throw_error (enum errors error, const char *fmt, ...)
372 {
373 va_list args;
374
375 va_start (args, fmt);
376 throw_verror (error, fmt, args);
377 va_end (args);
378 }
379
380 void
381 throw_quit (const char *fmt, ...)
382 {
383 va_list args;
384
385 va_start (args, fmt);
386 throw_vquit (fmt, args);
387 va_end (args);
388 }
This page took 0.044016 seconds and 4 git commands to generate.