]> gcc.gnu.org Git - gcc.git/blame - gcc/cp/except.c
Redefine exception in math.h for C++
[gcc.git] / gcc / cp / except.c
CommitLineData
8d08fdba 1/* Handle exceptional things in C++.
6467930b 2 Copyright (C) 1989, 92-95, 1996 Free Software Foundation, Inc.
8d2733ca
MS
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.
8d08fdba
MS
6
7This file is part of GNU CC.
8
9GNU CC is free software; you can redistribute it and/or modify
10it under the terms of the GNU General Public License as published by
11the Free Software Foundation; either version 2, or (at your option)
12any later version.
13
14GNU CC is distributed in the hope that it will be useful,
15but WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17GNU General Public License for more details.
18
19You should have received a copy of the GNU General Public License
20along with GNU CC; see the file COPYING. If not, write to
e9fa0c7c
RK
21the Free Software Foundation, 59 Temple Place - Suite 330,
22Boston, MA 02111-1307, USA. */
8d08fdba
MS
23
24
8d08fdba
MS
25#include "config.h"
26#include "tree.h"
27#include "rtl.h"
28#include "cp-tree.h"
29#include "flags.h"
8d2733ca
MS
30#include "obstack.h"
31#include "expr.h"
21451173 32#include "output.h"
6467930b
MS
33#include "except.h"
34#include "function.h"
8d08fdba 35
f30432d7 36rtx expand_builtin_return_addr PROTO((enum built_in_function, int, rtx));
a3b49ccd 37
8d2733ca
MS
38/* holds the fndecl for __builtin_return_address () */
39tree builtin_return_address_fndecl;
8d2733ca
MS
40
41/* A couple of backend routines from m88k.c */
42
43/* used to cache a call to __builtin_return_address () */
44static tree BuiltinReturnAddress;
f30432d7 45
8d2733ca
MS
46
47#include <stdio.h>
48
8d2733ca
MS
49static void
50easy_expand_asm (str)
51 char *str;
52{
53 expand_asm (build_string (strlen (str)+1, str));
8d08fdba
MS
54}
55
8d08fdba 56
8d2733ca 57#if 0
e92cc029 58/* This is the startup, and finish stuff per exception table. */
8d08fdba 59
8d2733ca
MS
60/* XXX - Tad: exception handling section */
61#ifndef EXCEPT_SECTION_ASM_OP
62#define EXCEPT_SECTION_ASM_OP "section\t.gcc_except_table,\"a\",@progbits"
63#endif
8d08fdba 64
8d2733ca
MS
65#ifdef EXCEPT_SECTION_ASM_OP
66typedef struct {
6467930b
MS
67 void *start_region;
68 void *end_region;
8d2733ca
MS
69 void *exception_handler;
70 } exception_table;
71#endif /* EXCEPT_SECTION_ASM_OP */
8d08fdba 72
8d2733ca 73#ifdef EXCEPT_SECTION_ASM_OP
8d08fdba 74
8d2733ca
MS
75 /* on machines which support it, the exception table lives in another section,
76 but it needs a label so we can reference it... This sets up that
77 label! */
78asm (EXCEPT_SECTION_ASM_OP);
79exception_table __EXCEPTION_TABLE__[1] = { (void*)0, (void*)0, (void*)0 };
80asm (TEXT_SECTION_ASM_OP);
8d08fdba 81
8d2733ca 82#endif /* EXCEPT_SECTION_ASM_OP */
8d08fdba 83
8d2733ca
MS
84#ifdef EXCEPT_SECTION_ASM_OP
85
86 /* we need to know where the end of the exception table is... so this
87 is how we do it! */
88
89asm (EXCEPT_SECTION_ASM_OP);
90exception_table __EXCEPTION_END__[1] = { (void*)-1, (void*)-1, (void*)-1 };
91asm (TEXT_SECTION_ASM_OP);
92
93#endif /* EXCEPT_SECTION_ASM_OP */
94
95#endif
8d08fdba 96
8d2733ca 97#include "decl.h"
8d2733ca
MS
98#include "insn-flags.h"
99#include "obstack.h"
8d2733ca
MS
100
101/* ======================================================================
102 Briefly the algorithm works like this:
103
104 When a constructor or start of a try block is encountered,
105 push_eh_entry (&eh_stack) is called. Push_eh_entry () creates a
106 new entry in the unwind protection stack and returns a label to
107 output to start the protection for that block.
108
109 When a destructor or end try block is encountered, pop_eh_entry
6467930b
MS
110 (&eh_stack) is called. Pop_eh_entry () returns the eh_entry it
111 created when push_eh_entry () was called. The eh_entry structure
8d2733ca
MS
112 contains three things at this point. The start protect label,
113 the end protect label, and the exception handler label. The end
114 protect label should be output before the call to the destructor
115 (if any). If it was a destructor, then its parse tree is stored
6467930b 116 in the finalization variable in the eh_entry structure. Otherwise
8d2733ca 117 the finalization variable is set to NULL to reflect the fact that
6467930b 118 is the the end of a try block. Next, this modified eh_entry node
8d2733ca
MS
119 is enqueued in the finalizations queue by calling
120 enqueue_eh_entry (&queue,entry).
121
122 +---------------------------------------------------------------+
123 |XXX: Will need modification to deal with partially |
124 | constructed arrays of objects |
125 | |
126 | Basically, this consists of keeping track of how many |
127 | of the objects have been constructed already (this |
128 | should be in a register though, so that shouldn't be a |
129 | problem. |
130 +---------------------------------------------------------------+
131
132 When a catch block is encountered, there is a lot of work to be
133 done.
134
135 Since we don't want to generate the catch block inline with the
136 regular flow of the function, we need to have some way of doing
f30432d7
MS
137 so. Luckily, we can use sequences to defer the catch sections.
138 When the start of a catch block is encountered, we start the
139 sequence. After the catch block is generated, we end the
140 sequence.
141
8d2733ca
MS
142 Next we must insure that when the catch block is executed, all
143 finalizations for the matching try block have been completed. If
144 any of those finalizations throw an exception, we must call
145 terminate according to the ARM (section r.15.6.1). What this
146 means is that we need to dequeue and emit finalizations for each
6467930b 147 entry in the eh_queue until we get to an entry with a NULL
8d2733ca
MS
148 finalization field. For any of the finalization entries, if it
149 is not a call to terminate (), we must protect it by giving it
150 another start label, end label, and exception handler label,
151 setting its finalization tree to be a call to terminate (), and
6467930b 152 enqueue'ing this new eh_entry to be output at an outer level.
8d2733ca
MS
153 Finally, after all that is done, we can get around to outputting
154 the catch block which basically wraps all the "catch (...) {...}"
155 statements in a big if/then/else construct that matches the
156 correct block to call.
157
158 ===================================================================== */
159
160extern rtx emit_insn PROTO((rtx));
161extern rtx gen_nop PROTO(());
8d2733ca
MS
162
163/* local globals for function calls
164 ====================================================================== */
165
166/* used to cache "terminate ()", "unexpected ()", "set_terminate ()", and
f30432d7 167 "set_unexpected ()" after default_conversion. (lib-except.c) */
6467930b 168static tree Terminate, Unexpected, SetTerminate, SetUnexpected, CatchMatch;
8d2733ca
MS
169
170/* used to cache __find_first_exception_table_match ()
171 for throw (lib-except.c) */
172static tree FirstExceptionMatch;
173
f30432d7 174/* used to cache a call to __unwind_function () (lib-except.c) */
8d2733ca
MS
175static tree Unwind;
176
f30432d7 177/* holds a ready to emit call to "terminate ()". */
8d2733ca
MS
178static tree TerminateFunctionCall;
179
72b7eeff
MS
180static tree empty_fndecl;
181
8d2733ca
MS
182/* ====================================================================== */
183
184
8d2733ca
MS
185/* ========================================================================= */
186
187
188
189/* local globals - these local globals are for storing data necessary for
190 generating the exception table and code in the correct order.
191
192 ========================================================================= */
193
a3b49ccd 194/* Holds the pc for doing "throw" */
5566b478 195static tree saved_pc;
e92cc029 196/* Holds the type of the thing being thrown. */
5566b478 197static tree saved_throw_type;
a3b49ccd 198/* Holds the value being thrown. */
5566b478 199static tree saved_throw_value;
72b7eeff 200/* Holds the cleanup for the value being thrown. */
5566b478 201static tree saved_cleanup;
a50f0918
MS
202/* Indicates if we are in a catch clause. */
203static tree saved_in_catch;
f30432d7 204
6467930b
MS
205extern int throw_used;
206extern rtx catch_clauses;
8d2733ca 207
8d2733ca
MS
208/* ========================================================================= */
209
6467930b 210/* Cheesyness to save some typing. Returns the return value rtx. */
8d2733ca 211
5566b478 212static rtx
f30432d7
MS
213do_function_call (func, params, return_type)
214 tree func, params, return_type;
215{
216 tree func_call;
217 func_call = build_function_call (func, params);
218 expand_call (func_call, NULL_RTX, 0);
219 if (return_type != NULL_TREE)
220 return hard_function_value (return_type, func_call);
221 return NULL_RTX;
222}
223
8d2733ca
MS
224/* ========================================================================= */
225
8ccc31eb
MS
226extern tree auto_function PROTO((tree, tree, enum built_in_function));
227
8d2733ca
MS
228/* sets up all the global eh stuff that needs to be initialized at the
229 start of compilation.
230
231 This includes:
6467930b 232 - Setting up all the function call trees. */
8d08fdba 233
8d08fdba 234void
8d2733ca 235init_exception_processing ()
8d08fdba 236{
8d2733ca
MS
237 extern tree define_function ();
238 tree unexpected_fndecl, terminate_fndecl;
239 tree set_unexpected_fndecl, set_terminate_fndecl;
240 tree catch_match_fndecl;
241 tree find_first_exception_match_fndecl;
242 tree unwind_fndecl;
f30432d7
MS
243 tree declspecs;
244 tree d;
a3b49ccd 245
8d2733ca 246 /* void (*)() */
8ccc31eb
MS
247 tree PFV = build_pointer_type (build_function_type
248 (void_type_node, void_list_node));
8d08fdba 249
8d2733ca
MS
250 /* arg list for the build_function_type call for set_terminate () and
251 set_unexpected () */
8ccc31eb 252 tree pfvlist = tree_cons (NULL_TREE, PFV, void_list_node);
8d08fdba 253
8ccc31eb
MS
254 /* void (*pfvtype (void (*) ()))() */
255 tree pfvtype = build_function_type (PFV, pfvlist);
8d2733ca 256
8ccc31eb
MS
257 /* void vtype () */
258 tree vtype = build_function_type (void_type_node, void_list_node);
259
260 set_terminate_fndecl = auto_function (get_identifier ("set_terminate"),
261 pfvtype, NOT_BUILT_IN);
262 set_unexpected_fndecl = auto_function (get_identifier ("set_unexpected"),
263 pfvtype, NOT_BUILT_IN);
264 unexpected_fndecl = auto_function (get_identifier ("unexpected"),
265 vtype, NOT_BUILT_IN);
266 terminate_fndecl = auto_function (get_identifier ("terminate"),
267 vtype, NOT_BUILT_IN);
268
8ccc31eb 269 push_lang_context (lang_name_c);
8d2733ca 270
8d2733ca 271 catch_match_fndecl =
72b7eeff
MS
272 builtin_function (flag_rtti
273 ? "__throw_type_match_rtti"
274 : "__throw_type_match",
275 build_function_type (ptr_type_node,
276 tree_cons (NULL_TREE, ptr_type_node,
277 tree_cons (NULL_TREE, ptr_type_node,
278 tree_cons (NULL_TREE, ptr_type_node,
279 void_list_node)))),
280 NOT_BUILT_IN, NULL_PTR);
8d2733ca 281 find_first_exception_match_fndecl =
72b7eeff
MS
282 builtin_function ("__find_first_exception_table_match",
283 build_function_type (ptr_type_node,
284 tree_cons (NULL_TREE, ptr_type_node,
285 void_list_node)),
286 NOT_BUILT_IN, NULL_PTR);
8d2733ca 287 unwind_fndecl =
72b7eeff
MS
288 builtin_function ("__unwind_function",
289 build_function_type (void_type_node,
290 tree_cons (NULL_TREE, ptr_type_node,
291 void_list_node)),
292 NOT_BUILT_IN, NULL_PTR);
72b7eeff
MS
293 empty_fndecl =
294 builtin_function ("__empty",
295 build_function_type (void_type_node, void_list_node),
296 NOT_BUILT_IN, NULL_PTR);
297 DECL_EXTERNAL (empty_fndecl) = 1;
298 TREE_PUBLIC (empty_fndecl) = 1;
8d2733ca
MS
299
300 Unexpected = default_conversion (unexpected_fndecl);
301 Terminate = default_conversion (terminate_fndecl);
302 SetTerminate = default_conversion (set_terminate_fndecl);
303 SetUnexpected = default_conversion (set_unexpected_fndecl);
304 CatchMatch = default_conversion (catch_match_fndecl);
305 FirstExceptionMatch = default_conversion (find_first_exception_match_fndecl);
306 Unwind = default_conversion (unwind_fndecl);
307 BuiltinReturnAddress = default_conversion (builtin_return_address_fndecl);
308
309 TerminateFunctionCall = build_function_call (Terminate, NULL_TREE);
310
311 pop_lang_context ();
f30432d7 312
f30432d7
MS
313 declspecs = tree_cons (NULL_TREE, get_identifier ("void"), NULL_TREE);
314 d = build_parse_node (INDIRECT_REF, get_identifier ("__eh_pc"));
c11b6f21 315 d = start_decl (d, declspecs, 0);
f30432d7 316 DECL_COMMON (d) = 1;
9e9ff709 317 cp_finish_decl (d, NULL_TREE, NULL_TREE, 1, 0);
f30432d7
MS
318 saved_pc = lookup_name (get_identifier ("__eh_pc"), 0);
319
320 declspecs = tree_cons (NULL_TREE, get_identifier ("void"), NULL_TREE);
321 d = build_parse_node (INDIRECT_REF, get_identifier ("__eh_type"));
c11b6f21 322 d = start_decl (d, declspecs, 0);
f30432d7 323 DECL_COMMON (d) = 1;
9e9ff709 324 cp_finish_decl (d, NULL_TREE, NULL_TREE, 1, 0);
f30432d7
MS
325 saved_throw_type = lookup_name (get_identifier ("__eh_type"), 0);
326
327 declspecs = tree_cons (NULL_TREE, get_identifier ("void"), NULL_TREE);
328 d = build_parse_node (INDIRECT_REF, get_identifier ("__eh_value"));
c11b6f21 329 d = start_decl (d, declspecs, 0);
f30432d7 330 DECL_COMMON (d) = 1;
9e9ff709 331 cp_finish_decl (d, NULL_TREE, NULL_TREE, 1, 0);
f30432d7 332 saved_throw_value = lookup_name (get_identifier ("__eh_value"), 0);
72b7eeff
MS
333
334 declspecs = tree_cons (NULL_TREE, get_identifier ("void"), NULL_TREE);
335 d = build_parse_node (INDIRECT_REF, get_identifier ("__eh_cleanup"));
c11b6f21
MS
336 d = make_call_declarator (d, void_list_node, NULL_TREE, NULL_TREE);
337 d = start_decl (d, declspecs, 0);
72b7eeff 338 DECL_COMMON (d) = 1;
9e9ff709 339 cp_finish_decl (d, NULL_TREE, NULL_TREE, 1, 0);
72b7eeff 340 saved_cleanup = lookup_name (get_identifier ("__eh_cleanup"), 0);
a50f0918
MS
341
342 declspecs = tree_cons (NULL_TREE, get_identifier ("bool"), NULL_TREE);
343 d = get_identifier ("__eh_in_catch");
c11b6f21 344 d = start_decl (d, declspecs, 0);
a50f0918
MS
345 DECL_COMMON (d) = 1;
346 cp_finish_decl (d, NULL_TREE, NULL_TREE, 1, 0);
347 saved_in_catch = lookup_name (get_identifier ("__eh_in_catch"), 0);
8d2733ca
MS
348}
349
f30432d7
MS
350/* Build a type value for use at runtime for a type that is matched
351 against by the exception handling system. */
6467930b 352
f30432d7
MS
353static tree
354build_eh_type_type (type)
355 tree type;
8d08fdba 356{
f30432d7
MS
357 char *typestring;
358 tree exp;
8d2733ca 359
f30432d7
MS
360 if (type == error_mark_node)
361 return error_mark_node;
8d2733ca 362
e92cc029 363 /* peel back references, so they match. */
f30432d7
MS
364 if (TREE_CODE (type) == REFERENCE_TYPE)
365 type = TREE_TYPE (type);
8d08fdba 366
e92cc029 367 /* Peel off cv qualifiers. */
f30432d7 368 type = TYPE_MAIN_VARIANT (type);
8d2733ca 369
f30432d7 370 if (flag_rtti)
8d08fdba 371 {
f30432d7 372 return build1 (ADDR_EXPR, ptr_type_node, get_typeid (type));
8d08fdba 373 }
f30432d7
MS
374
375 typestring = build_overload_name (type, 1, 1);
376 exp = combine_strings (build_string (strlen (typestring)+1, typestring));
377 return build1 (ADDR_EXPR, ptr_type_node, exp);
8d08fdba 378}
8d08fdba 379
faae18ab
MS
380/* Build a type value for use at runtime for a exp that is thrown or
381 matched against by the exception handling system. */
6467930b 382
faae18ab
MS
383static tree
384build_eh_type (exp)
385 tree exp;
386{
faae18ab
MS
387 if (flag_rtti)
388 {
389 exp = build_typeid (exp);
390 return build1 (ADDR_EXPR, ptr_type_node, exp);
391 }
f30432d7 392 return build_eh_type_type (TREE_TYPE (exp));
faae18ab
MS
393}
394
72b7eeff 395/* This routine creates the cleanup for the exception handling object. */
6467930b 396
5566b478 397static void
72b7eeff
MS
398push_eh_cleanup ()
399{
400 /* All cleanups must last longer than normal. */
401 int yes = suspend_momentary ();
402
403 /* Arrange to do a dynamically scoped cleanup upon exit from this region. */
404 tree cleanup = build_function_call (saved_cleanup, NULL_TREE);
a50f0918
MS
405 cleanup = build (COMPOUND_EXPR, void_type_node, cleanup,
406 build_modify_expr (saved_in_catch, NOP_EXPR,
407 build_modify_expr (saved_throw_type, NOP_EXPR, integer_zero_node)));
e349ee73 408 expand_decl_cleanup (NULL_TREE, cleanup);
72b7eeff
MS
409
410 resume_momentary (yes);
411}
412
413
8d2733ca
MS
414/* call this to start a catch block. Typename is the typename, and identifier
415 is the variable to place the object in or NULL if the variable doesn't
416 matter. If typename is NULL, that means its a "catch (...)" or catch
417 everything. In that case we don't need to do any type checking.
418 (ie: it ends up as the "else" clause rather than an "else if" clause) */
6467930b 419
8d08fdba 420void
a4443a08
MS
421expand_start_catch_block (declspecs, declarator)
422 tree declspecs, declarator;
8d08fdba 423{
8d2733ca 424 rtx false_label_rtx;
faae18ab 425 tree decl = NULL_TREE;
a3b49ccd 426 tree init;
8d2733ca
MS
427
428 if (! doing_eh (1))
429 return;
430
a3b49ccd 431 /* Create a binding level for the parm. */
c11b6f21 432 pushlevel (0);
a3b49ccd
MS
433 expand_start_bindings (0);
434
f675499c 435 false_label_rtx = gen_label_rtx ();
72b7eeff 436 push_label_entry (&false_label_stack, false_label_rtx, NULL_TREE);
a3b49ccd 437
faae18ab 438 if (declspecs)
8d08fdba 439 {
faae18ab 440 tree exp;
8d2733ca 441 rtx call_rtx, return_value_rtx;
faae18ab
MS
442 tree init_type;
443
c11b6f21 444 decl = grokdeclarator (declarator, declspecs, CATCHPARM, 1, NULL_TREE);
faae18ab
MS
445
446 if (decl == NULL_TREE)
447 {
448 error ("invalid catch parameter");
6467930b
MS
449
450 /* This is cheap, but we want to maintain the data structures. */
451 expand_eh_region_start ();
faae18ab
MS
452 return;
453 }
454
be99da77
MS
455 /* Make sure we mark the catch param as used, otherwise we'll get
456 a warning about an unused ((anonymous)). */
457 TREE_USED (decl) = 1;
458
e92cc029 459 /* Figure out the type that the initializer is. */
faae18ab 460 init_type = TREE_TYPE (decl);
f30432d7
MS
461 if (TREE_CODE (init_type) != REFERENCE_TYPE
462 && TREE_CODE (init_type) != POINTER_TYPE)
faae18ab
MS
463 init_type = build_reference_type (init_type);
464
f30432d7 465 exp = saved_throw_value;
faae18ab 466 exp = tree_cons (NULL_TREE,
f30432d7 467 build_eh_type_type (TREE_TYPE (decl)),
faae18ab 468 tree_cons (NULL_TREE,
f30432d7 469 saved_throw_type,
faae18ab
MS
470 tree_cons (NULL_TREE, exp, NULL_TREE)));
471 exp = build_function_call (CatchMatch, exp);
472 call_rtx = expand_call (exp, NULL_RTX, 0);
e1cd6e56 473 assemble_external (TREE_OPERAND (CatchMatch, 0));
8d2733ca 474
faae18ab 475 return_value_rtx = hard_function_value (ptr_type_node, exp);
8d2733ca
MS
476
477 /* did the throw type match function return TRUE? */
faae18ab 478 emit_cmp_insn (return_value_rtx, const0_rtx, EQ, NULL_RTX,
8d2733ca
MS
479 GET_MODE (return_value_rtx), 0, 0);
480
481 /* if it returned FALSE, jump over the catch block, else fall into it */
faae18ab
MS
482 emit_jump_insn (gen_beq (false_label_rtx));
483
72b7eeff
MS
484 push_eh_cleanup ();
485
faae18ab
MS
486 init = convert_from_reference (save_expr (make_tree (init_type, call_rtx)));
487
488 /* Do we need the below two lines? */
b3417a04 489 /* Let `cp_finish_decl' know that this initializer is ok. */
faae18ab
MS
490 DECL_INITIAL (decl) = init;
491 decl = pushdecl (decl);
b3417a04 492 cp_finish_decl (decl, init, NULL_TREE, 0, LOOKUP_ONLYCONVERTING);
8d08fdba
MS
493 }
494 else
495 {
72b7eeff
MS
496 push_eh_cleanup ();
497
e92cc029 498 /* Fall into the catch all section. */
8d08fdba 499 }
a3b49ccd 500
a50f0918 501 emit_move_insn (DECL_RTL (saved_in_catch), const1_rtx);
f30432d7 502
6467930b
MS
503 /* Because we are reordered out of line, we arrange
504 to rethrow in the outer context, should we encounter
505 an exception in the catch handler.
f30432d7 506
6467930b
MS
507 Matches the end in expand_end_catch_block (). */
508 expand_eh_region_start ();
f30432d7 509
6467930b
MS
510 emit_line_note (input_filename, lineno);
511}
f30432d7 512
f30432d7 513
f30432d7 514
8d2733ca
MS
515/* Call this to end a catch block. Its responsible for emitting the
516 code to handle jumping back to the correct place, and for emitting
517 the label to jump to if this catch block didn't match. */
6467930b 518
8d2733ca 519void expand_end_catch_block ()
8d08fdba 520{
6467930b
MS
521 rtx start_region_label_rtx;
522 rtx end_region_label_rtx;
523 tree decls, t;
a3b49ccd 524
f30432d7
MS
525 if (! doing_eh (1))
526 return;
8d2733ca 527
6467930b 528 /* Fall to outside the try statement when done executing handler and
f30432d7
MS
529 we fall off end of handler. This is jump Lresume in the
530 documentation. */
72b7eeff 531 expand_goto (top_label_entry (&caught_return_label_stack));
a3b49ccd 532
6467930b
MS
533 t = make_node (RTL_EXPR);
534 TREE_TYPE (t) = void_type_node;
535 RTL_EXPR_RTL (t) = const0_rtx;
536 TREE_SIDE_EFFECTS (t) = 1;
537 start_sequence_for_rtl_expr (t);
538 expand_internal_throw (DECL_RTL (top_label_entry (&caught_return_label_stack)));
539 RTL_EXPR_SEQUENCE (t) = get_insns ();
540 end_sequence ();
f30432d7 541
6467930b
MS
542 /* Matches the start in expand_start_catch_block (). */
543 expand_eh_region_end (t);
f30432d7 544
6467930b 545 expand_leftover_cleanups ();
f30432d7
MS
546
547 /* Cleanup the EH parameter. */
c11b6f21
MS
548 expand_end_bindings (getdecls (), kept_level_p (), 0);
549 poplevel (kept_level_p (), 1, 0);
a3b49ccd 550
6467930b 551 /* label we emit to jump to if this catch block didn't match. */
f30432d7
MS
552 /* This the closing } in the `if (eq) {' of the documentation. */
553 emit_label (pop_label_entry (&false_label_stack));
8d2733ca 554}
8d08fdba 555
6467930b
MS
556/* unwind the stack. */
557
db5ae43f 558static void
f30432d7
MS
559do_unwind (inner_throw_label)
560 rtx inner_throw_label;
db5ae43f 561{
be99da77
MS
562#if defined (SPARC_STACK_ALIGN) /* was sparc */
563 /* This doesn't work for the flat model sparc, I bet. */
db5ae43f
MS
564 tree fcall;
565 tree params;
566 rtx return_val_rtx;
f30432d7 567 rtx temp;
db5ae43f
MS
568
569 /* call to __builtin_return_address () */
f30432d7 570 params = tree_cons (NULL_TREE, integer_zero_node, NULL_TREE);
db5ae43f 571 fcall = build_function_call (BuiltinReturnAddress, params);
f30432d7 572 return_val_rtx = expand_expr (fcall, NULL_RTX, Pmode, 0);
ddd5a7c1 573 /* In the return, the new pc is pc+8, as the value coming in is
db5ae43f 574 really the address of the call insn, not the next insn. */
f30432d7
MS
575 temp = gen_reg_rtx (Pmode);
576 emit_move_insn (temp, inner_throw_label);
577 emit_move_insn (return_val_rtx, plus_constant (temp, -8));
d11ad92e 578 emit_insn (gen_rtx (USE, VOIDmode, gen_rtx (REG, SImode, 31)));
db5ae43f
MS
579 easy_expand_asm ("ret");
580 easy_expand_asm ("restore");
581 emit_barrier ();
582#endif
be99da77 583#if defined (ARM_FRAME_RTX) /* was __arm */
f30432d7
MS
584 if (flag_omit_frame_pointer)
585 sorry ("this implementation of exception handling requires a frame pointer");
db5ae43f 586
f30432d7
MS
587 emit_move_insn (stack_pointer_rtx,
588 gen_rtx (MEM, Pmode, plus_constant (hard_frame_pointer_rtx, -8)));
589 emit_move_insn (hard_frame_pointer_rtx,
590 gen_rtx (MEM, Pmode, plus_constant (hard_frame_pointer_rtx, -12)));
db5ae43f 591#endif
be99da77 592#if defined (TARGET_88000) /* was m88k */
db5ae43f
MS
593 rtx temp_frame = frame_pointer_rtx;
594
595 temp_frame = memory_address (Pmode, temp_frame);
596 temp_frame = copy_to_reg (gen_rtx (MEM, Pmode, temp_frame));
597
598 /* hopefully this will successfully pop the frame! */
599 emit_move_insn (frame_pointer_rtx, temp_frame);
600 emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
601 emit_move_insn (arg_pointer_rtx, frame_pointer_rtx);
602 emit_insn (gen_add2_insn (stack_pointer_rtx, gen_rtx (CONST_INT, VOIDmode,
603 (HOST_WIDE_INT)m88k_debugger_offset (stack_pointer_rtx, 0))));
604
605#if 0
606 emit_insn (gen_add2_insn (arg_pointer_rtx, gen_rtx (CONST_INT, VOIDmode,
607 -(HOST_WIDE_INT)m88k_debugger_offset (arg_pointer_rtx, 0))));
608
609 emit_move_insn (stack_pointer_rtx, arg_pointer_rtx);
610
611 emit_insn (gen_add2_insn (stack_pointer_rtx, gen_rtx (CONST_INT, VOIDmode,
612 (HOST_WIDE_INT)m88k_debugger_offset (arg_pointer_rtx, 0))));
613#endif
614#endif
be99da77 615#if ! defined (TARGET_88000) && ! defined (ARM_FRAME_RTX) && ! defined (SPARC_STACK_ALIGN)
f30432d7
MS
616 tree fcall;
617 tree params;
618 rtx return_val_rtx;
e1cd6e56 619
be99da77 620#if 0
e92cc029 621 /* I would like to do this here, but the move below doesn't seem to work. */
f30432d7
MS
622 /* call to __builtin_return_address () */
623 params = tree_cons (NULL_TREE, integer_zero_node, NULL_TREE);
624 fcall = build_function_call (BuiltinReturnAddress, params);
625 return_val_rtx = expand_expr (fcall, NULL_RTX, Pmode, 0);
be99da77 626
f30432d7 627 emit_move_insn (return_val_rtx, inner_throw_label);
e92cc029 628 /* So, for now, just pass throw label to stack unwinder. */
f30432d7
MS
629#endif
630 params = tree_cons (NULL_TREE, make_tree (ptr_type_node,
631 inner_throw_label), NULL_TREE);
632
633 do_function_call (Unwind, params, NULL_TREE);
634 assemble_external (TREE_OPERAND (Unwind, 0));
635 emit_barrier ();
e1cd6e56 636#endif
db5ae43f 637}
8d08fdba 638
f30432d7 639
e1cd6e56 640/* is called from expand_exception_blocks () to generate the code in a function
ddd5a7c1 641 to "throw" if anything in the function needs to perform a throw.
8d08fdba 642
ddd5a7c1 643 expands "throw" as the following pseudo code:
8d2733ca
MS
644
645 throw:
646 eh = find_first_exception_match (saved_pc);
647 if (!eh) goto gotta_rethrow_it;
648 goto eh;
649
650 gotta_rethrow_it:
651 saved_pc = __builtin_return_address (0);
652 pop_to_previous_level ();
6467930b 653 goto throw; */
8d2733ca 654
f30432d7 655void
8d2733ca
MS
656expand_builtin_throw ()
657{
658 tree fcall;
659 tree params;
660 rtx return_val_rtx;
f30432d7
MS
661 rtx gotta_rethrow_it;
662 rtx gotta_call_terminate;
f30432d7
MS
663 rtx top_of_loop;
664 rtx unwind_first;
665 tree t;
666
667 if (! doing_eh (0))
668 return;
669
670 if (! throw_used)
671 return;
8d2733ca 672
f30432d7 673 params = void_list_node;
c11b6f21
MS
674 t = make_call_declarator (get_identifier ("__throw"), params, NULL_TREE,
675 NULL_TREE);
f30432d7
MS
676 start_function (decl_tree_cons (NULL_TREE, get_identifier ("static"),
677 void_list_node),
c11b6f21 678 t, NULL_TREE, 0);
f30432d7
MS
679 store_parm_decls ();
680 pushlevel (0);
681 clear_last_expr ();
682 push_momentary ();
683 expand_start_bindings (0);
684
685 gotta_rethrow_it = gen_label_rtx ();
686 gotta_call_terminate = gen_label_rtx ();
f30432d7
MS
687 top_of_loop = gen_label_rtx ();
688 unwind_first = gen_label_rtx ();
689
a50f0918 690 /* These two can be frontend specific. If wanted, they can go in
e92cc029 691 expand_throw. */
a50f0918
MS
692 /* Do we have a valid object we are throwing? */
693 emit_cmp_insn (DECL_RTL (saved_throw_type), const0_rtx, EQ, NULL_RTX,
694 GET_MODE (DECL_RTL (saved_throw_type)), 0, 0);
695 emit_jump_insn (gen_beq (gotta_call_terminate));
696
f30432d7
MS
697 emit_jump (unwind_first);
698
699 emit_label (top_of_loop);
8d2733ca
MS
700
701 /* search for an exception handler for the saved_pc */
702 return_val_rtx = do_function_call (FirstExceptionMatch,
f30432d7 703 tree_cons (NULL_TREE, saved_pc, NULL_TREE),
8d2733ca 704 ptr_type_node);
e1cd6e56 705 assemble_external (TREE_OPERAND (FirstExceptionMatch, 0));
8d2733ca
MS
706
707 /* did we find one? */
708 emit_cmp_insn (return_val_rtx, const0_rtx, EQ, NULL_RTX,
709 GET_MODE (return_val_rtx), 0, 0);
710
711 /* if not, jump to gotta_rethrow_it */
712 emit_jump_insn (gen_beq (gotta_rethrow_it));
713
714 /* we found it, so jump to it */
715 emit_indirect_jump (return_val_rtx);
716
717 /* code to deal with unwinding and looking for it again */
718 emit_label (gotta_rethrow_it);
719
720 /* call to __builtin_return_address () */
be99da77
MS
721#if defined (ARM_FRAME_RTX) /* was __arm */
722 /* This should be moved into arm.h:RETURN_ADDR_RTX */
723 /* This replaces a 'call' to __builtin_return_address */
e1cd6e56 724 return_val_rtx = gen_reg_rtx (Pmode);
f30432d7 725 emit_move_insn (return_val_rtx, gen_rtx (MEM, Pmode, plus_constant (hard_frame_pointer_rtx, -4)));
e1cd6e56 726#else
f30432d7 727 params = tree_cons (NULL_TREE, integer_zero_node, NULL_TREE);
8d2733ca 728 fcall = build_function_call (BuiltinReturnAddress, params);
f30432d7 729 return_val_rtx = expand_expr (fcall, NULL_RTX, Pmode, 0);
e1cd6e56 730#endif
8d2733ca
MS
731
732 /* did __builtin_return_address () return a valid address? */
733 emit_cmp_insn (return_val_rtx, const0_rtx, EQ, NULL_RTX,
734 GET_MODE (return_val_rtx), 0, 0);
735
736 emit_jump_insn (gen_beq (gotta_call_terminate));
737
be99da77 738 return_val_rtx = eh_outer_context (return_val_rtx);
e1cd6e56 739
be99da77 740 /* Yes it did. */
6467930b 741 emit_move_insn (eh_saved_pc_rtx, return_val_rtx);
f30432d7
MS
742
743 do_unwind (gen_rtx (LABEL_REF, Pmode, top_of_loop));
744 emit_jump (top_of_loop);
8d2733ca
MS
745
746 /* no it didn't --> therefore we need to call terminate */
747 emit_label (gotta_call_terminate);
748 do_function_call (Terminate, NULL_TREE, NULL_TREE);
e1cd6e56 749 assemble_external (TREE_OPERAND (Terminate, 0));
f30432d7
MS
750
751 {
752 rtx ret_val, return_val_rtx;
753 emit_label (unwind_first);
754 ret_val = expand_builtin_return_addr (BUILT_IN_RETURN_ADDRESS,
755 0, hard_frame_pointer_rtx);
756
757 /* Set it up so that we continue inside, at the top of the loop. */
758 emit_move_insn (ret_val, gen_rtx (LABEL_REF, Pmode, top_of_loop));
21451173
MS
759#ifdef RETURN_ADDR_OFFSET
760 return_val_rtx = plus_constant (ret_val, -RETURN_ADDR_OFFSET);
f30432d7
MS
761 if (return_val_rtx != ret_val)
762 emit_move_insn (ret_val, return_val_rtx);
763#endif
764
e92cc029 765 /* Fall into epilogue to unwind prologue. */
f30432d7
MS
766 }
767
fc378698 768 expand_end_bindings (getdecls (), 1, 0);
f30432d7
MS
769 poplevel (1, 0, 0);
770 pop_momentary ();
771
772 finish_function (lineno, 0, 0);
8d08fdba 773}
8d2733ca
MS
774
775
f30432d7
MS
776void
777expand_start_eh_spec ()
778{
6467930b 779 expand_eh_region_start ();
f30432d7
MS
780}
781
5566b478 782static void
f30432d7
MS
783expand_end_eh_spec (raises)
784 tree raises;
785{
786 tree expr, second_try;
787 rtx check = gen_label_rtx ();
788 rtx cont;
789 rtx ret = gen_reg_rtx (Pmode);
790 rtx flag = gen_reg_rtx (TYPE_MODE (integer_type_node));
791 rtx end = gen_label_rtx ();
792
793 expr = make_node (RTL_EXPR);
794 TREE_TYPE (expr) = void_type_node;
795 RTL_EXPR_RTL (expr) = const0_rtx;
796 TREE_SIDE_EFFECTS (expr) = 1;
797 start_sequence_for_rtl_expr (expr);
798 cont = gen_label_rtx ();
799 emit_move_insn (ret, gen_rtx (LABEL_REF, Pmode, cont));
800 emit_jump (check);
801 emit_label (cont);
802 jumpif (make_tree (integer_type_node, flag), end);
803 do_function_call (Terminate, NULL_TREE, NULL_TREE);
804 assemble_external (TREE_OPERAND (Terminate, 0));
805 emit_barrier ();
806 RTL_EXPR_SEQUENCE (expr) = get_insns ();
807 end_sequence ();
808
809 second_try = expr;
810
811 expr = make_node (RTL_EXPR);
812 TREE_TYPE (expr) = void_type_node;
813 RTL_EXPR_RTL (expr) = const0_rtx;
814 TREE_SIDE_EFFECTS (expr) = 1;
815 start_sequence_for_rtl_expr (expr);
816
817 cont = gen_label_rtx ();
818 emit_move_insn (ret, gen_rtx (LABEL_REF, Pmode, cont));
819 emit_jump (check);
820 emit_label (cont);
821 jumpif (make_tree (integer_type_node, flag), end);
6467930b 822 expand_eh_region_start ();
f30432d7
MS
823 do_function_call (Unexpected, NULL_TREE, NULL_TREE);
824 assemble_external (TREE_OPERAND (Unexpected, 0));
825 emit_barrier ();
6467930b 826 expand_eh_region_end (second_try);
f30432d7
MS
827
828 emit_label (check);
829 emit_move_insn (flag, const1_rtx);
830 cont = gen_label_rtx ();
831 while (raises)
832 {
833 tree exp;
834 tree match_type = TREE_VALUE (raises);
835
836 if (match_type)
837 {
838 /* check TREE_VALUE (raises) here */
839 exp = saved_throw_value;
840 exp = tree_cons (NULL_TREE,
841 build_eh_type_type (match_type),
842 tree_cons (NULL_TREE,
843 saved_throw_type,
844 tree_cons (NULL_TREE, exp, NULL_TREE)));
845 exp = build_function_call (CatchMatch, exp);
846 assemble_external (TREE_OPERAND (CatchMatch, 0));
847
848 jumpif (exp, cont);
849 }
850
851 raises = TREE_CHAIN (raises);
852 }
853 emit_move_insn (flag, const0_rtx);
854 emit_label (cont);
855 emit_indirect_jump (ret);
856 emit_label (end);
857
858 RTL_EXPR_SEQUENCE (expr) = get_insns ();
859 end_sequence ();
860
6467930b 861 expand_eh_region_end (expr);
f30432d7
MS
862}
863
8d2733ca
MS
864/* This is called to expand all the toplevel exception handling
865 finalization for a function. It should only be called once per
866 function. */
6467930b 867
8d08fdba 868void
8d2733ca 869expand_exception_blocks ()
8d08fdba 870{
21451173 871 rtx funcend;
c11b6f21 872 rtx insn, insns;
6467930b 873 rtx eh_spec_insns = NULL_RTX;
f30432d7
MS
874
875 start_sequence ();
8d2733ca
MS
876
877 funcend = gen_label_rtx ();
878 emit_jump (funcend);
879 /* expand_null_return (); */
880
f30432d7
MS
881 start_sequence ();
882
883 /* Add all the catch clauses here. */
884 emit_insns (catch_clauses);
885 catch_clauses = NULL_RTX;
8d2733ca
MS
886
887 expand_leftover_cleanups ();
888
f30432d7
MS
889 insns = get_insns ();
890 end_sequence ();
891
6467930b
MS
892 /* Do this after we expand leftover cleanups, so that the expand_eh_region_end
893 that expand_end_eh_spec does will match the right expand_eh_region_start,
f30432d7
MS
894 and make sure it comes out before the terminate protected region. */
895 if (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl)))
896 {
6467930b
MS
897#if 1
898 {
899 rtx insns;
900 /* New... */
901 start_sequence ();
902 expand_start_eh_spec ();
903 eh_spec_insns = get_insns ();
904 end_sequence ();
905 }
906#endif
907
f30432d7
MS
908 expand_end_eh_spec (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl)));
909 push_to_sequence (insns);
910
911 /* Now expand any new ones. */
912 expand_leftover_cleanups ();
913
914 insns = get_insns ();
915 end_sequence ();
916 }
917
918 if (insns)
919 {
6467930b 920 /* Is this necessary? */
f30432d7 921 assemble_external (TREE_OPERAND (Terminate, 0));
f30432d7 922
6467930b 923 expand_eh_region_start ();
f30432d7 924 emit_insns (insns);
6467930b
MS
925 expand_eh_region_end (TerminateFunctionCall);
926 expand_leftover_cleanups ();
f30432d7
MS
927 }
928
8d2733ca 929 {
f30432d7
MS
930 /* Mark the end of the stack unwinder. */
931 rtx unwind_insns;
932 start_sequence ();
6467930b
MS
933#if 0
934 end_eh_unwinder ();
935#endif
f30432d7
MS
936 unwind_insns = get_insns ();
937 end_sequence ();
938 if (unwind_insns)
8d2733ca 939 {
f30432d7
MS
940 insns = unwind_insns;
941 emit_insns (insns);
8d2733ca
MS
942 }
943 }
f30432d7 944
8d2733ca 945 emit_label (funcend);
f30432d7
MS
946
947 /* Only if we had previous insns do we want to emit the jump around
948 them. If there weren't any, then insns will remain NULL_RTX. */
949 if (insns)
950 insns = get_insns ();
951 end_sequence ();
952
6467930b
MS
953#if 1
954 if (eh_spec_insns)
955 emit_insns_after (eh_spec_insns, get_insns ());
956#else
957 if (eh_spec_insns)
958 store_after_parms (eh_spec_insns);
959#endif
960
c11b6f21
MS
961 insn = get_last_insn ();
962 while (GET_CODE (insn) == NOTE
963 || (GET_CODE (insn) == INSN
964 && (GET_CODE (PATTERN (insn)) == USE
965 || GET_CODE (PATTERN (insn)) == CLOBBER)))
966 insn = PREV_INSN (insn);
967
968 emit_insns_after (insns, insn);
8d08fdba
MS
969}
970
72b7eeff
MS
971tree
972start_anon_func ()
973{
974 static int counter = 0;
e92cc029 975 int old_interface_unknown = interface_unknown;
72b7eeff
MS
976 char name[32];
977 tree params;
978 tree t;
979
980 push_cp_function_context (NULL_TREE);
981 push_to_top_level ();
982
983 /* No need to mangle this. */
984 push_lang_context (lang_name_c);
985
e92cc029
MS
986 interface_unknown = 1;
987
72b7eeff
MS
988 params = void_list_node;
989 /* tcf stands for throw clean funciton. */
990 sprintf (name, "__tcf_%d", counter++);
c11b6f21
MS
991 t = make_call_declarator (get_identifier (name), params, NULL_TREE,
992 NULL_TREE);
72b7eeff
MS
993 start_function (decl_tree_cons (NULL_TREE, get_identifier ("static"),
994 void_list_node),
c11b6f21 995 t, NULL_TREE, 0);
72b7eeff
MS
996 store_parm_decls ();
997 pushlevel (0);
998 clear_last_expr ();
999 push_momentary ();
1000 expand_start_bindings (0);
1001 emit_line_note (input_filename, lineno);
1002
e92cc029
MS
1003 interface_unknown = old_interface_unknown;
1004
72b7eeff
MS
1005 pop_lang_context ();
1006
1007 return current_function_decl;
1008}
1009
1010void
1011end_anon_func ()
1012{
fc378698 1013 expand_end_bindings (getdecls (), 1, 0);
72b7eeff
MS
1014 poplevel (1, 0, 0);
1015 pop_momentary ();
1016
1017 finish_function (lineno, 0, 0);
1018
1019 pop_from_top_level ();
1020 pop_cp_function_context (NULL_TREE);
1021}
8d2733ca 1022
6467930b 1023/* Expand a throw statement. This follows the following
8d2733ca
MS
1024 algorithm:
1025
1026 1. Allocate space to save the current PC onto the stack.
1027 2. Generate and emit a label and save its address into the
e1cd6e56 1028 newly allocated stack space since we can't save the pc directly.
8d2733ca
MS
1029 3. If this is the first call to throw in this function:
1030 generate a label for the throw block
1031 4. jump to the throw block label. */
6467930b 1032
8d08fdba 1033void
8d2733ca
MS
1034expand_throw (exp)
1035 tree exp;
8d08fdba 1036{
8d2733ca 1037 rtx label;
8d08fdba 1038
8d2733ca
MS
1039 if (! doing_eh (1))
1040 return;
8d08fdba 1041
8d2733ca
MS
1042 if (exp)
1043 {
faae18ab 1044 tree throw_type;
72b7eeff 1045 tree cleanup = empty_fndecl, e;
faae18ab 1046
a3b49ccd 1047 /* throw expression */
e92cc029 1048 /* First, decay it. */
f30432d7 1049 exp = decay_conversion (exp);
a3b49ccd 1050
f30432d7
MS
1051 if (TREE_CODE (TREE_TYPE (exp)) == POINTER_TYPE)
1052 {
1053 throw_type = build_eh_type (exp);
1054 exp = build_reinterpret_cast (ptr_type_node, exp);
1055 }
1056 else
1057 {
72b7eeff
MS
1058 rtx cleanup_insns;
1059 tree object;
a50f0918 1060
f30432d7
MS
1061 /* Make a copy of the thrown object. WP 15.1.5 */
1062 exp = build_new (NULL_TREE, TREE_TYPE (exp),
1063 build_tree_list (NULL_TREE, exp),
1064 0);
faae18ab 1065
f30432d7
MS
1066 if (exp == error_mark_node)
1067 error (" in thrown expression");
faae18ab 1068
72b7eeff
MS
1069 object = build_indirect_ref (exp, NULL_PTR);
1070 throw_type = build_eh_type (object);
1071
1072 start_sequence ();
1073 object = build_reinterpret_cast (TREE_TYPE (exp), saved_throw_value);
1074 object = build_indirect_ref (object, NULL_PTR);
c73964b2 1075 cleanup = maybe_build_cleanup_and_delete (object);
72b7eeff
MS
1076 if (cleanup)
1077 expand_expr (cleanup, const0_rtx, VOIDmode, 0);
1078 cleanup_insns = get_insns ();
1079 end_sequence ();
1080
1081 if (cleanup && cleanup_insns)
1082 {
1083 cleanup = start_anon_func ();
1084
c73964b2
MS
1085 expand_expr (maybe_build_cleanup_and_delete (object),
1086 const0_rtx, VOIDmode, 0);
72b7eeff
MS
1087
1088 end_anon_func ();
1089
1090 mark_addressable (cleanup);
1091 }
1092 else
1093 {
1094 cleanup = empty_fndecl;
1095 }
f30432d7 1096 }
faae18ab 1097
be99da77
MS
1098 if (cleanup == empty_fndecl)
1099 assemble_external (empty_fndecl);
1100
f30432d7
MS
1101 e = build_modify_expr (saved_throw_type, NOP_EXPR, throw_type);
1102 expand_expr (e, const0_rtx, VOIDmode, 0);
72b7eeff 1103
f30432d7
MS
1104 e = build_modify_expr (saved_throw_value, NOP_EXPR, exp);
1105 e = build1 (CLEANUP_POINT_EXPR, TREE_TYPE (e), e);
1106 expand_expr (e, const0_rtx, VOIDmode, 0);
72b7eeff
MS
1107
1108 cleanup = build_unary_op (ADDR_EXPR, cleanup, 0);
1109 cleanup = build_modify_expr (saved_cleanup, NOP_EXPR, cleanup);
1110 expand_expr (cleanup, const0_rtx, VOIDmode, 0);
8d2733ca
MS
1111 }
1112 else
a3b49ccd
MS
1113 {
1114 /* rethrow current exception */
8ccc31eb 1115 /* This part is easy, as we don't have to do anything else. */
a3b49ccd 1116 }
8d2733ca 1117
6467930b
MS
1118 /* This is the label that represents where in the code we were, when
1119 we got an exception. This needs to be updated when we rethrow an
1120 exception, so that the matching routine knows to search out. */
1121 label = gen_label_rtx ();
1122 emit_label (label);
8d2733ca 1123
6467930b 1124 expand_internal_throw (label);
f376e137 1125}
8d2733ca
MS
1126
1127/* Build a throw expression. */
6467930b 1128
8d2733ca
MS
1129tree
1130build_throw (e)
1131 tree e;
1132{
db5ae43f
MS
1133 if (e != error_mark_node)
1134 {
fc378698
MS
1135 if (current_template_parms)
1136 return build_min (THROW_EXPR, void_type_node, e);
db5ae43f
MS
1137 e = build1 (THROW_EXPR, void_type_node, e);
1138 TREE_SIDE_EFFECTS (e) = 1;
faae18ab 1139 TREE_USED (e) = 1;
db5ae43f 1140 }
8d2733ca 1141 return e;
8d08fdba 1142}
This page took 0.326843 seconds and 5 git commands to generate.