Line data Source code
1 : /* Handle exceptional things in C++.
2 : Copyright (C) 1989-2023 Free Software Foundation, Inc.
3 : Contributed by Michael Tiemann <tiemann@cygnus.com>
4 : Rewritten by Mike Stump <mrs@cygnus.com>, based upon an
5 : initial re-implementation courtesy Tad Hunt.
6 :
7 : This file is part of GCC.
8 :
9 : GCC is free software; you can redistribute it and/or modify
10 : it under the terms of the GNU General Public License as published by
11 : the Free Software Foundation; either version 3, or (at your option)
12 : any later version.
13 :
14 : GCC is distributed in the hope that it will be useful,
15 : but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : GNU General Public License for more details.
18 :
19 : You should have received a copy of the GNU General Public License
20 : along with GCC; see the file COPYING3. If not see
21 : <http://www.gnu.org/licenses/>. */
22 :
23 :
24 : #include "config.h"
25 : #include "system.h"
26 : #include "coretypes.h"
27 : #include "cp-tree.h"
28 : #include "stringpool.h"
29 : #include "trans-mem.h"
30 : #include "attribs.h"
31 : #include "tree-iterator.h"
32 : #include "target.h"
33 :
34 : static void push_eh_cleanup (tree);
35 : static tree prepare_eh_type (tree);
36 : static tree do_begin_catch (void);
37 : static int dtor_nothrow (tree);
38 : static tree do_end_catch (tree);
39 : static void initialize_handler_parm (tree, tree);
40 : static tree do_allocate_exception (tree);
41 : static tree wrap_cleanups_r (tree *, int *, void *);
42 : static int complete_ptr_ref_or_void_ptr_p (tree, tree);
43 : static bool is_admissible_throw_operand_or_catch_parameter (tree, bool);
44 :
45 : /* Sets up all the global eh stuff that needs to be initialized at the
46 : start of compilation. */
47 :
48 : void
49 88336 : init_exception_processing (void)
50 : {
51 88336 : tree tmp;
52 :
53 : /* void std::terminate (); */
54 88336 : push_nested_namespace (std_node);
55 88336 : tmp = build_function_type_list (void_type_node, NULL_TREE);
56 88336 : terminate_fn = build_cp_library_fn_ptr ("terminate", tmp,
57 : ECF_NOTHROW | ECF_NORETURN
58 : | ECF_COLD);
59 88336 : gcc_checking_assert (TREE_THIS_VOLATILE (terminate_fn)
60 : && TREE_NOTHROW (terminate_fn));
61 88336 : pop_nested_namespace (std_node);
62 :
63 : /* void __cxa_call_unexpected(void *); */
64 88336 : tmp = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
65 88336 : call_unexpected_fn
66 88336 : = push_throw_library_fn (get_identifier ("__cxa_call_unexpected"), tmp);
67 88336 : call_terminate_fn
68 88336 : = push_library_fn (get_identifier ("__cxa_call_terminate"), tmp, NULL_TREE,
69 : ECF_NORETURN | ECF_COLD | ECF_NOTHROW);
70 88336 : }
71 :
72 : /* Returns an expression to be executed if an unhandled exception is
73 : propagated out of a cleanup region. */
74 :
75 : tree
76 398177 : cp_protect_cleanup_actions (void)
77 : {
78 : /* [except.terminate]
79 :
80 : When the destruction of an object during stack unwinding exits
81 : using an exception ... void terminate(); is called. */
82 398177 : return call_terminate_fn;
83 : }
84 :
85 : static tree
86 85724 : prepare_eh_type (tree type)
87 : {
88 85724 : if (type == NULL_TREE)
89 : return type;
90 85724 : if (type == error_mark_node)
91 : return error_mark_node;
92 :
93 : /* peel back references, so they match. */
94 85650 : type = non_reference (type);
95 :
96 : /* Peel off cv qualifiers. */
97 85650 : type = TYPE_MAIN_VARIANT (type);
98 :
99 : /* Functions and arrays decay to pointers. */
100 85650 : type = type_decays_to (type);
101 :
102 85650 : return type;
103 : }
104 :
105 : /* Return the type info for TYPE as used by EH machinery. */
106 : tree
107 88299 : eh_type_info (tree type)
108 : {
109 88299 : if (type == NULL_TREE || type == error_mark_node)
110 : return type;
111 :
112 88225 : return get_tinfo_decl (type);
113 : }
114 :
115 : /* Build the address of a typeinfo decl for use in the runtime
116 : matching field of the exception model. */
117 :
118 : tree
119 81922 : build_eh_type_type (tree type)
120 : {
121 81922 : tree exp = eh_type_info (type);
122 :
123 81922 : if (!exp)
124 : return NULL;
125 :
126 81922 : mark_used (exp);
127 :
128 81922 : return convert (ptr_type_node, build_address (exp));
129 : }
130 :
131 : tree
132 104014 : build_exc_ptr (void)
133 : {
134 104014 : return build_call_n (builtin_decl_explicit (BUILT_IN_EH_POINTER),
135 104014 : 1, integer_zero_node);
136 : }
137 :
138 : /* Declare an exception ABI entry point called NAME.
139 : ECF are the library flags, RTYPE the return type and ARGS[NARGS]
140 : the parameter types. We return the DECL -- which might be one
141 : found via the symbol table pushing, if the user already declared
142 : it. If we pushed a new decl, the user will see it. */
143 :
144 : static tree
145 55332 : declare_library_fn_1 (const char *name, int ecf,
146 : tree rtype, int nargs, tree args[])
147 : {
148 55332 : tree ident = get_identifier (name);
149 55332 : tree except = ecf & ECF_NOTHROW ? empty_except_spec : NULL_TREE;
150 :
151 : /* Make a new decl. */
152 55332 : tree arg_list = void_list_node;
153 114526 : for (unsigned ix = nargs; ix--;)
154 59194 : arg_list = tree_cons (NULL_TREE, args[ix], arg_list);
155 55332 : tree fntype = build_function_type (rtype, arg_list);
156 55332 : tree res = push_library_fn (ident, fntype, except, ecf);
157 :
158 55332 : return res;
159 : }
160 :
161 : /* Find or declare a function NAME, returning RTYPE, taking a single
162 : parameter PTYPE, with an empty exception specification. ECF are the
163 : library fn flags. If TM_ECF is non-zero, also find or create a
164 : transaction variant and record it as a replacement, when flag_tm is
165 : in effect.
166 :
167 : Note that the C++ ABI document does not have a throw-specifier on
168 : the routines declared below via this function. The declarations
169 : are consistent with the actual implementations in libsupc++. */
170 :
171 : static tree
172 42335 : declare_library_fn (const char *name, tree rtype, tree ptype,
173 : int ecf, int tm_ecf)
174 : {
175 53974 : tree res = declare_library_fn_1 (name, ecf, rtype, ptype ? 1 : 0, &ptype);
176 42335 : if (res == error_mark_node)
177 : return res;
178 :
179 42279 : if (tm_ecf && flag_tm)
180 : {
181 66 : char *tm_name = concat ("_ITM_", name + 2, NULL_TREE);
182 :
183 66 : tree tm_fn = declare_library_fn_1 (tm_name, ecf | tm_ecf, rtype,
184 : ptype ? 1 : 0, &ptype);
185 66 : free (tm_name);
186 66 : if (tm_fn != error_mark_node)
187 66 : record_tm_replacement (res, tm_fn);
188 : }
189 :
190 : return res;
191 : }
192 :
193 : /* Build up a call to __cxa_get_exception_ptr so that we can build a
194 : copy constructor for the thrown object. */
195 :
196 : static tree
197 281 : do_get_exception_ptr (void)
198 : {
199 281 : if (!get_exception_ptr_fn)
200 : /* Declare void* __cxa_get_exception_ptr (void *) throw(). */
201 143 : get_exception_ptr_fn
202 143 : = declare_library_fn ("__cxa_get_exception_ptr",
203 : ptr_type_node, ptr_type_node,
204 : ECF_NOTHROW | ECF_PURE | ECF_LEAF | ECF_TM_PURE,
205 : 0);
206 :
207 281 : return cp_build_function_call_nary (get_exception_ptr_fn,
208 : tf_warning_or_error,
209 281 : build_exc_ptr (), NULL_TREE);
210 : }
211 :
212 : /* Build up a call to __cxa_begin_catch, to tell the runtime that the
213 : exception has been handled. */
214 :
215 : static tree
216 101046 : do_begin_catch (void)
217 : {
218 101046 : if (!begin_catch_fn)
219 : /* Declare void* __cxa_begin_catch (void *) throw(). */
220 11639 : begin_catch_fn
221 11639 : = declare_library_fn ("__cxa_begin_catch",
222 : ptr_type_node, ptr_type_node, ECF_NOTHROW,
223 : ECF_TM_PURE);
224 :
225 101046 : return cp_build_function_call_nary (begin_catch_fn, tf_warning_or_error,
226 101046 : build_exc_ptr (), NULL_TREE);
227 : }
228 :
229 : /* Returns nonzero if cleaning up an exception of type TYPE (which can be
230 : NULL_TREE for a ... handler) will not throw an exception. */
231 :
232 : static int
233 101034 : dtor_nothrow (tree type)
234 : {
235 101034 : if (type == NULL_TREE || type == error_mark_node)
236 : return 0;
237 :
238 6063 : if (TYPE_HAS_TRIVIAL_DESTRUCTOR (type))
239 : return 1;
240 :
241 2570 : if (CLASSTYPE_LAZY_DESTRUCTOR (type))
242 133 : lazily_declare_fn (sfk_destructor, type);
243 :
244 2570 : return TREE_NOTHROW (CLASSTYPE_DESTRUCTOR (type));
245 : }
246 :
247 : /* Build up a call to __cxa_end_catch, to destroy the exception object
248 : for the current catch block if no others are currently using it. */
249 :
250 : static tree
251 101046 : do_end_catch (tree type)
252 : {
253 101046 : if (!end_catch_fn)
254 : /* Declare void __cxa_end_catch ().
255 : This can throw if the destructor for the exception throws. */
256 11639 : end_catch_fn
257 11639 : = declare_library_fn ("__cxa_end_catch", void_type_node,
258 : NULL_TREE, 0, ECF_TM_PURE);
259 :
260 101046 : tree cleanup = cp_build_function_call_vec (end_catch_fn,
261 : NULL, tf_warning_or_error);
262 101046 : if (cleanup != error_mark_node)
263 101034 : TREE_NOTHROW (cleanup) = dtor_nothrow (type);
264 :
265 101046 : return cleanup;
266 : }
267 :
268 : /* This routine creates the cleanup for the current exception. */
269 :
270 : static void
271 101046 : push_eh_cleanup (tree type)
272 : {
273 101046 : finish_decl_cleanup (NULL_TREE, do_end_catch (type));
274 101046 : }
275 :
276 : /* Wrap EXPR in a MUST_NOT_THROW_EXPR expressing that EXPR must
277 : not throw any exceptions if COND is true. A condition of
278 : NULL_TREE is treated as 'true'. */
279 :
280 : tree
281 411 : build_must_not_throw_expr (tree body, tree cond)
282 : {
283 411 : tree type = body ? TREE_TYPE (body) : void_type_node;
284 :
285 411 : if (!flag_exceptions)
286 : return body;
287 :
288 408 : if (!cond)
289 : /* OK, unconditional. */;
290 : else
291 : {
292 121 : tree conv = NULL_TREE;
293 121 : if (!type_dependent_expression_p (cond))
294 100 : conv = perform_implicit_conversion_flags (boolean_type_node, cond,
295 : tf_warning_or_error,
296 : LOOKUP_NORMAL);
297 121 : if (tree inst = instantiate_non_dependent_or_null (conv))
298 94 : cond = cxx_constant_value (inst);
299 : else
300 27 : require_constant_expression (cond);
301 121 : if (integer_zerop (cond))
302 : return body;
303 91 : else if (integer_onep (cond))
304 333 : cond = NULL_TREE;
305 : }
306 :
307 378 : return build2 (MUST_NOT_THROW_EXPR, type, body, cond);
308 : }
309 :
310 :
311 : /* Initialize the catch parameter DECL. */
312 :
313 : static void
314 6051 : initialize_handler_parm (tree decl, tree exp)
315 : {
316 6051 : tree init;
317 6051 : tree init_type;
318 :
319 : /* Make sure we mark the catch param as used, otherwise we'll get a
320 : warning about an unused ((anonymous)). */
321 6051 : TREE_USED (decl) = 1;
322 6051 : DECL_READ_P (decl) = 1;
323 :
324 : /* Figure out the type that the initializer is. Pointers are returned
325 : adjusted by value from __cxa_begin_catch. Others are returned by
326 : reference. */
327 6051 : init_type = TREE_TYPE (decl);
328 6051 : if (!INDIRECT_TYPE_P (init_type))
329 1351 : init_type = build_reference_type (init_type);
330 :
331 : /* Since pointers are passed by value, initialize a reference to
332 : pointer catch parm with the address of the temporary. */
333 6051 : if (TYPE_REF_P (init_type)
334 6051 : && TYPE_PTR_P (TREE_TYPE (init_type)))
335 14 : exp = cp_build_addr_expr (exp, tf_warning_or_error);
336 :
337 6051 : exp = ocp_convert (init_type, exp, CONV_IMPLICIT|CONV_FORCE_TEMP, 0,
338 : tf_warning_or_error);
339 :
340 6051 : init = convert_from_reference (exp);
341 :
342 : /* If the constructor for the catch parm exits via an exception, we
343 : must call terminate. See eh23.C. */
344 6051 : if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
345 : {
346 : /* Generate the copy constructor call directly so we can wrap it.
347 : See also expand_default_init. */
348 281 : init = ocp_convert (TREE_TYPE (decl), init,
349 : CONV_IMPLICIT|CONV_FORCE_TEMP, 0,
350 : tf_warning_or_error);
351 : /* Force cleanups now to avoid nesting problems with the
352 : MUST_NOT_THROW_EXPR. */
353 281 : init = fold_build_cleanup_point_expr (TREE_TYPE (init), init);
354 281 : init = build_must_not_throw_expr (init, NULL_TREE);
355 : }
356 :
357 6051 : decl = pushdecl (decl);
358 :
359 6051 : start_decl_1 (decl, true);
360 6051 : cp_finish_decl (decl, init, /*init_const_expr_p=*/false, NULL_TREE,
361 : LOOKUP_ONLYCONVERTING|DIRECT_BIND);
362 6051 : }
363 :
364 :
365 : /* Routine to see if exception handling is turned on.
366 : DO_WARN is nonzero if we want to inform the user that exception
367 : handling is turned off.
368 :
369 : This is used to ensure that -fexceptions has been specified if the
370 : compiler tries to use any exception-specific functions. */
371 :
372 : static inline int
373 294127 : doing_eh (void)
374 : {
375 294127 : if (! flag_exceptions)
376 : {
377 14 : static int warned = 0;
378 14 : if (! warned)
379 : {
380 7 : error ("exception handling disabled, use %<-fexceptions%> to enable");
381 7 : warned = 1;
382 : }
383 14 : return 0;
384 : }
385 : return 1;
386 : }
387 :
388 : /* Call this to start a catch block. DECL is the catch parameter. */
389 :
390 : tree
391 101050 : expand_start_catch_block (tree decl)
392 : {
393 101050 : tree exp;
394 101050 : tree type, init;
395 :
396 101050 : if (! doing_eh ())
397 : return NULL_TREE;
398 :
399 101046 : if (decl)
400 : {
401 6149 : if (!is_admissible_throw_operand_or_catch_parameter (decl, false))
402 74 : decl = error_mark_node;
403 :
404 6149 : type = prepare_eh_type (TREE_TYPE (decl));
405 6149 : mark_used (eh_type_info (type));
406 : }
407 : else
408 : type = NULL_TREE;
409 :
410 : /* Call __cxa_end_catch at the end of processing the exception. */
411 101046 : push_eh_cleanup (type);
412 :
413 101046 : init = do_begin_catch ();
414 :
415 : /* If there's no decl at all, then all we need to do is make sure
416 : to tell the runtime that we've begun handling the exception. */
417 101046 : if (decl == NULL || decl == error_mark_node || init == error_mark_node)
418 94987 : finish_expr_stmt (init);
419 :
420 : /* If the C++ object needs constructing, we need to do that before
421 : calling __cxa_begin_catch, so that std::uncaught_exception gets
422 : the right value during the copy constructor. */
423 6059 : else if (flag_use_cxa_get_exception_ptr
424 6059 : && TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
425 : {
426 281 : exp = do_get_exception_ptr ();
427 281 : if (exp != error_mark_node)
428 273 : initialize_handler_parm (decl, exp);
429 281 : finish_expr_stmt (init);
430 : }
431 :
432 : /* Otherwise the type uses a bitwise copy, and we don't have to worry
433 : about the value of std::uncaught_exception and therefore can do the
434 : copy with the return value of __cxa_end_catch instead. */
435 : else
436 : {
437 5778 : tree init_type = type;
438 :
439 : /* Pointers are passed by values, everything else by reference. */
440 5778 : if (!TYPE_PTR_P (type))
441 4070 : init_type = build_pointer_type (type);
442 5778 : if (init_type != TREE_TYPE (init))
443 5719 : init = build1 (NOP_EXPR, init_type, init);
444 5778 : exp = create_temporary_var (init_type);
445 5778 : cp_finish_decl (exp, init, /*init_const_expr=*/false,
446 : NULL_TREE, LOOKUP_ONLYCONVERTING);
447 5778 : DECL_REGISTER (exp) = 1;
448 5778 : initialize_handler_parm (decl, exp);
449 : }
450 :
451 : return type;
452 : }
453 :
454 : /* True if we are in a catch block within a catch block. Assumes that we are
455 : in function scope. */
456 :
457 : static bool
458 93 : in_nested_catch (void)
459 : {
460 93 : int catches = 0;
461 :
462 : /* Scan through the template parameter scopes. */
463 93 : for (cp_binding_level *b = current_binding_level;
464 305 : b->kind != sk_function_parms;
465 212 : b = b->level_chain)
466 216 : if (b->kind == sk_catch
467 216 : && ++catches == 2)
468 : return true;
469 : return false;
470 : }
471 :
472 : /* Call this to end a catch block. Its responsible for emitting the
473 : code to handle jumping back to the correct place, and for emitting
474 : the label to jump to if this catch block didn't match. */
475 :
476 : void
477 101050 : expand_end_catch_block (void)
478 : {
479 101050 : if (! doing_eh ())
480 : return;
481 :
482 : /* The exception being handled is rethrown if control reaches the end of
483 : a handler of the function-try-block of a constructor or destructor. */
484 101046 : if (in_function_try_handler
485 486 : && (DECL_CONSTRUCTOR_P (current_function_decl)
486 155 : || DECL_DESTRUCTOR_P (current_function_decl))
487 101139 : && !in_nested_catch ())
488 : {
489 89 : tree rethrow = build_throw (input_location, NULL_TREE);
490 : /* Disable all warnings for the generated rethrow statement. */
491 89 : suppress_warning (rethrow);
492 89 : finish_expr_stmt (rethrow);
493 : }
494 : }
495 :
496 : tree
497 10840804 : begin_eh_spec_block (void)
498 : {
499 10840804 : tree r;
500 10840804 : location_t spec_location = DECL_SOURCE_LOCATION (current_function_decl);
501 :
502 : /* A noexcept specification (or throw() with -fnothrow-opt) is a
503 : MUST_NOT_THROW_EXPR. */
504 10840804 : if (TYPE_NOEXCEPT_P (TREE_TYPE (current_function_decl)))
505 : {
506 10824617 : r = build_stmt (spec_location, MUST_NOT_THROW_EXPR,
507 : NULL_TREE, NULL_TREE);
508 10824617 : TREE_SIDE_EFFECTS (r) = 1;
509 : }
510 : else
511 16187 : r = build_stmt (spec_location, EH_SPEC_BLOCK, NULL_TREE, NULL_TREE);
512 10840804 : add_stmt (r);
513 10840804 : TREE_OPERAND (r, 0) = push_stmt_list ();
514 10840804 : return r;
515 : }
516 :
517 : void
518 10840804 : finish_eh_spec_block (tree raw_raises, tree eh_spec_block)
519 : {
520 10840804 : tree raises;
521 :
522 10840804 : TREE_OPERAND (eh_spec_block, 0)
523 10840804 : = pop_stmt_list (TREE_OPERAND (eh_spec_block, 0));
524 :
525 10840804 : if (TREE_CODE (eh_spec_block) == MUST_NOT_THROW_EXPR)
526 : return;
527 :
528 : /* Strip cv quals, etc, from the specification types. */
529 228 : for (raises = NULL_TREE;
530 32640 : raw_raises && TREE_VALUE (raw_raises);
531 228 : raw_raises = TREE_CHAIN (raw_raises))
532 : {
533 228 : tree type = prepare_eh_type (TREE_VALUE (raw_raises));
534 228 : tree tinfo = eh_type_info (type);
535 :
536 228 : mark_used (tinfo);
537 228 : raises = tree_cons (NULL_TREE, type, raises);
538 : }
539 :
540 16187 : EH_SPEC_RAISES (eh_spec_block) = raises;
541 : }
542 :
543 : /* Return a pointer to a buffer for an exception object of type TYPE. */
544 :
545 : static tree
546 79377 : do_allocate_exception (tree type)
547 : {
548 79377 : if (!allocate_exception_fn)
549 : /* Declare void *__cxa_allocate_exception(size_t) throw(). */
550 9463 : allocate_exception_fn
551 9463 : = declare_library_fn ("__cxa_allocate_exception",
552 : ptr_type_node, size_type_node,
553 : ECF_NOTHROW | ECF_MALLOC | ECF_COLD, ECF_TM_PURE);
554 :
555 79377 : return cp_build_function_call_nary (allocate_exception_fn,
556 : tf_warning_or_error,
557 79377 : size_in_bytes (type), NULL_TREE);
558 : }
559 :
560 : /* Call __cxa_free_exception from a cleanup. This is never invoked
561 : directly, but see the comment for stabilize_throw_expr. */
562 :
563 : static tree
564 79353 : do_free_exception (tree ptr)
565 : {
566 79353 : if (!free_exception_fn)
567 : /* Declare void __cxa_free_exception (void *) throw(). */
568 9451 : free_exception_fn
569 9451 : = declare_library_fn ("__cxa_free_exception",
570 : void_type_node, ptr_type_node,
571 : ECF_NOTHROW | ECF_LEAF, ECF_TM_PURE);
572 :
573 79353 : return cp_build_function_call_nary (free_exception_fn,
574 79353 : tf_warning_or_error, ptr, NULL_TREE);
575 : }
576 :
577 : /* Wrap all cleanups for TARGET_EXPRs in MUST_NOT_THROW_EXPR.
578 : Called from build_throw via walk_tree_without_duplicates. */
579 :
580 : static tree
581 1842154 : wrap_cleanups_r (tree *tp, int *walk_subtrees, void * /*data*/)
582 : {
583 1842154 : tree exp = *tp;
584 1842154 : tree cleanup;
585 :
586 : /* Don't walk into types. */
587 1842154 : if (TYPE_P (exp))
588 : {
589 9 : *walk_subtrees = 0;
590 9 : return NULL_TREE;
591 : }
592 1842145 : if (TREE_CODE (exp) != TARGET_EXPR)
593 : return NULL_TREE;
594 :
595 106376 : cleanup = TARGET_EXPR_CLEANUP (exp);
596 106376 : if (cleanup)
597 : {
598 94739 : cleanup = build2 (MUST_NOT_THROW_EXPR, void_type_node, cleanup,
599 : NULL_TREE);
600 94739 : TARGET_EXPR_CLEANUP (exp) = cleanup;
601 : }
602 :
603 : /* Keep iterating. */
604 : return NULL_TREE;
605 : }
606 :
607 : /* Build a throw expression. */
608 :
609 : tree
610 956752 : build_throw (location_t loc, tree exp)
611 : {
612 956752 : if (exp == error_mark_node)
613 : return exp;
614 :
615 956721 : if (processing_template_decl)
616 : {
617 864671 : if (cfun)
618 864658 : current_function_returns_abnormally = 1;
619 864671 : exp = build_min (THROW_EXPR, void_type_node, exp);
620 864671 : SET_EXPR_LOCATION (exp, loc);
621 864671 : return exp;
622 : }
623 :
624 92050 : if (exp && null_node_p (exp))
625 4 : warning_at (loc, 0,
626 : "throwing NULL, which has integral, not pointer type");
627 :
628 92050 : if (exp != NULL_TREE)
629 : {
630 79400 : if (!is_admissible_throw_operand_or_catch_parameter (exp, true))
631 23 : return error_mark_node;
632 : }
633 :
634 92027 : if (! doing_eh ())
635 6 : return error_mark_node;
636 :
637 92021 : if (exp)
638 : {
639 79377 : tree throw_type;
640 79377 : tree temp_type;
641 79377 : tree cleanup;
642 79377 : tree object, ptr;
643 79377 : tree allocate_expr;
644 :
645 79377 : tsubst_flags_t complain = tf_warning_or_error;
646 :
647 : /* The CLEANUP_TYPE is the internal type of a destructor. */
648 79377 : if (!cleanup_type)
649 : {
650 9463 : tree tmp = build_function_type_list (void_type_node,
651 : ptr_type_node, NULL_TREE);
652 9463 : cleanup_type = build_pointer_type (tmp);
653 : }
654 :
655 79377 : if (!throw_fn)
656 : {
657 9463 : tree args[3] = {ptr_type_node, ptr_type_node, cleanup_type};
658 :
659 9463 : throw_fn = declare_library_fn_1 ("__cxa_throw",
660 : ECF_NORETURN | ECF_COLD,
661 : void_type_node, 3, args);
662 9463 : if (flag_tm && throw_fn != error_mark_node)
663 : {
664 19 : tree itm_fn = declare_library_fn_1 ("_ITM_cxa_throw",
665 : ECF_NORETURN | ECF_COLD,
666 : void_type_node, 3, args);
667 19 : if (itm_fn != error_mark_node)
668 : {
669 19 : apply_tm_attr (itm_fn, get_identifier ("transaction_pure"));
670 19 : record_tm_replacement (throw_fn, itm_fn);
671 : }
672 : }
673 : }
674 :
675 : /* [except.throw]
676 :
677 : A throw-expression initializes a temporary object, the type
678 : of which is determined by removing any top-level
679 : cv-qualifiers from the static type of the operand of throw
680 : and adjusting the type from "array of T" or "function return
681 : T" to "pointer to T" or "pointer to function returning T"
682 : respectively. */
683 79377 : temp_type = is_bitfield_expr_with_lowered_type (exp);
684 79377 : if (!temp_type)
685 79377 : temp_type = cv_unqualified (type_decays_to (TREE_TYPE (exp)));
686 :
687 : /* OK, this is kind of wacky. The standard says that we call
688 : terminate when the exception handling mechanism, after
689 : completing evaluation of the expression to be thrown but
690 : before the exception is caught (_except.throw_), calls a
691 : user function that exits via an uncaught exception.
692 :
693 : So we have to protect the actual initialization of the
694 : exception object with terminate(), but evaluate the
695 : expression first. Since there could be temps in the
696 : expression, we need to handle that, too. We also expand
697 : the call to __cxa_allocate_exception first (which doesn't
698 : matter, since it can't throw). */
699 :
700 : /* Allocate the space for the exception. */
701 79377 : allocate_expr = do_allocate_exception (temp_type);
702 79377 : if (allocate_expr == error_mark_node)
703 : return error_mark_node;
704 79353 : allocate_expr = get_target_expr (allocate_expr);
705 79353 : ptr = TARGET_EXPR_SLOT (allocate_expr);
706 79353 : TARGET_EXPR_CLEANUP (allocate_expr) = do_free_exception (ptr);
707 79353 : CLEANUP_EH_ONLY (allocate_expr) = 1;
708 :
709 79353 : object = build_nop (build_pointer_type (temp_type), ptr);
710 79353 : object = cp_build_fold_indirect_ref (object);
711 :
712 : /* And initialize the exception object. */
713 79353 : if (CLASS_TYPE_P (temp_type))
714 : {
715 76845 : int flags = LOOKUP_NORMAL | LOOKUP_ONLYCONVERTING;
716 76845 : bool converted = false;
717 76845 : location_t exp_loc = cp_expr_loc_or_loc (exp, loc);
718 :
719 : /* Under C++0x [12.8/16 class.copy], a thrown lvalue is sometimes
720 : treated as an rvalue for the purposes of overload resolution
721 : to favor move constructors over copy constructors. */
722 76845 : if (tree moved = treat_lvalue_as_rvalue_p (exp, /*return*/false))
723 : /* In C++20 we treat the return value as an rvalue that
724 : can bind to lvalue refs. In C++23, such an expression is just
725 : an xvalue. */
726 44 : exp = moved;
727 :
728 : /* Call the copy constructor. */
729 76845 : if (!converted)
730 : {
731 76845 : releasing_vec exp_vec (make_tree_vector_single (exp));
732 76845 : exp = (build_special_member_call
733 76845 : (object, complete_ctor_identifier, &exp_vec,
734 76845 : TREE_TYPE (object), flags, tf_warning_or_error));
735 76845 : }
736 :
737 76845 : if (exp == error_mark_node)
738 : {
739 2 : inform (exp_loc, " in thrown expression");
740 2 : return error_mark_node;
741 : }
742 : }
743 : else
744 : {
745 2508 : tree tmp = decay_conversion (exp, tf_warning_or_error);
746 2508 : if (tmp == error_mark_node)
747 : return error_mark_node;
748 2504 : exp = cp_build_init_expr (object, tmp);
749 : }
750 :
751 : /* Mark any cleanups from the initialization as MUST_NOT_THROW, since
752 : they are run after the exception object is initialized. */
753 79347 : cp_walk_tree_without_duplicates (&exp, wrap_cleanups_r, 0);
754 :
755 : /* Prepend the allocation. */
756 79347 : exp = build2 (COMPOUND_EXPR, TREE_TYPE (exp), allocate_expr, exp);
757 :
758 : /* Force all the cleanups to be evaluated here so that we don't have
759 : to do them during unwinding. */
760 79347 : exp = build1 (CLEANUP_POINT_EXPR, void_type_node, exp);
761 :
762 79347 : throw_type = build_eh_type_type (prepare_eh_type (TREE_TYPE (object)));
763 :
764 79347 : cleanup = NULL_TREE;
765 79347 : if (type_build_dtor_call (TREE_TYPE (object)))
766 : {
767 75047 : tree binfo = TYPE_BINFO (TREE_TYPE (object));
768 75047 : tree dtor_fn = lookup_fnfields (binfo,
769 : complete_dtor_identifier, 0,
770 : tf_warning_or_error);
771 75047 : dtor_fn = BASELINK_FUNCTIONS (dtor_fn);
772 75047 : if (!mark_used (dtor_fn)
773 75047 : || !perform_or_defer_access_check (binfo, dtor_fn,
774 : dtor_fn, complain))
775 0 : return error_mark_node;
776 75047 : if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (object)))
777 : {
778 75047 : cxx_mark_addressable (dtor_fn);
779 : /* Pretend it's a normal function. */
780 75047 : cleanup = build1 (ADDR_EXPR, cleanup_type, dtor_fn);
781 : }
782 : }
783 75047 : if (cleanup == NULL_TREE)
784 4300 : cleanup = build_int_cst (cleanup_type, 0);
785 :
786 : /* ??? Indicate that this function call throws throw_type. */
787 79347 : tree tmp = cp_build_function_call_nary (throw_fn, tf_warning_or_error,
788 : ptr, throw_type, cleanup,
789 : NULL_TREE);
790 :
791 : /* Tack on the initialization stuff. */
792 79347 : exp = build2 (COMPOUND_EXPR, TREE_TYPE (tmp), exp, tmp);
793 : }
794 : else
795 : {
796 : /* Rethrow current exception. */
797 12644 : if (!rethrow_fn)
798 : {
799 3449 : rethrow_fn = declare_library_fn_1 ("__cxa_rethrow",
800 : ECF_NORETURN | ECF_COLD,
801 : void_type_node, 0, NULL);
802 3449 : if (flag_tm && rethrow_fn != error_mark_node)
803 7 : apply_tm_attr (rethrow_fn, get_identifier ("transaction_pure"));
804 : }
805 :
806 : /* ??? Indicate that this function call allows exceptions of the type
807 : of the enclosing catch block (if known). */
808 12644 : exp = cp_build_function_call_vec (rethrow_fn, NULL, tf_warning_or_error);
809 : }
810 :
811 91991 : exp = build1_loc (loc, THROW_EXPR, void_type_node, exp);
812 :
813 91991 : return exp;
814 : }
815 :
816 : /* Make sure TYPE is complete, pointer to complete, reference to
817 : complete, or pointer to cv void. Issue diagnostic on failure.
818 : Return the zero on failure and nonzero on success. FROM can be
819 : the expr or decl from whence TYPE came, if available. */
820 :
821 : static int
822 85549 : complete_ptr_ref_or_void_ptr_p (tree type, tree from)
823 : {
824 85549 : int is_ptr;
825 :
826 : /* Check complete. */
827 85549 : type = complete_type_or_else (type, from);
828 85549 : if (!type)
829 : return 0;
830 :
831 : /* Or a pointer or ref to one, or cv void *. */
832 85477 : is_ptr = TYPE_PTR_P (type);
833 85477 : if (is_ptr || TYPE_REF_P (type))
834 : {
835 5096 : tree core = TREE_TYPE (type);
836 :
837 5096 : if (is_ptr && VOID_TYPE_P (core))
838 : /* OK */;
839 5025 : else if (!complete_type_or_else (core, from))
840 : return 0;
841 : }
842 : return 1;
843 : }
844 :
845 : /* If IS_THROW is true return truth-value if T is an expression admissible
846 : in throw-expression, i.e. if it is not of incomplete type or a pointer/
847 : reference to such a type or of an abstract class type.
848 : If IS_THROW is false, likewise for a catch parameter, same requirements
849 : for its type plus rvalue reference type is also not admissible. */
850 :
851 : static bool
852 85549 : is_admissible_throw_operand_or_catch_parameter (tree t, bool is_throw)
853 : {
854 85549 : tree expr = is_throw ? t : NULL_TREE;
855 85549 : tree type = TREE_TYPE (t);
856 :
857 : /* C++11 [except.handle] The exception-declaration shall not denote
858 : an incomplete type, an abstract class type, or an rvalue reference
859 : type. */
860 :
861 : /* 15.1/4 [...] The type of the throw-expression shall not be an
862 : incomplete type, or a pointer or a reference to an incomplete
863 : type, other than void*, const void*, volatile void*, or
864 : const volatile void*. Except for these restriction and the
865 : restrictions on type matching mentioned in 15.3, the operand
866 : of throw is treated exactly as a function argument in a call
867 : (5.2.2) or the operand of a return statement. */
868 85549 : if (!complete_ptr_ref_or_void_ptr_p (type, expr))
869 : return false;
870 :
871 85473 : tree nonref_type = non_reference (type);
872 85473 : if (!verify_type_context (input_location, TCTX_EXCEPTIONS, nonref_type))
873 : return false;
874 :
875 : /* 10.4/3 An abstract class shall not be used as a parameter type,
876 : as a function return type or as type of an explicit
877 : conversion. */
878 91558 : else if (abstract_virtuals_error (is_throw ? ACU_THROW : ACU_CATCH, type))
879 : return false;
880 85463 : else if (!is_throw
881 6082 : && TYPE_REF_P (type)
882 88472 : && TYPE_REF_IS_RVALUE (type))
883 : {
884 3 : error ("cannot declare %<catch%> parameter to be of rvalue "
885 : "reference type %qT", type);
886 3 : return false;
887 : }
888 85460 : else if (variably_modified_type_p (type, NULL_TREE))
889 : {
890 8 : if (is_throw)
891 4 : error_at (cp_expr_loc_or_input_loc (expr),
892 : "cannot throw expression of type %qT because it involves "
893 : "types of variable size", type);
894 : else
895 4 : error ("cannot catch type %qT because it involves types of "
896 : "variable size", type);
897 8 : return false;
898 : }
899 :
900 : return true;
901 : }
902 :
903 : /* Returns nonzero if FN is a declaration of a standard C library
904 : function which is known not to throw.
905 :
906 : [lib.res.on.exception.handling]: None of the functions from the
907 : Standard C library shall report an error by throwing an
908 : exception, unless it calls a program-supplied function that
909 : throws an exception. */
910 :
911 : #include "cfns.h"
912 :
913 : int
914 72643910 : nothrow_libfn_p (const_tree fn)
915 : {
916 72643910 : tree id;
917 :
918 72643910 : if (TREE_PUBLIC (fn)
919 71800936 : && DECL_EXTERNAL (fn)
920 71800936 : && DECL_NAMESPACE_SCOPE_P (fn)
921 98761177 : && DECL_EXTERN_C_P (fn))
922 : /* OK */;
923 : else
924 : /* Can't be a C library function. */
925 : return 0;
926 :
927 : /* Being a C library function, DECL_ASSEMBLER_NAME == DECL_NAME
928 : unless the system headers are playing rename tricks, and if
929 : they are, we don't want to be confused by them. */
930 1708674 : id = DECL_NAME (fn);
931 1708674 : const struct libc_name_struct *s
932 1708674 : = libc_name::libc_name_p (IDENTIFIER_POINTER (id), IDENTIFIER_LENGTH (id));
933 1708674 : if (s == NULL)
934 : return 0;
935 12190 : switch (s->c_ver)
936 : {
937 : case 89: return 1;
938 420 : case 99: return !flag_iso || flag_isoc99;
939 28 : case 11: return !flag_iso || flag_isoc11;
940 0 : default: gcc_unreachable ();
941 : }
942 : }
943 :
944 : /* Returns nonzero if an exception of type FROM will be caught by a
945 : handler for type TO, as per [except.handle]. */
946 :
947 : static bool
948 4275 : can_convert_eh (tree to, tree from)
949 : {
950 4275 : to = non_reference (to);
951 4275 : from = non_reference (from);
952 :
953 4275 : if (same_type_ignoring_top_level_qualifiers_p (to, from))
954 : return true;
955 :
956 4248 : if (TYPE_PTR_P (to) && TYPE_PTR_P (from))
957 : {
958 608 : to = TREE_TYPE (to);
959 608 : from = TREE_TYPE (from);
960 :
961 608 : if (! at_least_as_qualified_p (to, from))
962 : return false;
963 :
964 580 : if (VOID_TYPE_P (to))
965 : return true;
966 :
967 : /* Else fall through. */
968 : }
969 :
970 3984 : if (CLASS_TYPE_P (to) && CLASS_TYPE_P (from)
971 7815 : && publicly_uniquely_derived_p (to, from))
972 : return true;
973 :
974 : return false;
975 : }
976 :
977 : /* Check whether any of the handlers in I are shadowed by another handler
978 : accepting TYPE. Note that the shadowing may not be complete; even if
979 : an exception of type B would be caught by a handler for A, there could
980 : be a derived class C for which A is an ambiguous base but B is not, so
981 : the handler for B would catch an exception of type C. */
982 :
983 : static void
984 333173 : check_handlers_1 (tree master, tree_stmt_iterator i)
985 : {
986 333173 : tree type = TREE_TYPE (master);
987 :
988 669584 : for (; !tsi_end_p (i); tsi_next (&i))
989 : {
990 336746 : tree handler = tsi_stmt (i);
991 336746 : if (TREE_TYPE (handler) && can_convert_eh (type, TREE_TYPE (handler)))
992 : {
993 335 : auto_diagnostic_group d;
994 335 : if (warning_at (EXPR_LOCATION (handler), OPT_Wexceptions,
995 : "exception of type %qT will be caught by earlier "
996 335 : "handler", TREE_TYPE (handler)))
997 35 : inform (EXPR_LOCATION (master), "for type %qT", type);
998 335 : break;
999 335 : }
1000 : }
1001 333173 : }
1002 :
1003 : /* Given a STATEMENT_LIST of HANDLERs, make sure that they're OK. */
1004 :
1005 : void
1006 992485 : check_handlers (tree handlers)
1007 : {
1008 992485 : tree_stmt_iterator i;
1009 :
1010 : /* If we don't have a STATEMENT_LIST, then we've just got one
1011 : handler, and thus nothing to warn about. */
1012 992485 : if (TREE_CODE (handlers) != STATEMENT_LIST)
1013 660285 : return;
1014 :
1015 332200 : i = tsi_start (handlers);
1016 332200 : if (!tsi_end_p (i))
1017 665381 : while (1)
1018 : {
1019 665381 : tree handler = tsi_stmt (i);
1020 665381 : tsi_next (&i);
1021 :
1022 : /* No more handlers; nothing to shadow. */
1023 665381 : if (tsi_end_p (i))
1024 : break;
1025 333181 : if (TREE_TYPE (handler) == NULL_TREE)
1026 8 : permerror (EXPR_LOCATION (handler), "%<...%>"
1027 : " handler must be the last handler for its try block");
1028 : else
1029 333173 : check_handlers_1 (handler, i);
1030 : }
1031 : }
1032 :
1033 : /* walk_tree helper for finish_noexcept_expr. Returns non-null if the
1034 : expression *TP causes the noexcept operator to evaluate to false.
1035 :
1036 : 5.3.7 [expr.noexcept]: The result of the noexcept operator is false if
1037 : in a potentially-evaluated context the expression would contain
1038 : * a potentially evaluated call to a function, member function,
1039 : function pointer, or member function pointer that does not have a
1040 : non-throwing exception-specification (15.4),
1041 : * a potentially evaluated throw-expression (15.1),
1042 : * a potentially evaluated dynamic_cast expression dynamic_cast<T>(v),
1043 : where T is a reference type, that requires a run-time check (5.2.7), or
1044 : * a potentially evaluated typeid expression (5.2.8) applied to a glvalue
1045 : expression whose type is a polymorphic class type (10.3). */
1046 :
1047 : static tree
1048 20280588 : check_noexcept_r (tree *tp, int *walk_subtrees, void *)
1049 : {
1050 20280588 : tree t = *tp;
1051 20280588 : enum tree_code code = TREE_CODE (t);
1052 :
1053 20280588 : if (unevaluated_p (code))
1054 4 : *walk_subtrees = false;
1055 2691533 : else if ((code == CALL_EXPR && CALL_EXPR_FN (t))
1056 20280584 : || code == AGGR_INIT_EXPR)
1057 : {
1058 : /* We can only use the exception specification of the called function
1059 : for determining the value of a noexcept expression; we can't use
1060 : TREE_NOTHROW, as it might have a different value in another
1061 : translation unit, creating ODR problems.
1062 :
1063 : We could use TREE_NOTHROW (t) for !TREE_PUBLIC fns, though... */
1064 2736702 : tree fn = cp_get_callee (t);
1065 2736702 : if (concept_check_p (fn))
1066 : return NULL_TREE;
1067 2736701 : tree type = TREE_TYPE (fn);
1068 2736701 : gcc_assert (INDIRECT_TYPE_P (type));
1069 2736701 : type = TREE_TYPE (type);
1070 :
1071 2736701 : STRIP_NOPS (fn);
1072 2736701 : if (TREE_CODE (fn) == ADDR_EXPR)
1073 2708962 : fn = TREE_OPERAND (fn, 0);
1074 2736701 : if (TREE_CODE (fn) == FUNCTION_DECL)
1075 : {
1076 : /* We do use TREE_NOTHROW for ABI internals like __dynamic_cast,
1077 : and for C library functions known not to throw. */
1078 2708962 : if (DECL_EXTERN_C_P (fn)
1079 2708962 : && (DECL_ARTIFICIAL (fn)
1080 0 : || nothrow_libfn_p (fn)))
1081 98 : return TREE_NOTHROW (fn) ? NULL_TREE : fn;
1082 : /* We used to treat a call to a constexpr function as noexcept if
1083 : the call was a constant expression (CWG 1129). This has changed
1084 : in P0003 whereby noexcept has no special rule for constant
1085 : expressions anymore. Since the current behavior is important for
1086 : certain library functionality, we treat this as a DR, therefore
1087 : adjusting the behavior for C++11 and C++14. Previously, we had
1088 : to evaluate the noexcept-specifier's operand here, but that could
1089 : cause instantiations that would fail. */
1090 : }
1091 2736638 : if (!TYPE_NOTHROW_P (type))
1092 : return fn;
1093 : }
1094 :
1095 : return NULL_TREE;
1096 : }
1097 :
1098 : /* If a function that causes a noexcept-expression to be false isn't
1099 : defined yet, remember it and check it for TREE_NOTHROW again at EOF. */
1100 :
1101 : struct GTY(()) pending_noexcept {
1102 : tree fn;
1103 : location_t loc;
1104 : };
1105 : static GTY(()) vec<pending_noexcept, va_gc> *pending_noexcept_checks;
1106 :
1107 : /* FN is a FUNCTION_DECL that caused a noexcept-expr to be false. Warn if
1108 : it can't throw.
1109 :
1110 : TODO: Consider extending -Wnoexcept to do something like walk_subtrees in the
1111 : case of a defaulted function that obtained a noexcept(false) spec. */
1112 :
1113 : static void
1114 15 : maybe_noexcept_warning (tree fn)
1115 : {
1116 15 : if (TREE_NOTHROW (fn)
1117 15 : && (!DECL_IN_SYSTEM_HEADER (fn)
1118 3 : || global_dc->dc_warn_system_headers))
1119 : {
1120 9 : auto s = make_temp_override (global_dc->dc_warn_system_headers, true);
1121 9 : auto_diagnostic_group d;
1122 9 : if (warning (OPT_Wnoexcept, "noexcept-expression evaluates to %<false%> "
1123 : "because of a call to %qD", fn))
1124 9 : inform (DECL_SOURCE_LOCATION (fn),
1125 : "but %qD does not throw; perhaps "
1126 : "it should be declared %<noexcept%>", fn);
1127 9 : }
1128 15 : }
1129 :
1130 : /* Check any functions that weren't defined earlier when they caused a
1131 : noexcept expression to evaluate to false. */
1132 :
1133 : void
1134 88316 : perform_deferred_noexcept_checks (void)
1135 : {
1136 88316 : int i;
1137 88316 : pending_noexcept *p;
1138 88316 : location_t saved_loc = input_location;
1139 88322 : FOR_EACH_VEC_SAFE_ELT (pending_noexcept_checks, i, p)
1140 : {
1141 6 : input_location = p->loc;
1142 6 : maybe_noexcept_warning (p->fn);
1143 : }
1144 88316 : input_location = saved_loc;
1145 88316 : }
1146 :
1147 : /* Evaluate noexcept ( EXPR ). */
1148 :
1149 : tree
1150 1176826 : finish_noexcept_expr (tree expr, tsubst_flags_t complain)
1151 : {
1152 1176826 : if (expr == error_mark_node)
1153 : return error_mark_node;
1154 :
1155 1176676 : if (processing_template_decl)
1156 1007344 : return build_min (NOEXCEPT_EXPR, boolean_type_node, expr);
1157 :
1158 169332 : return (expr_noexcept_p (expr, complain)
1159 169332 : ? boolean_true_node : boolean_false_node);
1160 : }
1161 :
1162 : /* Returns whether EXPR is noexcept, possibly warning if allowed by
1163 : COMPLAIN. */
1164 :
1165 : bool
1166 2901855 : expr_noexcept_p (tree expr, tsubst_flags_t complain)
1167 : {
1168 2901855 : tree fn;
1169 :
1170 2901855 : if (expr == error_mark_node)
1171 : return false;
1172 :
1173 2901842 : fn = cp_walk_tree_without_duplicates (&expr, check_noexcept_r, 0);
1174 2901842 : if (fn)
1175 : {
1176 44058 : if ((complain & tf_warning) && warn_noexcept
1177 15 : && TREE_CODE (fn) == FUNCTION_DECL)
1178 : {
1179 15 : if (!DECL_INITIAL (fn))
1180 : {
1181 : /* Not defined yet; check again at EOF. */
1182 6 : pending_noexcept p = {fn, input_location};
1183 6 : vec_safe_push (pending_noexcept_checks, p);
1184 : }
1185 : else
1186 9 : maybe_noexcept_warning (fn);
1187 : }
1188 44058 : return false;
1189 : }
1190 : else
1191 : return true;
1192 : }
1193 :
1194 : /* Return true iff SPEC is throw() or noexcept(true). */
1195 :
1196 : bool
1197 262551796 : nothrow_spec_p (const_tree spec)
1198 : {
1199 420671595 : gcc_assert (!DEFERRED_NOEXCEPT_SPEC_P (spec));
1200 :
1201 262551796 : if (spec == empty_except_spec
1202 261674325 : || spec == noexcept_true_spec)
1203 : return true;
1204 :
1205 110020669 : gcc_assert (!spec
1206 : || TREE_VALUE (spec)
1207 : || spec == noexcept_false_spec
1208 : || TREE_PURPOSE (spec) == error_mark_node
1209 : || UNPARSED_NOEXCEPT_SPEC_P (spec)
1210 : || processing_template_decl);
1211 :
1212 : return false;
1213 : }
1214 :
1215 : /* For FUNCTION_TYPE or METHOD_TYPE, true if NODE is noexcept. This is the
1216 : case for things declared noexcept(true) and, with -fnothrow-opt, for
1217 : throw() functions. */
1218 :
1219 : bool
1220 10840804 : type_noexcept_p (const_tree type)
1221 : {
1222 10840804 : tree spec = TYPE_RAISES_EXCEPTIONS (type);
1223 21681608 : gcc_assert (!DEFERRED_NOEXCEPT_SPEC_P (spec));
1224 10840804 : if (flag_nothrow_opt)
1225 103 : return nothrow_spec_p (spec);
1226 : else
1227 10840701 : return spec == noexcept_true_spec;
1228 : }
1229 :
1230 : /* For FUNCTION_TYPE or METHOD_TYPE, true if NODE can throw any type,
1231 : i.e. no exception-specification or noexcept(false). */
1232 :
1233 : bool
1234 50398104 : type_throw_all_p (const_tree type)
1235 : {
1236 50398104 : tree spec = TYPE_RAISES_EXCEPTIONS (type);
1237 73064509 : gcc_assert (!DEFERRED_NOEXCEPT_SPEC_P (spec));
1238 22666405 : return spec == NULL_TREE || spec == noexcept_false_spec;
1239 : }
1240 :
1241 : /* Create a representation of the noexcept-specification with
1242 : constant-expression of EXPR. COMPLAIN is as for tsubst. */
1243 :
1244 : tree
1245 72581208 : build_noexcept_spec (tree expr, tsubst_flags_t complain)
1246 : {
1247 72581208 : if (check_for_bare_parameter_packs (expr))
1248 3 : return error_mark_node;
1249 72581205 : if (TREE_CODE (expr) != DEFERRED_NOEXCEPT
1250 72581205 : && !instantiation_dependent_expression_p (expr))
1251 : {
1252 67479911 : expr = build_converted_constant_bool_expr (expr, complain);
1253 67479911 : expr = instantiate_non_dependent_expr (expr, complain);
1254 67479911 : expr = cxx_constant_value (expr, complain);
1255 : }
1256 72581205 : if (TREE_CODE (expr) == INTEGER_CST)
1257 : {
1258 67479867 : if (operand_equal_p (expr, boolean_true_node, 0))
1259 67338615 : return noexcept_true_spec;
1260 : else
1261 : {
1262 141252 : gcc_checking_assert (operand_equal_p (expr, boolean_false_node, 0));
1263 141252 : return noexcept_false_spec;
1264 : }
1265 : }
1266 5101338 : else if (expr == error_mark_node)
1267 : return error_mark_node;
1268 : else
1269 : {
1270 5101294 : gcc_assert (processing_template_decl
1271 : || TREE_CODE (expr) == DEFERRED_NOEXCEPT);
1272 5101294 : if (TREE_CODE (expr) != DEFERRED_NOEXCEPT)
1273 : /* Avoid problems with a function type built with a dependent typedef
1274 : being reused in another scope (c++/84045). */
1275 2190245 : expr = strip_typedefs_expr (expr);
1276 5101294 : return build_tree_list (expr, NULL_TREE);
1277 : }
1278 : }
1279 :
1280 : /* If the current function has a cleanup that might throw, and the return value
1281 : has a non-trivial destructor, return a MODIFY_EXPR to set
1282 : current_retval_sentinel so that we know that the return value needs to be
1283 : destroyed on throw. Do the same if the current function might use the
1284 : named return value optimization, so we don't destroy it on return.
1285 : Otherwise, returns NULL_TREE. */
1286 :
1287 : tree
1288 21396917 : maybe_set_retval_sentinel ()
1289 : {
1290 21396917 : if (processing_template_decl)
1291 : return NULL_TREE;
1292 21396917 : tree retval = DECL_RESULT (current_function_decl);
1293 21396917 : if (!TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (retval)))
1294 : return NULL_TREE;
1295 765898 : if (!cp_function_chain->throwing_cleanup
1296 765575 : && (current_function_return_value == error_mark_node
1297 89419 : || current_function_return_value == NULL_TREE))
1298 : return NULL_TREE;
1299 :
1300 89742 : if (!current_retval_sentinel)
1301 : {
1302 : /* Just create the temporary now, maybe_splice_retval_cleanup
1303 : will do the rest. */
1304 89153 : current_retval_sentinel = create_temporary_var (boolean_type_node);
1305 89153 : DECL_INITIAL (current_retval_sentinel) = boolean_false_node;
1306 89153 : pushdecl_outermost_localscope (current_retval_sentinel);
1307 : }
1308 :
1309 89742 : return build2 (MODIFY_EXPR, boolean_type_node,
1310 89742 : current_retval_sentinel, boolean_true_node);
1311 : }
1312 :
1313 : /* COMPOUND_STMT is the STATEMENT_LIST for some block. If COMPOUND_STMT is the
1314 : current function body or a try block, and current_retval_sentinel was set in
1315 : this function, wrap the block in a CLEANUP_STMT to destroy the return value
1316 : on throw. */
1317 :
1318 : void
1319 184853738 : maybe_splice_retval_cleanup (tree compound_stmt, bool is_try)
1320 : {
1321 184852787 : if (!current_function_decl || !cfun
1322 369705230 : || DECL_CONSTRUCTOR_P (current_function_decl)
1323 159554204 : || DECL_DESTRUCTOR_P (current_function_decl)
1324 339001474 : || !current_retval_sentinel)
1325 : return;
1326 :
1327 : /* if we need a cleanup for the return value, add it in at the same level as
1328 : pushdecl_outermost_localscope. And also in try blocks. */
1329 106905 : cp_binding_level *b = current_binding_level;
1330 106905 : const bool function_body = b->kind == sk_function_parms;
1331 :
1332 106905 : if (function_body || is_try)
1333 : {
1334 89245 : location_t loc = DECL_SOURCE_LOCATION (current_function_decl);
1335 89245 : tree_stmt_iterator iter = tsi_start (compound_stmt);
1336 89245 : tree retval = DECL_RESULT (current_function_decl);
1337 :
1338 89245 : if (function_body)
1339 : {
1340 : /* Add a DECL_EXPR for current_retval_sentinel. */
1341 89153 : tree decl_expr = build_stmt (loc, DECL_EXPR, current_retval_sentinel);
1342 89153 : tsi_link_before (&iter, decl_expr, TSI_SAME_STMT);
1343 : }
1344 :
1345 89245 : if (!cp_function_chain->throwing_cleanup)
1346 : /* We're only using the sentinel for an NRV. */
1347 88944 : return;
1348 :
1349 : /* Skip past other decls, they can't contain a return. */
1350 391 : while (TREE_CODE (tsi_stmt (iter)) == DECL_EXPR)
1351 391 : tsi_next (&iter);
1352 301 : gcc_assert (!tsi_end_p (iter));
1353 :
1354 : /* Wrap the rest of the STATEMENT_LIST in a CLEANUP_STMT. */
1355 301 : tree stmts = NULL_TREE;
1356 943 : while (!tsi_end_p (iter))
1357 : {
1358 642 : append_to_statement_list_force (tsi_stmt (iter), &stmts);
1359 642 : tsi_delink (&iter);
1360 : }
1361 301 : tree dtor = build_cleanup (retval);
1362 301 : tree cond = build3 (COND_EXPR, void_type_node, current_retval_sentinel,
1363 : dtor, void_node);
1364 301 : tree cleanup = build_stmt (loc, CLEANUP_STMT,
1365 : stmts, cond, retval);
1366 301 : CLEANUP_EH_ONLY (cleanup) = true;
1367 301 : append_to_statement_list_force (cleanup, &compound_stmt);
1368 : }
1369 : }
1370 :
1371 : #include "gt-cp-except.h"
|