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