Branch data Line data Source code
1 : : /* m2except.cc implements the construction of exception trees.
2 : :
3 : : Copyright (C) 2012-2024 Free Software Foundation, Inc.
4 : : Contributed by Gaius Mulley <gaius@glam.ac.uk>.
5 : :
6 : : This file is part of GNU Modula-2.
7 : :
8 : : GNU Modula-2 is free software; you can redistribute it and/or modify
9 : : it under the terms of the GNU General Public License as published by
10 : : the Free Software Foundation; either version 3, or (at your option)
11 : : any later version.
12 : :
13 : : GNU Modula-2 is distributed in the hope that it will be useful, but
14 : : WITHOUT ANY WARRANTY; without even the implied warranty of
15 : : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 : : General Public License for more details.
17 : :
18 : : You should have received a copy of the GNU General Public License
19 : : along with GNU Modula-2; see the file COPYING3. If not see
20 : : <http://www.gnu.org/licenses/>. */
21 : :
22 : : #include "gcc-consolidation.h"
23 : :
24 : : #include "../m2-tree.h"
25 : :
26 : : #define GM2
27 : : #define GM2_BUG_REPORT \
28 : : "Please report this crash to the GNU Modula-2 mailing list " \
29 : : "<gm2@nongnu.org>\n"
30 : :
31 : : /* External functions. */
32 : :
33 : : #define m2except_c
34 : : #include "m2assert.h"
35 : : #include "m2block.h"
36 : : #include "m2decl.h"
37 : : #include "m2expr.h"
38 : : #include "m2statement.h"
39 : : #include "m2tree.h"
40 : : #include "m2treelib.h"
41 : : #include "m2type.h"
42 : :
43 : : /* Local prototypes. */
44 : :
45 : : #include "m2except.h"
46 : :
47 : : static tree build_exc_ptr (location_t location);
48 : : static tree do_begin_catch (location_t location);
49 : : static tree do_end_catch (location_t location);
50 : : static tree begin_handler (location_t location);
51 : : static void finish_handler (location_t location, tree handler);
52 : : static tree finish_handler_parms (location_t location, tree handler);
53 : : static void finish_handler_sequence (tree try_block);
54 : : static tree begin_try_block (location_t location);
55 : : static tree finish_expr_stmt (location_t location, tree expr);
56 : : static tree maybe_cleanup_point_expr_void (tree expr);
57 : : static tree build_target_expr_with_type (location_t location, tree init,
58 : : tree type);
59 : : static tree get_target_expr (location_t location, tree init);
60 : : static tree build_eh_type_type (location_t location, tree type);
61 : : static tree get_tinfo_decl_m2 (location_t location);
62 : : static tree eh_type_info (location_t location, tree type);
63 : : static tree build_address (tree t);
64 : :
65 : : void _M2_gm2except_init (void);
66 : : void _M2_gm2except_finally (void);
67 : :
68 : : /* Exception handling library functions. */
69 : :
70 : : static GTY (()) tree fn_begin_catch_tree = NULL_TREE;
71 : : static GTY (()) tree fn_end_catch_tree = NULL_TREE;
72 : : static GTY (()) tree fn_throw_tree = NULL_TREE;
73 : : static GTY (()) tree fn_rethrow_tree = NULL_TREE;
74 : : static GTY (()) tree cleanup_type = NULL_TREE;
75 : : static GTY (()) tree fn_allocate_exception_tree = NULL_TREE;
76 : : static GTY (()) tree fn_free_exception_tree = NULL_TREE;
77 : : static GTY (()) tree gm2_eh_int_type = NULL_TREE;
78 : :
79 : : /* Modula-2 linker fodder. */
80 : :
81 : : void
82 : 0 : _M2_gm2except_init (void)
83 : : {
84 : 0 : }
85 : : void
86 : 0 : _M2_gm2except_finally (void)
87 : : {
88 : 0 : }
89 : :
90 : : /* InitExceptions - initialize this module, it declares the external
91 : : functions and assigns them to the appropriate global tree
92 : : variables. */
93 : :
94 : : void
95 : 16934 : m2except_InitExceptions (location_t location)
96 : : {
97 : 16934 : tree t;
98 : :
99 : 16934 : m2assert_AssertLocation (location);
100 : 16934 : m2block_pushGlobalScope ();
101 : 16934 : flag_exceptions = 1;
102 : 16934 : init_eh ();
103 : :
104 : 16934 : m2decl_BuildStartFunctionDeclaration (FALSE);
105 : 16934 : fn_rethrow_tree = m2decl_BuildEndFunctionDeclaration (
106 : : location, location, "__cxa_rethrow", void_type_node, TRUE, FALSE,
107 : : TRUE, FALSE);
108 : 16934 : TREE_NOTHROW (fn_rethrow_tree) = 0;
109 : :
110 : 16934 : m2decl_BuildStartFunctionDeclaration (FALSE);
111 : 16934 : m2decl_BuildParameterDeclaration (location, NULL, ptr_type_node, FALSE);
112 : 16934 : fn_begin_catch_tree = m2decl_BuildEndFunctionDeclaration (
113 : : location, location, "__cxa_begin_catch", ptr_type_node, TRUE, FALSE,
114 : : TRUE, FALSE);
115 : 16934 : m2decl_BuildStartFunctionDeclaration (FALSE);
116 : 16934 : fn_end_catch_tree = m2decl_BuildEndFunctionDeclaration (
117 : : location, location, "__cxa_end_catch", void_type_node, TRUE, FALSE,
118 : : TRUE, FALSE);
119 : : /* This can throw if the destructor for the exception throws. */
120 : 16934 : TREE_NOTHROW (fn_end_catch_tree) = 0;
121 : :
122 : : /* The CLEANUP_TYPE is the internal type of a destructor. */
123 : 16934 : t = void_list_node;
124 : 16934 : t = tree_cons (NULL_TREE, ptr_type_node, t);
125 : 16934 : t = build_function_type (void_type_node, t);
126 : 16934 : cleanup_type = build_pointer_type (t);
127 : :
128 : : /* Declare void __cxa_throw (void*, void*, void (*)(void*)). */
129 : 16934 : m2decl_BuildStartFunctionDeclaration (FALSE);
130 : 16934 : m2decl_BuildParameterDeclaration (location, NULL, cleanup_type, FALSE);
131 : 16934 : m2decl_BuildParameterDeclaration (location, NULL, ptr_type_node, FALSE);
132 : 16934 : m2decl_BuildParameterDeclaration (location, NULL, ptr_type_node, FALSE);
133 : 16934 : fn_throw_tree = m2decl_BuildEndFunctionDeclaration (
134 : : location, location, "__cxa_throw", void_type_node, TRUE, FALSE, TRUE,
135 : : TRUE);
136 : :
137 : : /* Declare void __cxa_rethrow (void). */
138 : 16934 : m2decl_BuildStartFunctionDeclaration (FALSE);
139 : 16934 : fn_rethrow_tree = m2decl_BuildEndFunctionDeclaration (
140 : : location, location, "__cxa_rethrow", void_type_node, TRUE, FALSE, TRUE,
141 : : TRUE);
142 : :
143 : : /* Declare void *__cxa_allocate_exception (size_t). */
144 : 16934 : m2decl_BuildStartFunctionDeclaration (FALSE);
145 : 16934 : m2decl_BuildParameterDeclaration (location, NULL, size_type_node, FALSE);
146 : 16934 : fn_allocate_exception_tree = m2decl_BuildEndFunctionDeclaration (
147 : : location, location, "__cxa_allocate_exception", ptr_type_node, TRUE,
148 : : FALSE, TRUE, FALSE);
149 : :
150 : : /* Declare void *__cxa_free_exception (void *). */
151 : 16934 : m2decl_BuildStartFunctionDeclaration (FALSE);
152 : 16934 : m2decl_BuildParameterDeclaration (location, NULL, ptr_type_node, FALSE);
153 : 16934 : fn_free_exception_tree = m2decl_BuildEndFunctionDeclaration (
154 : : location, location, "__cxa_free_exception", ptr_type_node, TRUE, FALSE,
155 : : TRUE, FALSE);
156 : :
157 : : /* Define integer type exception type which will match C++ int type
158 : : in the C++ runtime library. */
159 : 16934 : gm2_eh_int_type = build_eh_type_type (location, integer_type_node);
160 : 16934 : m2block_popGlobalScope ();
161 : :
162 : 16934 : MARK_TS_TYPED (TRY_BLOCK);
163 : 16934 : MARK_TS_TYPED (THROW_EXPR);
164 : 16934 : MARK_TS_TYPED (HANDLER);
165 : 16934 : MARK_TS_TYPED (EXPR_STMT);
166 : 16934 : }
167 : :
168 : : /* do_call0 - return a tree containing: call builtin_function (). */
169 : :
170 : : static tree
171 : 2858 : do_call0 (location_t location, tree builtin_function)
172 : : {
173 : 2858 : tree function = build_address (builtin_function);
174 : 2858 : tree fntype = TREE_TYPE (TREE_TYPE (function));
175 : 2858 : tree result_type = TREE_TYPE (fntype);
176 : :
177 : 2858 : m2assert_AssertLocation (location);
178 : 2858 : return build_call_array_loc (location, result_type, function, 0, NULL);
179 : : }
180 : :
181 : : /* do_call1 - return a tree containing: call builtin_function
182 : : (param1). */
183 : :
184 : : static tree
185 : 5608 : do_call1 (location_t location, tree builtin_function, tree param1)
186 : : {
187 : 5608 : tree *argarray = XALLOCAVEC (tree, 1);
188 : 5608 : tree function = build_address (builtin_function);
189 : 5608 : tree fntype = TREE_TYPE (TREE_TYPE (function));
190 : 5608 : tree result_type = TREE_TYPE (fntype);
191 : :
192 : 5608 : m2assert_AssertLocation (location);
193 : 5608 : argarray[0] = param1;
194 : 5608 : return build_call_array_loc (location, result_type, function, 1, argarray);
195 : : }
196 : :
197 : : /* do_call3 - return a tree containing: call builtin_function
198 : : (param1, param2, param3). */
199 : :
200 : : static tree
201 : 120 : do_call3 (location_t location, tree builtin_function, tree param1, tree param2,
202 : : tree param3)
203 : : {
204 : 120 : tree *argarray = XALLOCAVEC (tree, 3);
205 : 120 : tree function = build_address (builtin_function);
206 : 120 : tree fntype = TREE_TYPE (TREE_TYPE (function));
207 : 120 : tree result_type = TREE_TYPE (fntype);
208 : :
209 : 120 : m2assert_AssertLocation (location);
210 : 120 : argarray[0] = param1;
211 : 120 : argarray[1] = param2;
212 : 120 : argarray[2] = param3;
213 : 120 : return build_call_array_loc (location, result_type, function, 3, argarray);
214 : : }
215 : :
216 : : /* build_exc_ptr - creates the GCC internal type, pointer to
217 : : exception control block. */
218 : :
219 : : static tree
220 : 2684 : build_exc_ptr (location_t location)
221 : : {
222 : 2684 : m2assert_AssertLocation (location);
223 : 2684 : return do_call1 (location, builtin_decl_explicit (BUILT_IN_EH_POINTER),
224 : 2684 : integer_zero_node);
225 : : }
226 : :
227 : : static tree
228 : 16934 : get_tinfo_decl_m2 (location_t location)
229 : : {
230 : 16934 : tree t = build_decl (location, VAR_DECL, get_identifier ("_ZTIi"),
231 : : ptr_type_node);
232 : :
233 : 16934 : m2assert_AssertLocation (location);
234 : 16934 : TREE_STATIC (t) = 1;
235 : 16934 : DECL_EXTERNAL (t) = 1;
236 : 16934 : TREE_PUBLIC (t) = 1;
237 : 16934 : DECL_ARTIFICIAL (t) = 1;
238 : 16934 : DECL_IGNORED_P (t) = 1;
239 : 16934 : m2block_pushDecl (t);
240 : 16934 : make_decl_rtl (t);
241 : 16934 : return t;
242 : : }
243 : :
244 : : /* Return the type info for TYPE as used by EH machinery. */
245 : :
246 : : static tree
247 : 16934 : eh_type_info (location_t location, tree type)
248 : : {
249 : 16934 : m2assert_AssertLocation (location);
250 : 16934 : if (type == NULL_TREE || type == error_mark_node)
251 : : return type;
252 : :
253 : 16934 : return get_tinfo_decl_m2 (location);
254 : : }
255 : :
256 : : /* Return an ADDR_EXPR giving the address of T. This function
257 : : attempts no optimizations or simplifications; it is a low-level
258 : : primitive. */
259 : :
260 : : static tree
261 : 25520 : build_address (tree t)
262 : : {
263 : 25520 : tree addr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (t)), t);
264 : :
265 : 25520 : return addr;
266 : : }
267 : :
268 : : /* Build the address of a typeinfo decl for use in the runtime
269 : : matching field of the exception model. */
270 : :
271 : : static tree
272 : 16934 : build_eh_type_type (location_t location, tree type)
273 : : {
274 : 16934 : tree exp = eh_type_info (location, type);
275 : :
276 : 16934 : m2assert_AssertLocation (location);
277 : 16934 : if (!exp)
278 : : return NULL;
279 : :
280 : 16934 : TREE_USED (exp) = 1;
281 : :
282 : 16934 : return convert (ptr_type_node, build_address (exp));
283 : : }
284 : :
285 : : /* Build a TARGET_EXPR, initializing the DECL with the VALUE. */
286 : :
287 : : static tree
288 : 120 : build_target_expr (tree decl, tree value)
289 : : {
290 : 120 : tree t = build4 (TARGET_EXPR, TREE_TYPE (decl), decl, value, NULL_TREE,
291 : : NULL_TREE);
292 : :
293 : : /* We always set TREE_SIDE_EFFECTS so that expand_expr does not
294 : : ignore the TARGET_EXPR. If there really turn out to be no
295 : : side-effects, then the optimizer should be able to get rid of
296 : : whatever code is generated anyhow. */
297 : 120 : TREE_SIDE_EFFECTS (t) = 1;
298 : :
299 : 120 : return t;
300 : : }
301 : :
302 : : /* Return an undeclared local temporary of type TYPE for use in
303 : : building a TARGET_EXPR. */
304 : :
305 : : static tree
306 : 120 : build_local_temp (location_t location, tree type)
307 : : {
308 : 120 : tree slot = build_decl (location, VAR_DECL, NULL_TREE, type);
309 : :
310 : 120 : m2assert_AssertLocation (location);
311 : 120 : DECL_ARTIFICIAL (slot) = 1;
312 : 120 : DECL_IGNORED_P (slot) = 1;
313 : 120 : DECL_CONTEXT (slot) = current_function_decl;
314 : 120 : layout_decl (slot, 0);
315 : 120 : return slot;
316 : : }
317 : :
318 : : /* Build a TARGET_EXPR using INIT to initialize a new temporary of
319 : : the indicated TYPE. */
320 : :
321 : : static tree
322 : 120 : build_target_expr_with_type (location_t location, tree init, tree type)
323 : : {
324 : 120 : tree slot;
325 : :
326 : 120 : m2assert_AssertLocation (location);
327 : 120 : gcc_assert (!VOID_TYPE_P (type));
328 : :
329 : 120 : if (TREE_CODE (init) == TARGET_EXPR)
330 : : return init;
331 : :
332 : 120 : slot = build_local_temp (location, type);
333 : 120 : return build_target_expr (slot, init);
334 : : }
335 : :
336 : : /* Like build_target_expr_with_type, but use the type of INIT. */
337 : :
338 : : static tree
339 : 120 : get_target_expr (location_t location, tree init)
340 : : {
341 : 120 : m2assert_AssertLocation (location);
342 : 120 : return build_target_expr_with_type (location, init, TREE_TYPE (init));
343 : : }
344 : :
345 : : /* do_allocate_exception - returns a tree which calls
346 : : allocate_exception (sizeof (type)); */
347 : :
348 : : static tree
349 : 120 : do_allocate_exception (location_t location, tree type)
350 : : {
351 : 120 : return do_call1 (location, fn_allocate_exception_tree, size_in_bytes (type));
352 : : }
353 : :
354 : : /* Call __cxa_free_exception from a cleanup. This is never invoked
355 : : directly, but see the comment for stabilize_throw_expr. */
356 : :
357 : : static tree
358 : 120 : do_free_exception (location_t location, tree ptr)
359 : : {
360 : 0 : return do_call1 (location, fn_free_exception_tree, ptr);
361 : : }
362 : :
363 : : /* do_throw - returns tree for a call to throw (ptr, gm2_eh_int_type,
364 : : 0). */
365 : :
366 : : static tree
367 : 120 : do_throw (location_t location, tree ptr)
368 : : {
369 : 120 : return do_call3 (location, fn_throw_tree, ptr,
370 : : unshare_expr (gm2_eh_int_type),
371 : 120 : build_int_cst (cleanup_type, 0));
372 : : }
373 : :
374 : : /* do_rethrow - returns a tree containing the call to rethrow (). */
375 : :
376 : : static tree
377 : 174 : do_rethrow (location_t location)
378 : : {
379 : 0 : return do_call0 (location, fn_rethrow_tree);
380 : : }
381 : :
382 : : /* gm2_build_throw - build a GCC throw expression tree which looks
383 : : identical to the C++ front end. */
384 : :
385 : : static tree
386 : 294 : gm2_build_throw (location_t location, tree exp)
387 : : {
388 : 294 : m2assert_AssertLocation (location);
389 : :
390 : 294 : if (exp == NULL_TREE)
391 : : /* Rethrow the current exception. */
392 : 174 : exp = build1 (THROW_EXPR, void_type_node, do_rethrow (location));
393 : : else
394 : : {
395 : 120 : tree object, ptr;
396 : 120 : tree allocate_expr;
397 : 120 : tree tmp;
398 : :
399 : 120 : exp = m2expr_FoldAndStrip (
400 : : convert (m2type_GetIntegerType (), m2expr_FoldAndStrip (exp)));
401 : 120 : exp = m2expr_GetIntegerOne (location);
402 : :
403 : : /* Allocate the space for the exception. */
404 : 120 : allocate_expr = do_allocate_exception (location, TREE_TYPE (exp));
405 : 120 : allocate_expr = get_target_expr (location, allocate_expr);
406 : 120 : ptr = TARGET_EXPR_SLOT (allocate_expr);
407 : 120 : TARGET_EXPR_CLEANUP (allocate_expr) = do_free_exception (location, ptr);
408 : 120 : CLEANUP_EH_ONLY (allocate_expr) = 1;
409 : :
410 : 120 : object = build1 (NOP_EXPR, build_pointer_type (TREE_TYPE (exp)), ptr);
411 : 120 : object = m2expr_BuildIndirect (location, object, TREE_TYPE (exp));
412 : :
413 : : /* And initialize the exception object. */
414 : 120 : exp = build2 (INIT_EXPR, TREE_TYPE (object), object, exp);
415 : :
416 : : /* Prepend the allocation. */
417 : 120 : exp = build2 (COMPOUND_EXPR, TREE_TYPE (exp), allocate_expr, exp);
418 : :
419 : : /* Force all the cleanups to be evaluated here so that we don't have
420 : : to do them during unwinding. */
421 : 120 : exp = build1 (CLEANUP_POINT_EXPR, void_type_node, exp);
422 : :
423 : 120 : tmp = do_throw (location, ptr);
424 : :
425 : : /* Tack on the initialization stuff. */
426 : 120 : exp = build2 (COMPOUND_EXPR, TREE_TYPE (tmp), exp, tmp);
427 : 120 : exp = build1 (THROW_EXPR, void_type_node, exp);
428 : : }
429 : :
430 : 294 : SET_EXPR_LOCATION (exp, location);
431 : 294 : return exp;
432 : : }
433 : :
434 : : /* gccgm2_BuildThrow - builds a throw expression and return the tree. */
435 : :
436 : : tree
437 : 294 : m2except_BuildThrow (location_t location, tree expr)
438 : : {
439 : 294 : return gm2_build_throw (location, expr);
440 : : }
441 : :
442 : : /* Build up a call to __cxa_begin_catch, to tell the runtime that the
443 : : exception has been handled. */
444 : :
445 : : static tree
446 : 2684 : do_begin_catch (location_t location)
447 : : {
448 : 2684 : return do_call1 (location, fn_begin_catch_tree, build_exc_ptr (location));
449 : : }
450 : :
451 : : /* Build up a call to __cxa_end_catch, to destroy the exception
452 : : object for the current catch block if no others are currently using
453 : : it. */
454 : :
455 : : static tree
456 : 2684 : do_end_catch (location_t location)
457 : : {
458 : 2684 : tree cleanup = do_call0 (location, fn_end_catch_tree);
459 : :
460 : 2684 : m2assert_AssertLocation (location);
461 : 2684 : TREE_NOTHROW (cleanup) = 1;
462 : 2684 : return cleanup;
463 : : }
464 : :
465 : : /* BuildTryBegin - returns a tree representing the 'try' block. */
466 : :
467 : : tree
468 : 2684 : m2except_BuildTryBegin (location_t location)
469 : : {
470 : 2684 : m2assert_AssertLocation (location);
471 : 2684 : return begin_try_block (location);
472 : : }
473 : :
474 : : /* BuildTryEnd - builds the end of the Try block and prepares for the
475 : : catch handlers. */
476 : :
477 : : void
478 : 2684 : m2except_BuildTryEnd (tree try_block)
479 : : {
480 : 2684 : TRY_STMTS (try_block) = m2block_pop_statement_list ();
481 : 2684 : TRY_HANDLERS (try_block) = m2block_begin_statement_list ();
482 : :
483 : : /* Now ensure that all successive add_stmts adds to this statement
484 : : sequence. */
485 : 2684 : m2block_push_statement_list (TRY_HANDLERS (try_block));
486 : 2684 : }
487 : :
488 : : /* BuildCatchBegin - creates a handler tree for the C++ statement
489 : : 'catch (...) {'. It returns the handler tree. */
490 : :
491 : : tree
492 : 2684 : m2except_BuildCatchBegin (location_t location)
493 : : {
494 : 2684 : tree handler = begin_handler (location);
495 : :
496 : 2684 : m2assert_AssertLocation (location);
497 : 2684 : return finish_handler_parms (location, handler);
498 : : }
499 : :
500 : : /* BuildCatchEnd - completes a try catch block. It returns the,
501 : : try_block, tree. It creates the C++ statement
502 : : '}' which matches the catch above. */
503 : :
504 : : tree
505 : 2684 : m2except_BuildCatchEnd (location_t location, tree handler, tree try_block)
506 : : {
507 : 2684 : m2assert_AssertLocation (location);
508 : 2684 : finish_handler (location, handler);
509 : 2684 : finish_handler_sequence (try_block);
510 : 2684 : return try_block;
511 : : }
512 : :
513 : : /* Begin a handler. Returns a HANDLER if appropriate. */
514 : :
515 : : static tree
516 : 2684 : begin_handler (location_t location)
517 : : {
518 : 2684 : tree r;
519 : :
520 : 2684 : m2assert_AssertLocation (location);
521 : 2684 : r = build_stmt (location, HANDLER, NULL_TREE, NULL_TREE);
522 : 2684 : add_stmt (location, r);
523 : :
524 : 2684 : HANDLER_BODY (r) = m2block_begin_statement_list ();
525 : :
526 : : /* Now ensure that all successive add_stmts adds to this
527 : : statement sequence. */
528 : 2684 : m2block_push_statement_list (HANDLER_BODY (r));
529 : 2684 : return r;
530 : : }
531 : :
532 : : /* Finish a handler, which may be given by HANDLER. The BLOCKs are
533 : : the return value from the matching call to finish_handler_parms. */
534 : :
535 : : static void
536 : 2684 : finish_handler (location_t location, tree handler)
537 : : {
538 : : /* We might need to rethrow the exception if we reach the end.
539 : : use this code: finish_expr_stmt (build_throw (NULL_TREE)); */
540 : 2684 : tree body = m2block_pop_statement_list ();
541 : :
542 : 2684 : m2assert_AssertLocation (location);
543 : 2684 : HANDLER_BODY (handler) = body;
544 : 2684 : HANDLER_BODY (handler) = build2 (TRY_FINALLY_EXPR, void_type_node, body,
545 : : do_end_catch (location));
546 : 2684 : }
547 : :
548 : : /* Finish the handler-parameters for a handler, which may be given by
549 : : HANDLER. */
550 : :
551 : : static tree
552 : 2684 : finish_handler_parms (location_t location, tree handler)
553 : : {
554 : 2684 : m2assert_AssertLocation (location);
555 : : /* Equivalent to C++ catch (...). */
556 : 2684 : finish_expr_stmt (location, do_begin_catch (location));
557 : :
558 : 2684 : HANDLER_TYPE (handler) = NULL_TREE;
559 : 2684 : return handler;
560 : : }
561 : :
562 : : /* Finish a handler-sequence for a try-block, which may be given by
563 : : TRY_BLOCK. */
564 : :
565 : : static void
566 : 2684 : finish_handler_sequence (tree try_block)
567 : : {
568 : 2684 : TRY_HANDLERS (try_block) = m2block_pop_statement_list ();
569 : 2684 : }
570 : :
571 : : /* Begin a try-block. Returns a newly-created TRY_BLOCK if
572 : : appropriate. */
573 : :
574 : : static tree
575 : 2684 : begin_try_block (location_t location)
576 : : {
577 : 2684 : tree r = build_stmt (location, TRY_BLOCK, NULL_TREE, NULL_TREE);
578 : :
579 : 2684 : m2assert_AssertLocation (location);
580 : 2684 : TRY_STMTS (r) = m2block_begin_statement_list ();
581 : :
582 : : /* Now ensure that all successive add_stmts adds to this statement
583 : : sequence. */
584 : 2684 : m2block_push_statement_list (TRY_STMTS (r));
585 : 2684 : return r;
586 : : }
587 : :
588 : : /* Finish an expression-statement, whose EXPRESSION is as indicated. */
589 : :
590 : : static tree
591 : 2684 : finish_expr_stmt (location_t location, tree expr)
592 : : {
593 : 2684 : tree r = NULL_TREE;
594 : :
595 : 2684 : m2assert_AssertLocation (location);
596 : 2684 : if (expr != NULL_TREE)
597 : : {
598 : 2684 : expr = build1 (CONVERT_EXPR, void_type_node, expr);
599 : :
600 : : /* Simplification of inner statement expressions, compound exprs, etc
601 : : can result in us already having an EXPR_STMT. */
602 : 2684 : if (TREE_CODE (expr) != CLEANUP_POINT_EXPR)
603 : : {
604 : 2684 : if (TREE_CODE (expr) != EXPR_STMT)
605 : 2684 : expr = build_stmt (location, EXPR_STMT, expr);
606 : 2684 : expr = maybe_cleanup_point_expr_void (expr);
607 : : }
608 : 2684 : r = add_stmt (location, expr);
609 : : }
610 : :
611 : 2684 : return r;
612 : : }
613 : :
614 : : /* Like maybe_cleanup_point_expr except have the type of the new
615 : : expression be void so we don't need to create a temporary variable to
616 : : hold the inner expression. The reason why we do this is because the
617 : : original type might be an aggregate and we cannot create a temporary
618 : : variable for that type. */
619 : :
620 : : static tree
621 : 2684 : maybe_cleanup_point_expr_void (tree expr)
622 : : {
623 : 2684 : return fold_build_cleanup_point_expr (void_type_node, expr);
624 : : }
625 : :
626 : : #include "gt-m2-m2except.h"
|