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