Branch data Line data Source code
1 : : /* Handle exceptional things in C++.
2 : : Copyright (C) 1989-2024 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 : : /* Sets up all the global eh stuff that needs to be initialized at the
46 : : start of compilation. */
47 : :
48 : : void
49 : 99528 : init_exception_processing (void)
50 : : {
51 : 99528 : tree tmp;
52 : :
53 : : /* void std::terminate (); */
54 : 99528 : push_nested_namespace (std_node);
55 : 99528 : tmp = build_function_type_list (void_type_node, NULL_TREE);
56 : 99528 : terminate_fn = build_cp_library_fn_ptr ("terminate", tmp,
57 : : ECF_NOTHROW | ECF_NORETURN
58 : : | ECF_COLD);
59 : 99528 : gcc_checking_assert (TREE_THIS_VOLATILE (terminate_fn)
60 : : && TREE_NOTHROW (terminate_fn));
61 : 99528 : pop_nested_namespace (std_node);
62 : :
63 : : /* void __cxa_call_unexpected(void *); */
64 : 99528 : tmp = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
65 : 99528 : call_unexpected_fn
66 : 99528 : = push_throw_library_fn (get_identifier ("__cxa_call_unexpected"), tmp);
67 : 99528 : call_terminate_fn
68 : 99528 : = push_library_fn (get_identifier ("__cxa_call_terminate"), tmp, NULL_TREE,
69 : : ECF_NORETURN | ECF_COLD | ECF_NOTHROW);
70 : 99528 : }
71 : :
72 : : /* Returns an expression to be executed if an unhandled exception is
73 : : propagated out of a cleanup region. */
74 : :
75 : : tree
76 : 571296 : 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 : 571296 : return call_terminate_fn;
83 : : }
84 : :
85 : : static tree
86 : 114989 : prepare_eh_type (tree type)
87 : : {
88 : 114989 : if (type == NULL_TREE)
89 : : return type;
90 : 114989 : if (type == error_mark_node)
91 : : return error_mark_node;
92 : :
93 : : /* peel back references, so they match. */
94 : 114915 : type = non_reference (type);
95 : :
96 : : /* Peel off cv qualifiers. */
97 : 114915 : type = TYPE_MAIN_VARIANT (type);
98 : :
99 : : /* Functions and arrays decay to pointers. */
100 : 114915 : type = type_decays_to (type);
101 : :
102 : 114915 : return type;
103 : : }
104 : :
105 : : /* Return the type info for TYPE as used by EH machinery. */
106 : : tree
107 : 117802 : eh_type_info (tree type)
108 : : {
109 : 117802 : if (type == NULL_TREE || type == error_mark_node)
110 : : return type;
111 : :
112 : 117728 : 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 : 109858 : build_eh_type_type (tree type)
120 : : {
121 : 109858 : tree exp = eh_type_info (type);
122 : :
123 : 109858 : if (!exp)
124 : : return NULL;
125 : :
126 : 109858 : mark_used (exp);
127 : :
128 : 109858 : return convert (ptr_type_node, build_address (exp));
129 : : }
130 : :
131 : : tree
132 : 138911 : build_exc_ptr (void)
133 : : {
134 : 138911 : return build_call_n (builtin_decl_explicit (BUILT_IN_EH_POINTER),
135 : 138911 : 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 : 72504 : declare_library_fn_1 (const char *name, int ecf,
146 : : tree rtype, int nargs, tree args[])
147 : : {
148 : 72504 : tree ident = get_identifier (name);
149 : 72504 : tree except = ecf & ECF_NOTHROW ? empty_except_spec : NULL_TREE;
150 : :
151 : : /* Make a new decl. */
152 : 72504 : tree arg_list = void_list_node;
153 : 150496 : for (unsigned ix = nargs; ix--;)
154 : 77992 : arg_list = tree_cons (NULL_TREE, args[ix], arg_list);
155 : 72504 : tree fntype = build_function_type (rtype, arg_list);
156 : 72504 : tree res = push_library_fn (ident, fntype, except, ecf);
157 : :
158 : 72504 : 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 : 54942 : declare_library_fn (const char *name, tree rtype, tree ptype,
173 : : int ecf, int tm_ecf)
174 : : {
175 : 69759 : tree res = declare_library_fn_1 (name, ecf, rtype, ptype ? 1 : 0, &ptype);
176 : 54942 : if (res == error_mark_node)
177 : : return res;
178 : :
179 : 54886 : 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 : 290 : do_get_exception_ptr (void)
198 : : {
199 : 290 : if (!get_exception_ptr_fn)
200 : : /* Declare void* __cxa_get_exception_ptr (void *) throw(). */
201 : 148 : get_exception_ptr_fn
202 : 148 : = 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 : 290 : return cp_build_function_call_nary (get_exception_ptr_fn,
208 : : tf_warning_or_error,
209 : 290 : 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 : 133297 : do_begin_catch (void)
217 : : {
218 : 133297 : if (!begin_catch_fn)
219 : : /* Declare void* __cxa_begin_catch (void *) throw(). */
220 : 14817 : begin_catch_fn
221 : 14817 : = declare_library_fn ("__cxa_begin_catch",
222 : : ptr_type_node, ptr_type_node, ECF_NOTHROW,
223 : : ECF_TM_PURE);
224 : :
225 : 133297 : return cp_build_function_call_nary (begin_catch_fn, tf_warning_or_error,
226 : 133297 : 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 : 133285 : dtor_nothrow (tree type)
234 : : {
235 : 133285 : if (type == NULL_TREE || type == error_mark_node)
236 : : return 0;
237 : :
238 : 7630 : if (TYPE_HAS_TRIVIAL_DESTRUCTOR (type))
239 : : return 1;
240 : :
241 : 3998 : if (CLASSTYPE_LAZY_DESTRUCTOR (type))
242 : 133 : lazily_declare_fn (sfk_destructor, type);
243 : :
244 : 3998 : 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 : 133297 : do_end_catch (tree type)
252 : : {
253 : 133297 : if (!end_catch_fn)
254 : : /* Declare void __cxa_end_catch ().
255 : : This can throw if the destructor for the exception throws. */
256 : 14817 : end_catch_fn
257 : 14817 : = declare_library_fn ("__cxa_end_catch", void_type_node,
258 : : NULL_TREE, 0, ECF_TM_PURE);
259 : :
260 : 133297 : tree cleanup = cp_build_function_call_vec (end_catch_fn,
261 : : NULL, tf_warning_or_error);
262 : 133297 : if (cleanup != error_mark_node)
263 : 133285 : TREE_NOTHROW (cleanup) = dtor_nothrow (type);
264 : :
265 : 133297 : return cleanup;
266 : : }
267 : :
268 : : /* This routine creates the cleanup for the current exception. */
269 : :
270 : : static void
271 : 133297 : push_eh_cleanup (tree type)
272 : : {
273 : 133297 : finish_decl_cleanup (NULL_TREE, do_end_catch (type));
274 : 133297 : }
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 : 420 : build_must_not_throw_expr (tree body, tree cond)
282 : : {
283 : 420 : tree type = body ? TREE_TYPE (body) : void_type_node;
284 : :
285 : 420 : if (!flag_exceptions)
286 : : return body;
287 : :
288 : 417 : 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 : 342 : cond = NULL_TREE;
305 : : }
306 : :
307 : 387 : return build2 (MUST_NOT_THROW_EXPR, type, body, cond);
308 : : }
309 : :
310 : :
311 : : /* Initialize the catch parameter DECL. */
312 : :
313 : : static void
314 : 7618 : initialize_handler_parm (tree decl, tree exp)
315 : : {
316 : 7618 : tree init;
317 : 7618 : 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 : 7618 : TREE_USED (decl) = 1;
322 : 7618 : 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 : 7618 : init_type = TREE_TYPE (decl);
328 : 7618 : if (!INDIRECT_TYPE_P (init_type))
329 : 1481 : 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 : 7618 : if (TYPE_REF_P (init_type)
334 : 7618 : && TYPE_PTR_P (TREE_TYPE (init_type)))
335 : 14 : exp = cp_build_addr_expr (exp, tf_warning_or_error);
336 : :
337 : 7618 : exp = ocp_convert (init_type, exp, CONV_IMPLICIT|CONV_FORCE_TEMP, 0,
338 : : tf_warning_or_error);
339 : :
340 : 7618 : 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 : 7618 : 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 : 290 : 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 : 290 : init = fold_build_cleanup_point_expr (TREE_TYPE (init), init);
354 : 290 : init = build_must_not_throw_expr (init, NULL_TREE);
355 : : }
356 : :
357 : 7618 : decl = pushdecl (decl);
358 : :
359 : 7618 : start_decl_1 (decl, true);
360 : 7618 : cp_finish_decl (decl, init, /*init_const_expr_p=*/false, NULL_TREE,
361 : : LOOKUP_ONLYCONVERTING|DIRECT_BIND);
362 : 7618 : }
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 : 389408 : doing_eh (void)
374 : : {
375 : 389408 : if (! flag_exceptions)
376 : : {
377 : 31 : static int warned = 0;
378 : 31 : if (! warned)
379 : : {
380 : 11 : error ("exception handling disabled, use %<-fexceptions%> to enable");
381 : 11 : warned = 1;
382 : : }
383 : 31 : 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 : 133305 : expand_start_catch_block (tree decl)
392 : : {
393 : 133305 : tree exp;
394 : 133305 : tree type, init;
395 : :
396 : 133305 : if (! doing_eh ())
397 : : return NULL_TREE;
398 : :
399 : 133297 : if (decl)
400 : : {
401 : 7716 : if (!is_admissible_throw_operand_or_catch_parameter (decl, false,
402 : : tf_warning_or_error))
403 : 74 : decl = error_mark_node;
404 : :
405 : 7716 : type = prepare_eh_type (TREE_TYPE (decl));
406 : 7716 : mark_used (eh_type_info (type));
407 : : }
408 : : else
409 : : type = NULL_TREE;
410 : :
411 : : /* Call __cxa_end_catch at the end of processing the exception. */
412 : 133297 : push_eh_cleanup (type);
413 : :
414 : 133297 : init = do_begin_catch ();
415 : :
416 : : /* If there's no decl at all, then all we need to do is make sure
417 : : to tell the runtime that we've begun handling the exception. */
418 : 133297 : if (decl == NULL || decl == error_mark_node || init == error_mark_node)
419 : 125671 : finish_expr_stmt (init);
420 : :
421 : : /* If the C++ object needs constructing, we need to do that before
422 : : calling __cxa_begin_catch, so that std::uncaught_exception gets
423 : : the right value during the copy constructor. */
424 : 7626 : else if (flag_use_cxa_get_exception_ptr
425 : 7626 : && TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
426 : : {
427 : 290 : exp = do_get_exception_ptr ();
428 : 290 : if (exp != error_mark_node)
429 : 282 : initialize_handler_parm (decl, exp);
430 : 290 : finish_expr_stmt (init);
431 : : }
432 : :
433 : : /* Otherwise the type uses a bitwise copy, and we don't have to worry
434 : : about the value of std::uncaught_exception and therefore can do the
435 : : copy with the return value of __cxa_end_catch instead. */
436 : : else
437 : : {
438 : 7336 : tree init_type = type;
439 : :
440 : : /* Pointers are passed by values, everything else by reference. */
441 : 7336 : if (!TYPE_PTR_P (type))
442 : 5628 : init_type = build_pointer_type (type);
443 : 7336 : if (init_type != TREE_TYPE (init))
444 : 7277 : init = build1 (NOP_EXPR, init_type, init);
445 : 7336 : exp = create_temporary_var (init_type);
446 : 7336 : cp_finish_decl (exp, init, /*init_const_expr=*/false,
447 : : NULL_TREE, LOOKUP_ONLYCONVERTING);
448 : 7336 : DECL_REGISTER (exp) = 1;
449 : 7336 : initialize_handler_parm (decl, exp);
450 : : }
451 : :
452 : : return type;
453 : : }
454 : :
455 : : /* True if we are in a catch block within a catch block. Assumes that we are
456 : : in function scope. */
457 : :
458 : : static bool
459 : 123 : in_nested_catch (void)
460 : : {
461 : 123 : int catches = 0;
462 : :
463 : : /* Scan through the template parameter scopes. */
464 : 123 : for (cp_binding_level *b = current_binding_level;
465 : 401 : b->kind != sk_function_parms;
466 : 278 : b = b->level_chain)
467 : 282 : if (b->kind == sk_catch
468 : 282 : && ++catches == 2)
469 : : return true;
470 : : return false;
471 : : }
472 : :
473 : : /* Call this to end a catch block. Its responsible for emitting the
474 : : code to handle jumping back to the correct place, and for emitting
475 : : the label to jump to if this catch block didn't match. */
476 : :
477 : : void
478 : 133305 : expand_end_catch_block (void)
479 : : {
480 : 133305 : if (! doing_eh ())
481 : : return;
482 : :
483 : : /* The exception being handled is rethrown if control reaches the end of
484 : : a handler of the function-try-block of a constructor or destructor. */
485 : 133297 : if (in_function_try_handler
486 : 714 : && (DECL_CONSTRUCTOR_P (current_function_decl)
487 : 239 : || DECL_DESTRUCTOR_P (current_function_decl))
488 : 133420 : && !in_nested_catch ())
489 : : {
490 : 119 : tree rethrow = build_throw (input_location, NULL_TREE,
491 : : tf_warning_or_error);
492 : : /* Disable all warnings for the generated rethrow statement. */
493 : 119 : suppress_warning (rethrow);
494 : 119 : finish_expr_stmt (rethrow);
495 : : }
496 : : }
497 : :
498 : : tree
499 : 17122952 : begin_eh_spec_block (void)
500 : : {
501 : 17122952 : tree r;
502 : 17122952 : location_t spec_location = DECL_SOURCE_LOCATION (current_function_decl);
503 : :
504 : : /* A noexcept specification (or throw() with -fnothrow-opt) is a
505 : : MUST_NOT_THROW_EXPR. */
506 : 17122952 : if (TYPE_NOEXCEPT_P (TREE_TYPE (current_function_decl)))
507 : : {
508 : 17095525 : r = build_stmt (spec_location, MUST_NOT_THROW_EXPR,
509 : : NULL_TREE, NULL_TREE);
510 : 17095525 : TREE_SIDE_EFFECTS (r) = 1;
511 : : }
512 : : else
513 : 27427 : r = build_stmt (spec_location, EH_SPEC_BLOCK, NULL_TREE, NULL_TREE);
514 : 17122952 : add_stmt (r);
515 : 17122952 : TREE_OPERAND (r, 0) = push_stmt_list ();
516 : 17122952 : return r;
517 : : }
518 : :
519 : : void
520 : 17122952 : finish_eh_spec_block (tree raw_raises, tree eh_spec_block)
521 : : {
522 : 17122952 : tree raises;
523 : :
524 : 17122952 : TREE_OPERAND (eh_spec_block, 0)
525 : 17122952 : = pop_stmt_list (TREE_OPERAND (eh_spec_block, 0));
526 : :
527 : 17122952 : if (TREE_CODE (eh_spec_block) == MUST_NOT_THROW_EXPR)
528 : : return;
529 : :
530 : : /* Strip cv quals, etc, from the specification types. */
531 : 228 : for (raises = NULL_TREE;
532 : 55120 : raw_raises && TREE_VALUE (raw_raises);
533 : 228 : raw_raises = TREE_CHAIN (raw_raises))
534 : : {
535 : 228 : tree type = prepare_eh_type (TREE_VALUE (raw_raises));
536 : 228 : tree tinfo = eh_type_info (type);
537 : :
538 : 228 : mark_used (tinfo);
539 : 228 : raises = tree_cons (NULL_TREE, type, raises);
540 : : }
541 : :
542 : 27427 : EH_SPEC_RAISES (eh_spec_block) = raises;
543 : : }
544 : :
545 : : /* Return a pointer to a buffer for an exception object of type TYPE. */
546 : :
547 : : static tree
548 : 107084 : do_allocate_exception (tree type)
549 : : {
550 : 107084 : if (!allocate_exception_fn)
551 : : /* Declare void *__cxa_allocate_exception(size_t) throw(). */
552 : 12586 : allocate_exception_fn
553 : 12586 : = declare_library_fn ("__cxa_allocate_exception",
554 : : ptr_type_node, size_type_node,
555 : : ECF_NOTHROW | ECF_MALLOC | ECF_COLD, ECF_TM_PURE);
556 : :
557 : 107084 : return cp_build_function_call_nary (allocate_exception_fn,
558 : : tf_warning_or_error,
559 : 107084 : size_in_bytes (type), NULL_TREE);
560 : : }
561 : :
562 : : /* Call __cxa_free_exception from a cleanup. This is never invoked
563 : : directly, but see the comment for stabilize_throw_expr. */
564 : :
565 : : static tree
566 : 107060 : do_free_exception (tree ptr)
567 : : {
568 : 107060 : if (!free_exception_fn)
569 : : /* Declare void __cxa_free_exception (void *) throw(). */
570 : 12574 : free_exception_fn
571 : 12574 : = declare_library_fn ("__cxa_free_exception",
572 : : void_type_node, ptr_type_node,
573 : : ECF_NOTHROW | ECF_LEAF, ECF_TM_PURE);
574 : :
575 : 107060 : return cp_build_function_call_nary (free_exception_fn,
576 : 107060 : tf_warning_or_error, ptr, NULL_TREE);
577 : : }
578 : :
579 : : /* Wrap all cleanups for TARGET_EXPRs in MUST_NOT_THROW_EXPR.
580 : : Called from build_throw via walk_tree_without_duplicates. */
581 : :
582 : : static tree
583 : 2454537 : wrap_cleanups_r (tree *tp, int *walk_subtrees, void * /*data*/)
584 : : {
585 : 2454537 : tree exp = *tp;
586 : 2454537 : tree cleanup;
587 : :
588 : : /* Don't walk into types. */
589 : 2454537 : if (TYPE_P (exp))
590 : : {
591 : 9 : *walk_subtrees = 0;
592 : 9 : return NULL_TREE;
593 : : }
594 : 2454528 : if (TREE_CODE (exp) != TARGET_EXPR)
595 : : return NULL_TREE;
596 : :
597 : 141147 : cleanup = TARGET_EXPR_CLEANUP (exp);
598 : 141147 : if (cleanup)
599 : : {
600 : 126380 : cleanup = build2 (MUST_NOT_THROW_EXPR, void_type_node, cleanup,
601 : : NULL_TREE);
602 : 126380 : TARGET_EXPR_CLEANUP (exp) = cleanup;
603 : : }
604 : :
605 : : /* Keep iterating. */
606 : : return NULL_TREE;
607 : : }
608 : :
609 : : /* Build a throw expression. */
610 : :
611 : : tree
612 : 1288159 : build_throw (location_t loc, tree exp, tsubst_flags_t complain)
613 : : {
614 : 1288159 : if (exp == error_mark_node)
615 : : return exp;
616 : :
617 : 1288128 : if (processing_template_decl)
618 : : {
619 : 1165305 : if (cfun)
620 : 1165278 : current_function_returns_abnormally = 1;
621 : 1165305 : exp = build_min (THROW_EXPR, void_type_node, exp);
622 : 1165305 : SET_EXPR_LOCATION (exp, loc);
623 : 1165305 : return exp;
624 : : }
625 : :
626 : 122823 : if (exp && null_node_p (exp) && (complain & tf_warning))
627 : 4 : warning_at (loc, 0,
628 : : "throwing NULL, which has integral, not pointer type");
629 : :
630 : 122823 : if (exp && !is_admissible_throw_operand_or_catch_parameter (exp,
631 : : /*is_throw=*/true,
632 : : complain))
633 : 25 : return error_mark_node;
634 : :
635 : 122798 : if (! doing_eh ())
636 : 15 : return error_mark_node;
637 : :
638 : 122783 : if (exp)
639 : : {
640 : 107084 : tree throw_type;
641 : 107084 : tree temp_type;
642 : 107084 : tree cleanup;
643 : 107084 : tree object, ptr;
644 : 107084 : tree allocate_expr;
645 : :
646 : : /* The CLEANUP_TYPE is the internal type of a destructor. */
647 : 107084 : if (!cleanup_type)
648 : : {
649 : 12586 : tree tmp = build_function_type_list (void_type_node,
650 : : ptr_type_node, NULL_TREE);
651 : 12586 : cleanup_type = build_pointer_type (tmp);
652 : : }
653 : :
654 : 107084 : if (!throw_fn)
655 : : {
656 : 12586 : tree args[3] = {ptr_type_node, ptr_type_node, cleanup_type};
657 : :
658 : 12586 : throw_fn = declare_library_fn_1 ("__cxa_throw",
659 : : ECF_NORETURN | ECF_XTHROW | ECF_COLD,
660 : : void_type_node, 3, args);
661 : 12586 : if (flag_tm && throw_fn != error_mark_node)
662 : : {
663 : 19 : tree itm_fn = declare_library_fn_1 ("_ITM_cxa_throw",
664 : : ECF_NORETURN | ECF_XTHROW
665 : : | 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 : 107084 : temp_type = is_bitfield_expr_with_lowered_type (exp);
684 : 107084 : if (!temp_type)
685 : 107084 : 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 : 107084 : allocate_expr = do_allocate_exception (temp_type);
702 : 107084 : if (allocate_expr == error_mark_node)
703 : : return error_mark_node;
704 : 107060 : allocate_expr = get_target_expr (allocate_expr);
705 : 107060 : ptr = TARGET_EXPR_SLOT (allocate_expr);
706 : 107060 : TARGET_EXPR_CLEANUP (allocate_expr) = do_free_exception (ptr);
707 : 107060 : CLEANUP_EH_ONLY (allocate_expr) = 1;
708 : :
709 : 107060 : object = build_nop (build_pointer_type (temp_type), ptr);
710 : 107060 : object = cp_build_fold_indirect_ref (object);
711 : :
712 : : /* And initialize the exception object. */
713 : 107060 : if (CLASS_TYPE_P (temp_type))
714 : : {
715 : 103838 : int flags = LOOKUP_NORMAL | LOOKUP_ONLYCONVERTING;
716 : 103838 : location_t exp_loc = cp_expr_loc_or_loc (exp, loc);
717 : :
718 : : /* Under C++0x [12.8/16 class.copy], a thrown lvalue is sometimes
719 : : treated as an rvalue for the purposes of overload resolution
720 : : to favor move constructors over copy constructors. */
721 : 103838 : if (tree moved = treat_lvalue_as_rvalue_p (exp, /*return*/false))
722 : : /* In C++20 we treat the return value as an rvalue that
723 : : can bind to lvalue refs. In C++23, such an expression is just
724 : : an xvalue. */
725 : 60 : exp = moved;
726 : :
727 : : /* Call the copy constructor. */
728 : 103838 : releasing_vec exp_vec (make_tree_vector_single (exp));
729 : 103838 : exp = build_special_member_call (object, complete_ctor_identifier,
730 : 103838 : &exp_vec, TREE_TYPE (object), flags,
731 : : complain);
732 : 103838 : if (exp == error_mark_node)
733 : : {
734 : 11 : if (complain & tf_error)
735 : 9 : inform (exp_loc, " in thrown expression");
736 : 11 : return error_mark_node;
737 : : }
738 : 103838 : }
739 : : else
740 : : {
741 : 3222 : tree tmp = decay_conversion (exp, complain);
742 : 3222 : if (tmp == error_mark_node)
743 : : return error_mark_node;
744 : 3218 : exp = cp_build_init_expr (object, tmp);
745 : : }
746 : :
747 : : /* Mark any cleanups from the initialization as MUST_NOT_THROW, since
748 : : they are run after the exception object is initialized. */
749 : 107045 : cp_walk_tree_without_duplicates (&exp, wrap_cleanups_r, 0);
750 : :
751 : : /* Prepend the allocation. */
752 : 107045 : exp = build2 (COMPOUND_EXPR, TREE_TYPE (exp), allocate_expr, exp);
753 : :
754 : : /* Force all the cleanups to be evaluated here so that we don't have
755 : : to do them during unwinding. */
756 : 107045 : exp = build1 (CLEANUP_POINT_EXPR, void_type_node, exp);
757 : :
758 : 107045 : throw_type = build_eh_type_type (prepare_eh_type (TREE_TYPE (object)));
759 : :
760 : 107045 : cleanup = NULL_TREE;
761 : 107045 : if (type_build_dtor_call (TREE_TYPE (object)))
762 : : {
763 : 101477 : tree binfo = TYPE_BINFO (TREE_TYPE (object));
764 : 101477 : tree dtor_fn = lookup_fnfields (binfo,
765 : : complete_dtor_identifier, 0,
766 : : complain);
767 : 101477 : dtor_fn = BASELINK_FUNCTIONS (dtor_fn);
768 : 101477 : if (!mark_used (dtor_fn)
769 : 101477 : || !perform_or_defer_access_check (binfo, dtor_fn,
770 : : dtor_fn, complain))
771 : 0 : return error_mark_node;
772 : 101477 : if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (object)))
773 : : {
774 : 101477 : cxx_mark_addressable (dtor_fn);
775 : : /* Pretend it's a normal function. */
776 : 101477 : cleanup = build1 (ADDR_EXPR, cleanup_type, dtor_fn);
777 : : }
778 : : }
779 : 101477 : if (cleanup == NULL_TREE)
780 : 5568 : cleanup = build_int_cst (cleanup_type, 0);
781 : :
782 : : /* ??? Indicate that this function call throws throw_type. */
783 : 107045 : tree tmp = cp_build_function_call_nary (throw_fn, complain,
784 : : ptr, throw_type, cleanup,
785 : : NULL_TREE);
786 : :
787 : : /* Tack on the initialization stuff. */
788 : 107045 : exp = build2 (COMPOUND_EXPR, TREE_TYPE (tmp), exp, tmp);
789 : : }
790 : : else
791 : : {
792 : : /* Rethrow current exception. */
793 : 15699 : if (!rethrow_fn)
794 : : {
795 : 4891 : rethrow_fn = declare_library_fn_1 ("__cxa_rethrow",
796 : : ECF_NORETURN | ECF_XTHROW
797 : : | ECF_COLD,
798 : : void_type_node, 0, NULL);
799 : 4891 : if (flag_tm && rethrow_fn != error_mark_node)
800 : 7 : apply_tm_attr (rethrow_fn, get_identifier ("transaction_pure"));
801 : : }
802 : :
803 : : /* ??? Indicate that this function call allows exceptions of the type
804 : : of the enclosing catch block (if known). */
805 : 15699 : exp = cp_build_function_call_vec (rethrow_fn, NULL, complain);
806 : : }
807 : :
808 : 122744 : exp = build1_loc (loc, THROW_EXPR, void_type_node, exp);
809 : :
810 : 122744 : return exp;
811 : : }
812 : :
813 : : /* Make sure TYPE is complete, pointer to complete, reference to
814 : : complete, or pointer to cv void. Issue diagnostic on failure.
815 : : Return the zero on failure and nonzero on success. FROM can be
816 : : the expr or decl from whence TYPE came, if available. */
817 : :
818 : : static bool
819 : 114837 : complete_ptr_ref_or_void_ptr_p (tree type, tree from, tsubst_flags_t complain)
820 : : {
821 : : /* Check complete. */
822 : 114837 : type = complete_type_or_maybe_complain (type, from, complain);
823 : 114837 : if (!type)
824 : : return false;
825 : :
826 : : /* Or a pointer or ref to one, or cv void *. */
827 : 114765 : const bool is_ptr = TYPE_PTR_P (type);
828 : 114765 : if (is_ptr || TYPE_REF_P (type))
829 : : {
830 : 6535 : tree core = TREE_TYPE (type);
831 : :
832 : 6535 : if (is_ptr && VOID_TYPE_P (core))
833 : : /* OK */;
834 : 6464 : else if (!complete_type_or_maybe_complain (core, from, complain))
835 : : return false;
836 : : }
837 : : return true;
838 : : }
839 : :
840 : : /* If IS_THROW is true return truth-value if T is an expression admissible
841 : : in throw-expression, i.e. if it is not of incomplete type or a pointer/
842 : : reference to such a type or of an abstract class type.
843 : : If IS_THROW is false, likewise for a catch parameter, same requirements
844 : : for its type plus rvalue reference type is also not admissible. */
845 : :
846 : : static bool
847 : 114837 : is_admissible_throw_operand_or_catch_parameter (tree t, bool is_throw,
848 : : tsubst_flags_t complain)
849 : : {
850 : 114837 : tree expr = is_throw ? t : NULL_TREE;
851 : 114837 : tree type = TREE_TYPE (t);
852 : :
853 : : /* C++11 [except.handle] The exception-declaration shall not denote
854 : : an incomplete type, an abstract class type, or an rvalue reference
855 : : type. */
856 : :
857 : : /* 15.1/4 [...] The type of the throw-expression shall not be an
858 : : incomplete type, or a pointer or a reference to an incomplete
859 : : type, other than void*, const void*, volatile void*, or
860 : : const volatile void*. Except for these restriction and the
861 : : restrictions on type matching mentioned in 15.3, the operand
862 : : of throw is treated exactly as a function argument in a call
863 : : (5.2.2) or the operand of a return statement. */
864 : 114837 : if (!complete_ptr_ref_or_void_ptr_p (type, expr, complain))
865 : : return false;
866 : :
867 : 114759 : tree nonref_type = non_reference (type);
868 : 114759 : if (!verify_type_context (input_location, TCTX_EXCEPTIONS, nonref_type))
869 : : return false;
870 : :
871 : : /* 10.4/3 An abstract class shall not be used as a parameter type,
872 : : as a function return type or as type of an explicit
873 : : conversion. */
874 : 122411 : else if (abstract_virtuals_error (is_throw ? ACU_THROW : ACU_CATCH, type,
875 : : complain))
876 : : return false;
877 : 114749 : else if (!is_throw
878 : 7649 : && TYPE_REF_P (type)
879 : 119195 : && TYPE_REF_IS_RVALUE (type))
880 : : {
881 : 3 : if (complain & tf_error)
882 : 3 : error ("cannot declare %<catch%> parameter to be of rvalue "
883 : : "reference type %qT", type);
884 : 3 : return false;
885 : : }
886 : 114746 : else if (variably_modified_type_p (type, NULL_TREE))
887 : : {
888 : 8 : if (complain & tf_error)
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 : : }
898 : 8 : return false;
899 : : }
900 : :
901 : : return true;
902 : : }
903 : :
904 : : /* Returns nonzero if FN is a declaration of a standard C library
905 : : function which is known not to throw.
906 : :
907 : : [lib.res.on.exception.handling]: None of the functions from the
908 : : Standard C library shall report an error by throwing an
909 : : exception, unless it calls a program-supplied function that
910 : : throws an exception. */
911 : :
912 : : #include "cfns.h"
913 : :
914 : : int
915 : 102099488 : nothrow_libfn_p (const_tree fn)
916 : : {
917 : 102099488 : tree id;
918 : :
919 : 102099488 : if (TREE_PUBLIC (fn)
920 : 100620501 : && DECL_EXTERNAL (fn)
921 : 100620501 : && DECL_NAMESPACE_SCOPE_P (fn)
922 : 137563212 : && DECL_EXTERN_C_P (fn))
923 : : /* OK */;
924 : : else
925 : : /* Can't be a C library function. */
926 : : return 0;
927 : :
928 : : /* Being a C library function, DECL_ASSEMBLER_NAME == DECL_NAME
929 : : unless the system headers are playing rename tricks, and if
930 : : they are, we don't want to be confused by them. */
931 : 2281368 : id = DECL_NAME (fn);
932 : 2281368 : const struct libc_name_struct *s
933 : 2281368 : = libc_name::libc_name_p (IDENTIFIER_POINTER (id), IDENTIFIER_LENGTH (id));
934 : 2281368 : if (s == NULL)
935 : : return 0;
936 : 15390 : switch (s->c_ver)
937 : : {
938 : : case 89: return 1;
939 : 420 : case 99: return !flag_iso || flag_isoc99;
940 : 28 : case 11: return !flag_iso || flag_isoc11;
941 : 0 : default: gcc_unreachable ();
942 : : }
943 : : }
944 : :
945 : : /* Returns nonzero if an exception of type FROM will be caught by a
946 : : handler for type TO, as per [except.handle]. */
947 : :
948 : : static bool
949 : 4290 : can_convert_eh (tree to, tree from)
950 : : {
951 : 4290 : to = non_reference (to);
952 : 4290 : from = non_reference (from);
953 : :
954 : 4290 : if (same_type_ignoring_top_level_qualifiers_p (to, from))
955 : : return true;
956 : :
957 : 4263 : if (TYPE_PTR_P (to) && TYPE_PTR_P (from))
958 : : {
959 : 608 : to = TREE_TYPE (to);
960 : 608 : from = TREE_TYPE (from);
961 : :
962 : 608 : if (! at_least_as_qualified_p (to, from))
963 : : return false;
964 : :
965 : 580 : if (VOID_TYPE_P (to))
966 : : return true;
967 : :
968 : : /* Else fall through. */
969 : : }
970 : :
971 : 3987 : if (CLASS_TYPE_P (to) && CLASS_TYPE_P (from)
972 : 7833 : && publicly_uniquely_derived_p (to, from))
973 : : return true;
974 : :
975 : : return false;
976 : : }
977 : :
978 : : /* Check whether any of the handlers in I are shadowed by another handler
979 : : accepting TYPE. Note that the shadowing may not be complete; even if
980 : : an exception of type B would be caught by a handler for A, there could
981 : : be a derived class C for which A is an ambiguous base but B is not, so
982 : : the handler for B would catch an exception of type C. */
983 : :
984 : : static void
985 : 456257 : check_handlers_1 (tree master, tree_stmt_iterator i)
986 : : {
987 : 456257 : tree type = TREE_TYPE (master);
988 : :
989 : 915753 : for (; !tsi_end_p (i); tsi_next (&i))
990 : : {
991 : 459831 : tree handler = tsi_stmt (i);
992 : 459831 : if (TREE_TYPE (handler) && can_convert_eh (type, TREE_TYPE (handler)))
993 : : {
994 : 335 : auto_diagnostic_group d;
995 : 335 : if (warning_at (EXPR_LOCATION (handler), OPT_Wexceptions,
996 : : "exception of type %qT will be caught by earlier "
997 : 335 : "handler", TREE_TYPE (handler)))
998 : 35 : inform (EXPR_LOCATION (master), "for type %qT", type);
999 : 335 : break;
1000 : 335 : }
1001 : : }
1002 : 456257 : }
1003 : :
1004 : : /* Given a STATEMENT_LIST of HANDLERs, make sure that they're OK. */
1005 : :
1006 : : void
1007 : 1327958 : check_handlers (tree handlers)
1008 : : {
1009 : 1327958 : tree_stmt_iterator i;
1010 : :
1011 : : /* If we don't have a STATEMENT_LIST, then we've just got one
1012 : : handler, and thus nothing to warn about. */
1013 : 1327958 : if (TREE_CODE (handlers) != STATEMENT_LIST)
1014 : 872675 : return;
1015 : :
1016 : 455283 : i = tsi_start (handlers);
1017 : 455283 : if (!tsi_end_p (i))
1018 : 911548 : while (1)
1019 : : {
1020 : 911548 : tree handler = tsi_stmt (i);
1021 : 911548 : tsi_next (&i);
1022 : :
1023 : : /* No more handlers; nothing to shadow. */
1024 : 911548 : if (tsi_end_p (i))
1025 : : break;
1026 : 456265 : if (TREE_TYPE (handler) == NULL_TREE)
1027 : 8 : permerror (EXPR_LOCATION (handler), "%<...%>"
1028 : : " handler must be the last handler for its try block");
1029 : : else
1030 : 456257 : check_handlers_1 (handler, i);
1031 : : }
1032 : : }
1033 : :
1034 : : /* walk_tree helper for finish_noexcept_expr. Returns non-null if the
1035 : : expression *TP causes the noexcept operator to evaluate to false.
1036 : :
1037 : : 5.3.7 [expr.noexcept]: The result of the noexcept operator is false if
1038 : : in a potentially-evaluated context the expression would contain
1039 : : * a potentially evaluated call to a function, member function,
1040 : : function pointer, or member function pointer that does not have a
1041 : : non-throwing exception-specification (15.4),
1042 : : * a potentially evaluated throw-expression (15.1),
1043 : : * a potentially evaluated dynamic_cast expression dynamic_cast<T>(v),
1044 : : where T is a reference type, that requires a run-time check (5.2.7), or
1045 : : * a potentially evaluated typeid expression (5.2.8) applied to a glvalue
1046 : : expression whose type is a polymorphic class type (10.3). */
1047 : :
1048 : : static tree
1049 : 32917264 : check_noexcept_r (tree *tp, int *walk_subtrees, void *)
1050 : : {
1051 : 32917264 : tree t = *tp;
1052 : 32917264 : enum tree_code code = TREE_CODE (t);
1053 : :
1054 : 32917264 : if (unevaluated_p (code))
1055 : 5 : *walk_subtrees = false;
1056 : 4310134 : else if ((code == CALL_EXPR && CALL_EXPR_FN (t))
1057 : 32917259 : || code == AGGR_INIT_EXPR)
1058 : : {
1059 : : /* We can only use the exception specification of the called function
1060 : : for determining the value of a noexcept expression; we can't use
1061 : : TREE_NOTHROW, as it might have a different value in another
1062 : : translation unit, creating ODR problems.
1063 : :
1064 : : We could use TREE_NOTHROW (t) for !TREE_PUBLIC fns, though... */
1065 : 4453497 : tree fn = cp_get_callee (t);
1066 : 4453497 : if (concept_check_p (fn))
1067 : : return NULL_TREE;
1068 : 4453496 : tree type = TREE_TYPE (fn);
1069 : 4453496 : gcc_assert (INDIRECT_TYPE_P (type));
1070 : 4453496 : type = TREE_TYPE (type);
1071 : :
1072 : 4453496 : STRIP_NOPS (fn);
1073 : 4453496 : if (TREE_CODE (fn) == ADDR_EXPR)
1074 : 4415942 : fn = TREE_OPERAND (fn, 0);
1075 : 4453496 : if (TREE_CODE (fn) == FUNCTION_DECL)
1076 : : {
1077 : : /* We do use TREE_NOTHROW for ABI internals like __dynamic_cast,
1078 : : and for C library functions known not to throw. */
1079 : 4415942 : if (DECL_EXTERN_C_P (fn)
1080 : 4415942 : && (DECL_ARTIFICIAL (fn)
1081 : 0 : || nothrow_libfn_p (fn)))
1082 : 98 : return TREE_NOTHROW (fn) ? NULL_TREE : fn;
1083 : : /* We used to treat a call to a constexpr function as noexcept if
1084 : : the call was a constant expression (CWG 1129). This has changed
1085 : : in P0003 whereby noexcept has no special rule for constant
1086 : : expressions anymore. Since the current behavior is important for
1087 : : certain library functionality, we treat this as a DR, therefore
1088 : : adjusting the behavior for C++11 and C++14. Previously, we had
1089 : : to evaluate the noexcept-specifier's operand here, but that could
1090 : : cause instantiations that would fail. */
1091 : : }
1092 : 4453433 : if (!TYPE_NOTHROW_P (type))
1093 : : return fn;
1094 : : }
1095 : :
1096 : : return NULL_TREE;
1097 : : }
1098 : :
1099 : : /* If a function that causes a noexcept-expression to be false isn't
1100 : : defined yet, remember it and check it for TREE_NOTHROW again at EOF. */
1101 : :
1102 : : struct GTY(()) pending_noexcept {
1103 : : tree fn;
1104 : : location_t loc;
1105 : : };
1106 : : static GTY(()) vec<pending_noexcept, va_gc> *pending_noexcept_checks;
1107 : :
1108 : : /* FN is a FUNCTION_DECL that caused a noexcept-expr to be false. Warn if
1109 : : it can't throw.
1110 : :
1111 : : TODO: Consider extending -Wnoexcept to do something like walk_subtrees in the
1112 : : case of a defaulted function that obtained a noexcept(false) spec. */
1113 : :
1114 : : static void
1115 : 15 : maybe_noexcept_warning (tree fn)
1116 : : {
1117 : 15 : if (TREE_NOTHROW (fn)
1118 : 15 : && (!DECL_IN_SYSTEM_HEADER (fn)
1119 : 3 : || global_dc->m_warn_system_headers))
1120 : : {
1121 : 9 : auto s = make_temp_override (global_dc->m_warn_system_headers, true);
1122 : 9 : auto_diagnostic_group d;
1123 : 9 : if (warning (OPT_Wnoexcept, "noexcept-expression evaluates to %<false%> "
1124 : : "because of a call to %qD", fn))
1125 : 9 : inform (DECL_SOURCE_LOCATION (fn),
1126 : : "but %qD does not throw; perhaps "
1127 : : "it should be declared %<noexcept%>", fn);
1128 : 9 : }
1129 : 15 : }
1130 : :
1131 : : /* Check any functions that weren't defined earlier when they caused a
1132 : : noexcept expression to evaluate to false. */
1133 : :
1134 : : void
1135 : 99146 : perform_deferred_noexcept_checks (void)
1136 : : {
1137 : 99146 : int i;
1138 : 99146 : pending_noexcept *p;
1139 : 99146 : location_t saved_loc = input_location;
1140 : 99152 : FOR_EACH_VEC_SAFE_ELT (pending_noexcept_checks, i, p)
1141 : : {
1142 : 6 : input_location = p->loc;
1143 : 6 : maybe_noexcept_warning (p->fn);
1144 : : }
1145 : 99146 : input_location = saved_loc;
1146 : 99146 : }
1147 : :
1148 : : /* Evaluate noexcept ( EXPR ). */
1149 : :
1150 : : tree
1151 : 1858457 : finish_noexcept_expr (tree expr, tsubst_flags_t complain)
1152 : : {
1153 : 1858457 : if (expr == error_mark_node)
1154 : : return error_mark_node;
1155 : :
1156 : 1858316 : if (processing_template_decl)
1157 : 1499570 : return build_min (NOEXCEPT_EXPR, boolean_type_node, expr);
1158 : :
1159 : 358746 : return (expr_noexcept_p (expr, complain)
1160 : 358746 : ? boolean_true_node : boolean_false_node);
1161 : : }
1162 : :
1163 : : /* Returns whether EXPR is noexcept, possibly warning if allowed by
1164 : : COMPLAIN. */
1165 : :
1166 : : bool
1167 : 4541658 : expr_noexcept_p (tree expr, tsubst_flags_t complain)
1168 : : {
1169 : 4541658 : tree fn;
1170 : :
1171 : 4541658 : if (expr == error_mark_node)
1172 : : return false;
1173 : :
1174 : 4541646 : fn = cp_walk_tree_without_duplicates (&expr, check_noexcept_r, 0);
1175 : 4541646 : if (fn)
1176 : : {
1177 : 69379 : if ((complain & tf_warning) && warn_noexcept
1178 : 15 : && TREE_CODE (fn) == FUNCTION_DECL)
1179 : : {
1180 : 15 : if (!DECL_INITIAL (fn))
1181 : : {
1182 : : /* Not defined yet; check again at EOF. */
1183 : 6 : pending_noexcept p = {fn, input_location};
1184 : 6 : vec_safe_push (pending_noexcept_checks, p);
1185 : : }
1186 : : else
1187 : 9 : maybe_noexcept_warning (fn);
1188 : : }
1189 : 69379 : return false;
1190 : : }
1191 : : else
1192 : : return true;
1193 : : }
1194 : :
1195 : : /* Return true iff SPEC is throw() or noexcept(true). */
1196 : :
1197 : : bool
1198 : 394228988 : nothrow_spec_p (const_tree spec)
1199 : : {
1200 : 634519985 : gcc_assert (!DEFERRED_NOEXCEPT_SPEC_P (spec));
1201 : :
1202 : 394228988 : if (spec == empty_except_spec
1203 : 393080655 : || spec == noexcept_true_spec)
1204 : : return true;
1205 : :
1206 : 161924127 : gcc_assert (!spec
1207 : : || TREE_VALUE (spec)
1208 : : || spec == noexcept_false_spec
1209 : : || TREE_PURPOSE (spec) == error_mark_node
1210 : : || UNPARSED_NOEXCEPT_SPEC_P (spec)
1211 : : || processing_template_decl);
1212 : :
1213 : : return false;
1214 : : }
1215 : :
1216 : : /* For FUNCTION_TYPE or METHOD_TYPE, true if NODE is noexcept. This is the
1217 : : case for things declared noexcept(true) and, with -fnothrow-opt, for
1218 : : throw() functions. */
1219 : :
1220 : : bool
1221 : 17122952 : type_noexcept_p (const_tree type)
1222 : : {
1223 : 17122952 : tree spec = TYPE_RAISES_EXCEPTIONS (type);
1224 : 34245904 : gcc_assert (!DEFERRED_NOEXCEPT_SPEC_P (spec));
1225 : 17122952 : if (flag_nothrow_opt)
1226 : 103 : return nothrow_spec_p (spec);
1227 : : else
1228 : 17122849 : return spec == noexcept_true_spec;
1229 : : }
1230 : :
1231 : : /* For FUNCTION_TYPE or METHOD_TYPE, true if NODE can throw any type,
1232 : : i.e. no exception-specification or noexcept(false). */
1233 : :
1234 : : bool
1235 : 77317635 : type_throw_all_p (const_tree type)
1236 : : {
1237 : 77317635 : tree spec = TYPE_RAISES_EXCEPTIONS (type);
1238 : 113237983 : gcc_assert (!DEFERRED_NOEXCEPT_SPEC_P (spec));
1239 : 35920348 : return spec == NULL_TREE || spec == noexcept_false_spec;
1240 : : }
1241 : :
1242 : : /* Create a representation of the noexcept-specification with
1243 : : constant-expression of EXPR. COMPLAIN is as for tsubst. */
1244 : :
1245 : : tree
1246 : 106075987 : build_noexcept_spec (tree expr, tsubst_flags_t complain)
1247 : : {
1248 : 106075987 : if (check_for_bare_parameter_packs (expr))
1249 : 3 : return error_mark_node;
1250 : 106075984 : if (TREE_CODE (expr) != DEFERRED_NOEXCEPT
1251 : 106075984 : && !instantiation_dependent_expression_p (expr))
1252 : : {
1253 : 98199489 : expr = build_converted_constant_bool_expr (expr, complain);
1254 : 98199489 : expr = instantiate_non_dependent_expr (expr, complain);
1255 : 98199489 : expr = cxx_constant_value (expr, complain);
1256 : : }
1257 : 106075984 : if (TREE_CODE (expr) == INTEGER_CST)
1258 : : {
1259 : 98199456 : if (operand_equal_p (expr, boolean_true_node, 0))
1260 : 97993554 : return noexcept_true_spec;
1261 : : else
1262 : : {
1263 : 205902 : gcc_checking_assert (operand_equal_p (expr, boolean_false_node, 0));
1264 : 205902 : return noexcept_false_spec;
1265 : : }
1266 : : }
1267 : 7876528 : else if (expr == error_mark_node)
1268 : : return error_mark_node;
1269 : : else
1270 : : {
1271 : 7876495 : gcc_assert (processing_template_decl
1272 : : || TREE_CODE (expr) == DEFERRED_NOEXCEPT);
1273 : 7876495 : if (TREE_CODE (expr) != DEFERRED_NOEXCEPT)
1274 : : /* Avoid problems with a function type built with a dependent typedef
1275 : : being reused in another scope (c++/84045). */
1276 : 3252338 : expr = strip_typedefs_expr (expr);
1277 : 7876495 : return build_tree_list (expr, NULL_TREE);
1278 : : }
1279 : : }
1280 : :
1281 : : /* If the current function has a cleanup that might throw, and the return value
1282 : : has a non-trivial destructor, return a MODIFY_EXPR to set
1283 : : current_retval_sentinel so that we know that the return value needs to be
1284 : : destroyed on throw. Do the same if the current function might use the
1285 : : named return value optimization, so we don't destroy it on return.
1286 : : Otherwise, returns NULL_TREE.
1287 : :
1288 : : The sentinel is set to indicate that we're in the process of returning, and
1289 : : therefore should destroy a normal return value on throw, and shouldn't
1290 : : destroy a named return value variable on normal scope exit. It is set on
1291 : : return, and cleared either by maybe_splice_retval_cleanup, or when an
1292 : : exception reaches the NRV scope (finalize_nrv_r). Note that once return
1293 : : passes the NRV scope, it's effectively a normal return value, so cleanup
1294 : : past that point is handled by maybe_splice_retval_cleanup. */
1295 : :
1296 : : tree
1297 : 32675117 : maybe_set_retval_sentinel ()
1298 : : {
1299 : 32675117 : if (processing_template_decl)
1300 : : return NULL_TREE;
1301 : 32675117 : tree retval = DECL_RESULT (current_function_decl);
1302 : 32675117 : if (!TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (retval)))
1303 : : return NULL_TREE;
1304 : 1080534 : if (!cp_function_chain->throwing_cleanup
1305 : 1079923 : && (current_function_return_value == error_mark_node
1306 : 128394 : || current_function_return_value == NULL_TREE))
1307 : : return NULL_TREE;
1308 : :
1309 : 129005 : if (!current_retval_sentinel)
1310 : : {
1311 : : /* Just create the temporary now, maybe_splice_retval_cleanup
1312 : : will do the rest. */
1313 : 120842 : current_retval_sentinel = create_temporary_var (boolean_type_node);
1314 : 120842 : DECL_INITIAL (current_retval_sentinel) = boolean_false_node;
1315 : 120842 : pushdecl_outermost_localscope (current_retval_sentinel);
1316 : : }
1317 : :
1318 : 129005 : return build2 (MODIFY_EXPR, boolean_type_node,
1319 : 129005 : current_retval_sentinel, boolean_true_node);
1320 : : }
1321 : :
1322 : : /* COMPOUND_STMT is the STATEMENT_LIST for some block. If COMPOUND_STMT is the
1323 : : current function body or a try block, and current_retval_sentinel was set in
1324 : : this function, wrap the block in a CLEANUP_STMT to destroy the return value
1325 : : on throw. */
1326 : :
1327 : : void
1328 : 282851601 : maybe_splice_retval_cleanup (tree compound_stmt, bool is_try)
1329 : : {
1330 : 282850634 : if (!current_function_decl || !cfun
1331 : 565700924 : || DECL_CONSTRUCTOR_P (current_function_decl)
1332 : 246120225 : || DECL_DESTRUCTOR_P (current_function_decl)
1333 : 520886388 : || !current_retval_sentinel)
1334 : : return;
1335 : :
1336 : : /* if we need a cleanup for the return value, add it in at the same level as
1337 : : pushdecl_outermost_localscope. And also in try blocks. */
1338 : 178233 : cp_binding_level *b = current_binding_level;
1339 : 178233 : const bool function_body = b->kind == sk_function_parms;
1340 : :
1341 : 178233 : if (function_body || is_try)
1342 : : {
1343 : 120959 : location_t loc = DECL_SOURCE_LOCATION (current_function_decl);
1344 : 120959 : tree_stmt_iterator iter = tsi_start (compound_stmt);
1345 : 120959 : tree retval = DECL_RESULT (current_function_decl);
1346 : :
1347 : 120959 : if (function_body)
1348 : : {
1349 : : /* Add a DECL_EXPR for current_retval_sentinel. */
1350 : 120842 : tree decl_expr = build_stmt (loc, DECL_EXPR, current_retval_sentinel);
1351 : 120842 : tsi_link_before (&iter, decl_expr, TSI_SAME_STMT);
1352 : : }
1353 : :
1354 : 120959 : if (!cp_function_chain->throwing_cleanup)
1355 : : /* We're only using the sentinel for an NRV. */
1356 : 120354 : return;
1357 : :
1358 : : /* Skip past other decls, they can't contain a return. */
1359 : 863 : while (!tsi_end_p (iter)
1360 : 863 : && TREE_CODE (tsi_stmt (iter)) == DECL_EXPR)
1361 : 254 : tsi_next (&iter);
1362 : :
1363 : 609 : if (tsi_end_p (iter))
1364 : : /* Nothing to wrap. */
1365 : : return;
1366 : :
1367 : : /* Wrap the rest of the STATEMENT_LIST in a CLEANUP_STMT. */
1368 : 605 : tree stmts = NULL_TREE;
1369 : 1718 : while (!tsi_end_p (iter))
1370 : : {
1371 : 1113 : append_to_statement_list_force (tsi_stmt (iter), &stmts);
1372 : 1113 : tsi_delink (&iter);
1373 : : }
1374 : 605 : tree dtor = build_cleanup (retval);
1375 : 605 : if (!function_body)
1376 : : {
1377 : : /* Clear the sentinel so we don't try to destroy the retval again on
1378 : : rethrow (c++/112301). */
1379 : 90 : tree clear = build2 (MODIFY_EXPR, boolean_type_node,
1380 : 45 : current_retval_sentinel, boolean_false_node);
1381 : 45 : dtor = build2 (COMPOUND_EXPR, void_type_node, clear, dtor);
1382 : : }
1383 : 605 : tree cond = build3 (COND_EXPR, void_type_node, current_retval_sentinel,
1384 : : dtor, void_node);
1385 : 605 : tree cleanup = build_stmt (loc, CLEANUP_STMT,
1386 : : stmts, cond, retval);
1387 : 605 : CLEANUP_EH_ONLY (cleanup) = true;
1388 : 605 : append_to_statement_list_force (cleanup, &compound_stmt);
1389 : : }
1390 : : }
1391 : :
1392 : : #include "gt-cp-except.h"
|