OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gcc-4.5.1/] [gcc/] [cp/] [except.c] - Blame information for rev 283

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 283 jeremybenn
/* Handle exceptional things in C++.
2
   Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
3
   2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010
4
   Free Software Foundation, Inc.
5
   Contributed by Michael Tiemann <tiemann@cygnus.com>
6
   Rewritten by Mike Stump <mrs@cygnus.com>, based upon an
7
   initial re-implementation courtesy Tad Hunt.
8
 
9
This file is part of GCC.
10
 
11
GCC is free software; you can redistribute it and/or modify
12
it under the terms of the GNU General Public License as published by
13
the Free Software Foundation; either version 3, or (at your option)
14
any later version.
15
 
16
GCC is distributed in the hope that it will be useful,
17
but WITHOUT ANY WARRANTY; without even the implied warranty of
18
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
GNU General Public License for more details.
20
 
21
You should have received a copy of the GNU General Public License
22
along with GCC; see the file COPYING3.  If not see
23
<http://www.gnu.org/licenses/>.  */
24
 
25
 
26
#include "config.h"
27
#include "system.h"
28
#include "coretypes.h"
29
#include "tm.h"
30
#include "tree.h"
31
#include "rtl.h"
32
#include "expr.h"
33
#include "libfuncs.h"
34
#include "cp-tree.h"
35
#include "flags.h"
36
#include "output.h"
37
#include "except.h"
38
#include "toplev.h"
39
#include "tree-inline.h"
40
#include "tree-iterator.h"
41
#include "target.h"
42
#include "gimple.h"
43
 
44
static void push_eh_cleanup (tree);
45
static tree prepare_eh_type (tree);
46
static tree do_begin_catch (void);
47
static int dtor_nothrow (tree);
48
static tree do_end_catch (tree);
49
static bool decl_is_java_type (tree decl, int err);
50
static void initialize_handler_parm (tree, tree);
51
static tree do_allocate_exception (tree);
52
static tree wrap_cleanups_r (tree *, int *, void *);
53
static int complete_ptr_ref_or_void_ptr_p (tree, tree);
54
static bool is_admissible_throw_operand (tree);
55
static int can_convert_eh (tree, tree);
56
static tree cp_protect_cleanup_actions (void);
57
 
58
/* Sets up all the global eh stuff that needs to be initialized at the
59
   start of compilation.  */
60
 
61
void
62
init_exception_processing (void)
63
{
64
  tree tmp;
65
 
66
  /* void std::terminate (); */
67
  push_namespace (std_identifier);
68
  tmp = build_function_type (void_type_node, void_list_node);
69
  terminate_node = build_cp_library_fn_ptr ("terminate", tmp);
70
  TREE_THIS_VOLATILE (terminate_node) = 1;
71
  TREE_NOTHROW (terminate_node) = 1;
72
  pop_namespace ();
73
 
74
  /* void __cxa_call_unexpected(void *); */
75
  tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
76
  tmp = build_function_type (void_type_node, tmp);
77
  call_unexpected_node
78
    = push_throw_library_fn (get_identifier ("__cxa_call_unexpected"), tmp);
79
 
80
  lang_protect_cleanup_actions = &cp_protect_cleanup_actions;
81
}
82
 
83
/* Returns an expression to be executed if an unhandled exception is
84
   propagated out of a cleanup region.  */
85
 
86
static tree
87
cp_protect_cleanup_actions (void)
88
{
89
  /* [except.terminate]
90
 
91
     When the destruction of an object during stack unwinding exits
92
     using an exception ... void terminate(); is called.  */
93
  return terminate_node;
94
}
95
 
96
static tree
97
prepare_eh_type (tree type)
98
{
99
  if (type == NULL_TREE)
100
    return type;
101
  if (type == error_mark_node)
102
    return error_mark_node;
103
 
104
  /* peel back references, so they match.  */
105
  type = non_reference (type);
106
 
107
  /* Peel off cv qualifiers.  */
108
  type = TYPE_MAIN_VARIANT (type);
109
 
110
  /* Functions and arrays decay to pointers.  */
111
  type = type_decays_to (type);
112
 
113
  return type;
114
}
115
 
116
/* Return the type info for TYPE as used by EH machinery.  */
117
tree
118
eh_type_info (tree type)
119
{
120
  tree exp;
121
 
122
  if (type == NULL_TREE || type == error_mark_node)
123
    return type;
124
 
125
  if (decl_is_java_type (type, 0))
126
    exp = build_java_class_ref (TREE_TYPE (type));
127
  else
128
    exp = get_tinfo_decl (type);
129
 
130
  return exp;
131
}
132
 
133
/* Build the address of a typeinfo decl for use in the runtime
134
   matching field of the exception model.  */
135
 
136
tree
137
build_eh_type_type (tree type)
138
{
139
  tree exp = eh_type_info (type);
140
 
141
  if (!exp)
142
    return NULL;
143
 
144
  mark_used (exp);
145
 
146
  return convert (ptr_type_node, build_address (exp));
147
}
148
 
149
tree
150
build_exc_ptr (void)
151
{
152
  return build_call_n (built_in_decls [BUILT_IN_EH_POINTER],
153
                       1, integer_zero_node);
154
}
155
 
156
/* Declare a function NAME, returning RETURN_TYPE, taking a single
157
   parameter PARM_TYPE, with an empty exception specification.
158
 
159
   Note that the C++ ABI document does not have a throw-specifier on
160
   the routines declared below via this function.  The declarations
161
   are consistent with the actual implementations in libsupc++.  */
162
 
163
static tree
164
declare_nothrow_library_fn (tree name, tree return_type, tree parm_type)
165
{
166
  tree tmp = tree_cons (NULL_TREE, parm_type, void_list_node);
167
  return push_library_fn (name, build_function_type (return_type, tmp),
168
                          empty_except_spec);
169
}
170
 
171
/* Build up a call to __cxa_get_exception_ptr so that we can build a
172
   copy constructor for the thrown object.  */
173
 
174
static tree
175
do_get_exception_ptr (void)
176
{
177
  tree fn;
178
 
179
  fn = get_identifier ("__cxa_get_exception_ptr");
180
  if (!get_global_value_if_present (fn, &fn))
181
    {
182
      /* Declare void* __cxa_get_exception_ptr (void *) throw().  */
183
      fn = declare_nothrow_library_fn (fn, ptr_type_node, ptr_type_node);
184
    }
185
 
186
  return cp_build_function_call (fn, tree_cons (NULL_TREE, build_exc_ptr (),
187
                                                NULL_TREE),
188
                                 tf_warning_or_error);
189
}
190
 
191
/* Build up a call to __cxa_begin_catch, to tell the runtime that the
192
   exception has been handled.  */
193
 
194
static tree
195
do_begin_catch (void)
196
{
197
  tree fn;
198
 
199
  fn = get_identifier ("__cxa_begin_catch");
200
  if (!get_global_value_if_present (fn, &fn))
201
    {
202
      /* Declare void* __cxa_begin_catch (void *) throw().  */
203
      fn = declare_nothrow_library_fn (fn, ptr_type_node, ptr_type_node);
204
    }
205
 
206
  return cp_build_function_call (fn, tree_cons (NULL_TREE, build_exc_ptr (),
207
                                                NULL_TREE),
208
                                 tf_warning_or_error);
209
}
210
 
211
/* Returns nonzero if cleaning up an exception of type TYPE (which can be
212
   NULL_TREE for a ... handler) will not throw an exception.  */
213
 
214
static int
215
dtor_nothrow (tree type)
216
{
217
  if (type == NULL_TREE || type == error_mark_node)
218
    return 0;
219
 
220
  if (TYPE_HAS_TRIVIAL_DESTRUCTOR (type))
221
    return 1;
222
 
223
  if (CLASSTYPE_LAZY_DESTRUCTOR (type))
224
    lazily_declare_fn (sfk_destructor, type);
225
 
226
  return TREE_NOTHROW (CLASSTYPE_DESTRUCTORS (type));
227
}
228
 
229
/* Build up a call to __cxa_end_catch, to destroy the exception object
230
   for the current catch block if no others are currently using it.  */
231
 
232
static tree
233
do_end_catch (tree type)
234
{
235
  tree fn, cleanup;
236
 
237
  fn = get_identifier ("__cxa_end_catch");
238
  if (!get_global_value_if_present (fn, &fn))
239
    {
240
      /* Declare void __cxa_end_catch ().  */
241
      fn = push_void_library_fn (fn, void_list_node);
242
      /* This can throw if the destructor for the exception throws.  */
243
      TREE_NOTHROW (fn) = 0;
244
    }
245
 
246
  cleanup = cp_build_function_call (fn, NULL_TREE, tf_warning_or_error);
247
  TREE_NOTHROW (cleanup) = dtor_nothrow (type);
248
 
249
  return cleanup;
250
}
251
 
252
/* This routine creates the cleanup for the current exception.  */
253
 
254
static void
255
push_eh_cleanup (tree type)
256
{
257
  finish_decl_cleanup (NULL_TREE, do_end_catch (type));
258
}
259
 
260
/* Return nonzero value if DECL is a Java type suitable for catch or
261
   throw.  */
262
 
263
static bool
264
decl_is_java_type (tree decl, int err)
265
{
266
  bool r = (TREE_CODE (decl) == POINTER_TYPE
267
            && TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE
268
            && TYPE_FOR_JAVA (TREE_TYPE (decl)));
269
 
270
  if (err)
271
    {
272
      if (TREE_CODE (decl) == REFERENCE_TYPE
273
          && TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE
274
          && TYPE_FOR_JAVA (TREE_TYPE (decl)))
275
        {
276
          /* Can't throw a reference.  */
277
          error ("type %qT is disallowed in Java %<throw%> or %<catch%>",
278
                 decl);
279
        }
280
 
281
      if (r)
282
        {
283
          tree jthrow_node
284
            = IDENTIFIER_GLOBAL_VALUE (get_identifier ("jthrowable"));
285
 
286
          if (jthrow_node == NULL_TREE)
287
            fatal_error
288
              ("call to Java %<catch%> or %<throw%> with %<jthrowable%> undefined");
289
 
290
          jthrow_node = TREE_TYPE (TREE_TYPE (jthrow_node));
291
 
292
          if (! DERIVED_FROM_P (jthrow_node, TREE_TYPE (decl)))
293
            {
294
              /* Thrown object must be a Throwable.  */
295
              error ("type %qT is not derived from %<java::lang::Throwable%>",
296
                     TREE_TYPE (decl));
297
            }
298
        }
299
    }
300
 
301
  return r;
302
}
303
 
304
/* Select the personality routine to be used for exception handling,
305
   or issue an error if we need two different ones in the same
306
   translation unit.
307
   ??? At present eh_personality_decl is set to
308
   __gxx_personality_(sj|v)0 in init_exception_processing - should it
309
   be done here instead?  */
310
void
311
choose_personality_routine (enum languages lang)
312
{
313
  static enum {
314
    chose_none,
315
    chose_cpp,
316
    chose_java,
317
    gave_error
318
  } state;
319
 
320
  switch (state)
321
    {
322
    case gave_error:
323
      return;
324
 
325
    case chose_cpp:
326
      if (lang != lang_cplusplus)
327
        goto give_error;
328
      return;
329
 
330
    case chose_java:
331
      if (lang != lang_java)
332
        goto give_error;
333
      return;
334
 
335
    case chose_none:
336
      ; /* Proceed to language selection.  */
337
    }
338
 
339
  switch (lang)
340
    {
341
    case lang_cplusplus:
342
      state = chose_cpp;
343
      break;
344
 
345
    case lang_java:
346
      state = chose_java;
347
      terminate_node = built_in_decls [BUILT_IN_ABORT];
348
      pragma_java_exceptions = true;
349
      break;
350
 
351
    default:
352
      gcc_unreachable ();
353
    }
354
  return;
355
 
356
 give_error:
357
  error ("mixing C++ and Java catches in a single translation unit");
358
  state = gave_error;
359
}
360
 
361
/* Initialize the catch parameter DECL.  */
362
 
363
static void
364
initialize_handler_parm (tree decl, tree exp)
365
{
366
  tree init;
367
  tree init_type;
368
 
369
  /* Make sure we mark the catch param as used, otherwise we'll get a
370
     warning about an unused ((anonymous)).  */
371
  TREE_USED (decl) = 1;
372
 
373
  /* Figure out the type that the initializer is.  Pointers are returned
374
     adjusted by value from __cxa_begin_catch.  Others are returned by
375
     reference.  */
376
  init_type = TREE_TYPE (decl);
377
  if (!POINTER_TYPE_P (init_type))
378
    init_type = build_reference_type (init_type);
379
 
380
  choose_personality_routine (decl_is_java_type (init_type, 0)
381
                              ? lang_java : lang_cplusplus);
382
 
383
  /* Since pointers are passed by value, initialize a reference to
384
     pointer catch parm with the address of the temporary.  */
385
  if (TREE_CODE (init_type) == REFERENCE_TYPE
386
      && TYPE_PTR_P (TREE_TYPE (init_type)))
387
    exp = cp_build_unary_op (ADDR_EXPR, exp, 1, tf_warning_or_error);
388
 
389
  exp = ocp_convert (init_type, exp, CONV_IMPLICIT|CONV_FORCE_TEMP, 0);
390
 
391
  init = convert_from_reference (exp);
392
 
393
  /* If the constructor for the catch parm exits via an exception, we
394
     must call terminate.  See eh23.C.  */
395
  if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
396
    {
397
      /* Generate the copy constructor call directly so we can wrap it.
398
         See also expand_default_init.  */
399
      init = ocp_convert (TREE_TYPE (decl), init,
400
                          CONV_IMPLICIT|CONV_FORCE_TEMP, 0);
401
      /* Force cleanups now to avoid nesting problems with the
402
         MUST_NOT_THROW_EXPR.  */
403
      init = fold_build_cleanup_point_expr (TREE_TYPE (init), init);
404
      init = build1 (MUST_NOT_THROW_EXPR, TREE_TYPE (init), init);
405
    }
406
 
407
  decl = pushdecl (decl);
408
 
409
  start_decl_1 (decl, true);
410
  cp_finish_decl (decl, init, /*init_const_expr_p=*/false, NULL_TREE,
411
                  LOOKUP_ONLYCONVERTING|DIRECT_BIND);
412
}
413
 
414
/* Call this to start a catch block.  DECL is the catch parameter.  */
415
 
416
tree
417
expand_start_catch_block (tree decl)
418
{
419
  tree exp;
420
  tree type, init;
421
 
422
  if (! doing_eh (1))
423
    return NULL_TREE;
424
 
425
  /* Make sure this declaration is reasonable.  */
426
  if (decl && !complete_ptr_ref_or_void_ptr_p (TREE_TYPE (decl), NULL_TREE))
427
    decl = error_mark_node;
428
 
429
  if (decl)
430
    type = prepare_eh_type (TREE_TYPE (decl));
431
  else
432
    type = NULL_TREE;
433
 
434
  if (decl && decl_is_java_type (type, 1))
435
    {
436
      /* Java only passes object via pointer and doesn't require
437
         adjusting.  The java object is immediately before the
438
         generic exception header.  */
439
      exp = build_exc_ptr ();
440
      exp = build1 (NOP_EXPR, build_pointer_type (type), exp);
441
      exp = build2 (POINTER_PLUS_EXPR, TREE_TYPE (exp), exp,
442
                    fold_build1_loc (input_location,
443
                                 NEGATE_EXPR, sizetype,
444
                                 TYPE_SIZE_UNIT (TREE_TYPE (exp))));
445
      exp = cp_build_indirect_ref (exp, RO_NULL, tf_warning_or_error);
446
      initialize_handler_parm (decl, exp);
447
      return type;
448
    }
449
 
450
  /* Call __cxa_end_catch at the end of processing the exception.  */
451
  push_eh_cleanup (type);
452
 
453
  init = do_begin_catch ();
454
 
455
  /* If there's no decl at all, then all we need to do is make sure
456
     to tell the runtime that we've begun handling the exception.  */
457
  if (decl == NULL || decl == error_mark_node || init == error_mark_node)
458
    finish_expr_stmt (init);
459
 
460
  /* If the C++ object needs constructing, we need to do that before
461
     calling __cxa_begin_catch, so that std::uncaught_exception gets
462
     the right value during the copy constructor.  */
463
  else if (flag_use_cxa_get_exception_ptr
464
           && TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
465
    {
466
      exp = do_get_exception_ptr ();
467
      initialize_handler_parm (decl, exp);
468
      finish_expr_stmt (init);
469
    }
470
 
471
  /* Otherwise the type uses a bitwise copy, and we don't have to worry
472
     about the value of std::uncaught_exception and therefore can do the
473
     copy with the return value of __cxa_end_catch instead.  */
474
  else
475
    {
476
      tree init_type = type;
477
 
478
      /* Pointers are passed by values, everything else by reference.  */
479
      if (!TYPE_PTR_P (type))
480
        init_type = build_pointer_type (type);
481
      if (init_type != TREE_TYPE (init))
482
        init = build1 (NOP_EXPR, init_type, init);
483
      exp = create_temporary_var (init_type);
484
      DECL_REGISTER (exp) = 1;
485
      cp_finish_decl (exp, init, /*init_const_expr=*/false,
486
                      NULL_TREE, LOOKUP_ONLYCONVERTING);
487
      initialize_handler_parm (decl, exp);
488
    }
489
 
490
  return type;
491
}
492
 
493
 
494
/* Call this to end a catch block.  Its responsible for emitting the
495
   code to handle jumping back to the correct place, and for emitting
496
   the label to jump to if this catch block didn't match.  */
497
 
498
void
499
expand_end_catch_block (void)
500
{
501
  if (! doing_eh (1))
502
    return;
503
 
504
  /* The exception being handled is rethrown if control reaches the end of
505
     a handler of the function-try-block of a constructor or destructor.  */
506
  if (in_function_try_handler
507
      && (DECL_CONSTRUCTOR_P (current_function_decl)
508
          || DECL_DESTRUCTOR_P (current_function_decl)))
509
    finish_expr_stmt (build_throw (NULL_TREE));
510
}
511
 
512
tree
513
begin_eh_spec_block (void)
514
{
515
  tree r = build_stmt (input_location, EH_SPEC_BLOCK, NULL_TREE, NULL_TREE);
516
  add_stmt (r);
517
  EH_SPEC_STMTS (r) = push_stmt_list ();
518
  return r;
519
}
520
 
521
void
522
finish_eh_spec_block (tree raw_raises, tree eh_spec_block)
523
{
524
  tree raises;
525
 
526
  EH_SPEC_STMTS (eh_spec_block) = pop_stmt_list (EH_SPEC_STMTS (eh_spec_block));
527
 
528
  /* Strip cv quals, etc, from the specification types.  */
529
  for (raises = NULL_TREE;
530
       raw_raises && TREE_VALUE (raw_raises);
531
       raw_raises = TREE_CHAIN (raw_raises))
532
    {
533
      tree type = prepare_eh_type (TREE_VALUE (raw_raises));
534
      tree tinfo = eh_type_info (type);
535
 
536
      mark_used (tinfo);
537
      raises = tree_cons (NULL_TREE, type, raises);
538
    }
539
 
540
  EH_SPEC_RAISES (eh_spec_block) = raises;
541
}
542
 
543
/* Return a pointer to a buffer for an exception object of type TYPE.  */
544
 
545
static tree
546
do_allocate_exception (tree type)
547
{
548
  tree fn;
549
 
550
  fn = get_identifier ("__cxa_allocate_exception");
551
  if (!get_global_value_if_present (fn, &fn))
552
    {
553
      /* Declare void *__cxa_allocate_exception(size_t) throw().  */
554
      fn = declare_nothrow_library_fn (fn, ptr_type_node, size_type_node);
555
    }
556
 
557
  return cp_build_function_call (fn,
558
                                 tree_cons (NULL_TREE, size_in_bytes (type),
559
                                            NULL_TREE),
560
                                 tf_warning_or_error);
561
}
562
 
563
/* Call __cxa_free_exception from a cleanup.  This is never invoked
564
   directly, but see the comment for stabilize_throw_expr.  */
565
 
566
static tree
567
do_free_exception (tree ptr)
568
{
569
  tree fn;
570
 
571
  fn = get_identifier ("__cxa_free_exception");
572
  if (!get_global_value_if_present (fn, &fn))
573
    {
574
      /* Declare void __cxa_free_exception (void *) throw().  */
575
      fn = declare_nothrow_library_fn (fn, void_type_node, ptr_type_node);
576
    }
577
 
578
  return cp_build_function_call (fn, tree_cons (NULL_TREE, ptr, NULL_TREE),
579
                                 tf_warning_or_error);
580
}
581
 
582
/* Wrap all cleanups for TARGET_EXPRs in MUST_NOT_THROW_EXPR.
583
   Called from build_throw via walk_tree_without_duplicates.  */
584
 
585
static tree
586
wrap_cleanups_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
587
                 void *data ATTRIBUTE_UNUSED)
588
{
589
  tree exp = *tp;
590
  tree cleanup;
591
 
592
  /* Don't walk into types.  */
593
  if (TYPE_P (exp))
594
    {
595
      *walk_subtrees = 0;
596
      return NULL_TREE;
597
    }
598
  if (TREE_CODE (exp) != TARGET_EXPR)
599
    return NULL_TREE;
600
 
601
  cleanup = TARGET_EXPR_CLEANUP (exp);
602
  if (cleanup)
603
    {
604
      cleanup = build1 (MUST_NOT_THROW_EXPR, void_type_node, cleanup);
605
      TARGET_EXPR_CLEANUP (exp) = cleanup;
606
    }
607
 
608
  /* Keep iterating.  */
609
  return NULL_TREE;
610
}
611
 
612
/* Build a throw expression.  */
613
 
614
tree
615
build_throw (tree exp)
616
{
617
  tree fn;
618
 
619
  if (exp == error_mark_node)
620
    return exp;
621
 
622
  if (processing_template_decl)
623
    {
624
      if (cfun)
625
        current_function_returns_abnormally = 1;
626
      return build_min (THROW_EXPR, void_type_node, exp);
627
    }
628
 
629
  if (exp == null_node)
630
    warning (0, "throwing NULL, which has integral, not pointer type");
631
 
632
  if (exp != NULL_TREE)
633
    {
634
      if (!is_admissible_throw_operand (exp))
635
        return error_mark_node;
636
    }
637
 
638
  if (! doing_eh (1))
639
    return error_mark_node;
640
 
641
  if (exp && decl_is_java_type (TREE_TYPE (exp), 1))
642
    {
643
      tree fn = get_identifier ("_Jv_Throw");
644
      if (!get_global_value_if_present (fn, &fn))
645
        {
646
          /* Declare void _Jv_Throw (void *).  */
647
          tree tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
648
          tmp = build_function_type (ptr_type_node, tmp);
649
          fn = push_throw_library_fn (fn, tmp);
650
        }
651
      else if (really_overloaded_fn (fn))
652
        {
653
          error ("%qD should never be overloaded", fn);
654
          return error_mark_node;
655
        }
656
      fn = OVL_CURRENT (fn);
657
      exp = cp_build_function_call (fn, tree_cons (NULL_TREE, exp, NULL_TREE),
658
                                    tf_warning_or_error);
659
    }
660
  else if (exp)
661
    {
662
      tree throw_type;
663
      tree temp_type;
664
      tree cleanup;
665
      tree object, ptr;
666
      tree tmp;
667
      tree temp_expr, allocate_expr;
668
      bool elided;
669
 
670
      /* The CLEANUP_TYPE is the internal type of a destructor.  */
671
      if (!cleanup_type)
672
        {
673
          tmp = void_list_node;
674
          tmp = tree_cons (NULL_TREE, ptr_type_node, tmp);
675
          tmp = build_function_type (void_type_node, tmp);
676
          cleanup_type = build_pointer_type (tmp);
677
        }
678
 
679
      fn = get_identifier ("__cxa_throw");
680
      if (!get_global_value_if_present (fn, &fn))
681
        {
682
          /* Declare void __cxa_throw (void*, void*, void (*)(void*)).  */
683
          /* ??? Second argument is supposed to be "std::type_info*".  */
684
          tmp = void_list_node;
685
          tmp = tree_cons (NULL_TREE, cleanup_type, tmp);
686
          tmp = tree_cons (NULL_TREE, ptr_type_node, tmp);
687
          tmp = tree_cons (NULL_TREE, ptr_type_node, tmp);
688
          tmp = build_function_type (void_type_node, tmp);
689
          fn = push_throw_library_fn (fn, tmp);
690
        }
691
 
692
      /* [except.throw]
693
 
694
         A throw-expression initializes a temporary object, the type
695
         of which is determined by removing any top-level
696
         cv-qualifiers from the static type of the operand of throw
697
         and adjusting the type from "array of T" or "function return
698
         T" to "pointer to T" or "pointer to function returning T"
699
         respectively.  */
700
      temp_type = is_bitfield_expr_with_lowered_type (exp);
701
      if (!temp_type)
702
        temp_type = type_decays_to (TREE_TYPE (exp));
703
 
704
      /* OK, this is kind of wacky.  The standard says that we call
705
         terminate when the exception handling mechanism, after
706
         completing evaluation of the expression to be thrown but
707
         before the exception is caught (_except.throw_), calls a
708
         user function that exits via an uncaught exception.
709
 
710
         So we have to protect the actual initialization of the
711
         exception object with terminate(), but evaluate the
712
         expression first.  Since there could be temps in the
713
         expression, we need to handle that, too.  We also expand
714
         the call to __cxa_allocate_exception first (which doesn't
715
         matter, since it can't throw).  */
716
 
717
      /* Allocate the space for the exception.  */
718
      allocate_expr = do_allocate_exception (temp_type);
719
      allocate_expr = get_target_expr (allocate_expr);
720
      ptr = TARGET_EXPR_SLOT (allocate_expr);
721
      object = build_nop (build_pointer_type (temp_type), ptr);
722
      object = cp_build_indirect_ref (object, RO_NULL, tf_warning_or_error);
723
 
724
      elided = (TREE_CODE (exp) == TARGET_EXPR);
725
 
726
      /* And initialize the exception object.  */
727
      if (CLASS_TYPE_P (temp_type))
728
        {
729
          int flags = LOOKUP_NORMAL | LOOKUP_ONLYCONVERTING;
730
          VEC(tree,gc) *exp_vec;
731
 
732
          /* Under C++0x [12.8/16 class.copy], a thrown lvalue is sometimes
733
             treated as an rvalue for the purposes of overload resolution
734
             to favor move constructors over copy constructors.  */
735
          if (/* Must be a local, automatic variable.  */
736
              TREE_CODE (exp) == VAR_DECL
737
              && DECL_CONTEXT (exp) == current_function_decl
738
              && ! TREE_STATIC (exp)
739
              /* The variable must not have the `volatile' qualifier.  */
740
              && !(cp_type_quals (TREE_TYPE (exp)) & TYPE_QUAL_VOLATILE))
741
            flags = flags | LOOKUP_PREFER_RVALUE;
742
 
743
          /* Call the copy constructor.  */
744
          exp_vec = make_tree_vector_single (exp);
745
          exp = (build_special_member_call
746
                 (object, complete_ctor_identifier, &exp_vec,
747
                  TREE_TYPE (object), flags, tf_warning_or_error));
748
          release_tree_vector (exp_vec);
749
          if (exp == error_mark_node)
750
            {
751
              error ("  in thrown expression");
752
              return error_mark_node;
753
            }
754
        }
755
      else
756
        {
757
          tmp = decay_conversion (exp);
758
          if (tmp == error_mark_node)
759
            return error_mark_node;
760
          exp = build2 (INIT_EXPR, temp_type, object, tmp);
761
        }
762
 
763
      /* Pre-evaluate the thrown expression first, since if we allocated
764
         the space first we would have to deal with cleaning it up if
765
         evaluating this expression throws.
766
 
767
         The case where EXP the initializer is a cast or a function
768
         returning a class is a bit of a grey area in the standard; it's
769
         unclear whether or not it should be allowed to throw.  We used to
770
         say no, as that allowed us to optimize this case without worrying
771
         about deallocating the exception object if it does.  But that
772
         conflicted with expectations (PR 13944) and the EDG compiler; now
773
         we wrap the initialization in a TRY_CATCH_EXPR to call
774
         do_free_exception rather than in a MUST_NOT_THROW_EXPR, for this
775
         case only.
776
 
777
         BUT: Issue 475 may do away with this inconsistency by removing the
778
         terminate() in this situation.
779
 
780
         Note that we don't check the return value from stabilize_init
781
         because it will only return false in cases where elided is true,
782
         and therefore we don't need to work around the failure to
783
         preevaluate.  */
784
      temp_expr = NULL_TREE;
785
      stabilize_init (exp, &temp_expr);
786
 
787
      /* Wrap the initialization in a CLEANUP_POINT_EXPR so that cleanups
788
         for temporaries within the initialization are run before the one
789
         for the exception object, preserving LIFO order.  */
790
      exp = build1 (CLEANUP_POINT_EXPR, void_type_node, exp);
791
 
792
      if (elided)
793
        exp = build2 (TRY_CATCH_EXPR, void_type_node, exp,
794
                      do_free_exception (ptr));
795
      else
796
        exp = build1 (MUST_NOT_THROW_EXPR, void_type_node, exp);
797
 
798
      /* Prepend the allocation.  */
799
      exp = build2 (COMPOUND_EXPR, TREE_TYPE (exp), allocate_expr, exp);
800
      if (temp_expr)
801
        {
802
          /* Prepend the calculation of the throw expression.  Also, force
803
             any cleanups from the expression to be evaluated here so that
804
             we don't have to do them during unwinding.  But first wrap
805
             them in MUST_NOT_THROW_EXPR, since they are run after the
806
             exception object is initialized.  */
807
          cp_walk_tree_without_duplicates (&temp_expr, wrap_cleanups_r, 0);
808
          exp = build2 (COMPOUND_EXPR, TREE_TYPE (exp), temp_expr, exp);
809
          exp = build1 (CLEANUP_POINT_EXPR, TREE_TYPE (exp), exp);
810
        }
811
 
812
      throw_type = build_eh_type_type (prepare_eh_type (TREE_TYPE (object)));
813
 
814
      if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (object)))
815
        {
816
          cleanup = lookup_fnfields (TYPE_BINFO (TREE_TYPE (object)),
817
                                     complete_dtor_identifier, 0);
818
          cleanup = BASELINK_FUNCTIONS (cleanup);
819
          mark_used (cleanup);
820
          cxx_mark_addressable (cleanup);
821
          /* Pretend it's a normal function.  */
822
          cleanup = build1 (ADDR_EXPR, cleanup_type, cleanup);
823
        }
824
      else
825
        cleanup = build_int_cst (cleanup_type, 0);
826
 
827
      tmp = tree_cons (NULL_TREE, cleanup, NULL_TREE);
828
      tmp = tree_cons (NULL_TREE, throw_type, tmp);
829
      tmp = tree_cons (NULL_TREE, ptr, tmp);
830
      /* ??? Indicate that this function call throws throw_type.  */
831
      tmp = cp_build_function_call (fn, tmp, tf_warning_or_error);
832
 
833
      /* Tack on the initialization stuff.  */
834
      exp = build2 (COMPOUND_EXPR, TREE_TYPE (tmp), exp, tmp);
835
    }
836
  else
837
    {
838
      /* Rethrow current exception.  */
839
 
840
      tree fn = get_identifier ("__cxa_rethrow");
841
      if (!get_global_value_if_present (fn, &fn))
842
        {
843
          /* Declare void __cxa_rethrow (void).  */
844
          fn = push_throw_library_fn
845
            (fn, build_function_type (void_type_node, void_list_node));
846
        }
847
 
848
      /* ??? Indicate that this function call allows exceptions of the type
849
         of the enclosing catch block (if known).  */
850
      exp = cp_build_function_call (fn, NULL_TREE, tf_warning_or_error);
851
    }
852
 
853
  exp = build1 (THROW_EXPR, void_type_node, exp);
854
 
855
  return exp;
856
}
857
 
858
/* Make sure TYPE is complete, pointer to complete, reference to
859
   complete, or pointer to cv void. Issue diagnostic on failure.
860
   Return the zero on failure and nonzero on success. FROM can be
861
   the expr or decl from whence TYPE came, if available.  */
862
 
863
static int
864
complete_ptr_ref_or_void_ptr_p (tree type, tree from)
865
{
866
  int is_ptr;
867
 
868
  /* Check complete.  */
869
  type = complete_type_or_else (type, from);
870
  if (!type)
871
    return 0;
872
 
873
  /* Or a pointer or ref to one, or cv void *.  */
874
  is_ptr = TREE_CODE (type) == POINTER_TYPE;
875
  if (is_ptr || TREE_CODE (type) == REFERENCE_TYPE)
876
    {
877
      tree core = TREE_TYPE (type);
878
 
879
      if (is_ptr && VOID_TYPE_P (core))
880
        /* OK */;
881
      else if (!complete_type_or_else (core, from))
882
        return 0;
883
    }
884
  return 1;
885
}
886
 
887
/* Return truth-value if EXPRESSION is admissible in throw-expression,
888
   i.e. if it is not of incomplete type or a pointer/reference to such
889
   a type or of an abstract class type.  */
890
 
891
static bool
892
is_admissible_throw_operand (tree expr)
893
{
894
  tree type = TREE_TYPE (expr);
895
 
896
  /* 15.1/4 [...] The type of the throw-expression shall not be an
897
            incomplete type, or a pointer or a reference to an incomplete
898
            type, other than void*, const void*, volatile void*, or
899
            const volatile void*.  Except for these restriction and the
900
            restrictions on type matching mentioned in 15.3, the operand
901
            of throw is treated exactly as a function argument in a call
902
            (5.2.2) or the operand of a return statement.  */
903
  if (!complete_ptr_ref_or_void_ptr_p (type, expr))
904
    return false;
905
 
906
  /* 10.4/3 An abstract class shall not be used as a parameter type,
907
            as a function return type or as type of an explicit
908
            conversion.  */
909
  else if (CLASS_TYPE_P (type) && CLASSTYPE_PURE_VIRTUALS (type))
910
    {
911
      error ("expression %qE of abstract class type %qT cannot "
912
             "be used in throw-expression", expr, type);
913
      return false;
914
    }
915
 
916
  return true;
917
}
918
 
919
/* Returns nonzero if FN is a declaration of a standard C library
920
   function which is known not to throw.
921
 
922
   [lib.res.on.exception.handling]: None of the functions from the
923
   Standard C library shall report an error by throwing an
924
   exception, unless it calls a program-supplied function that
925
   throws an exception.  */
926
 
927
#include "cfns.h"
928
 
929
int
930
nothrow_libfn_p (const_tree fn)
931
{
932
  tree id;
933
 
934
  if (TREE_PUBLIC (fn)
935
      && DECL_EXTERNAL (fn)
936
      && DECL_NAMESPACE_SCOPE_P (fn)
937
      && DECL_EXTERN_C_P (fn))
938
    /* OK */;
939
  else
940
    /* Can't be a C library function.  */
941
    return 0;
942
 
943
  /* Being a C library function, DECL_ASSEMBLER_NAME == DECL_NAME
944
     unless the system headers are playing rename tricks, and if
945
     they are, we don't want to be confused by them.  */
946
  id = DECL_NAME (fn);
947
  return !!libc_name_p (IDENTIFIER_POINTER (id), IDENTIFIER_LENGTH (id));
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 int
954
can_convert_eh (tree to, tree from)
955
{
956
  to = non_reference (to);
957
  from = non_reference (from);
958
 
959
  if (TREE_CODE (to) == POINTER_TYPE && TREE_CODE (from) == POINTER_TYPE)
960
    {
961
      to = TREE_TYPE (to);
962
      from = TREE_TYPE (from);
963
 
964
      if (! at_least_as_qualified_p (to, from))
965
        return 0;
966
 
967
      if (TREE_CODE (to) == VOID_TYPE)
968
        return 1;
969
 
970
      /* Else fall through.  */
971
    }
972
 
973
  if (CLASS_TYPE_P (to) && CLASS_TYPE_P (from)
974
      && PUBLICLY_UNIQUELY_DERIVED_P (to, from))
975
    return 1;
976
 
977
  return 0;
978
}
979
 
980
/* Check whether any of the handlers in I are shadowed by another handler
981
   accepting TYPE.  Note that the shadowing may not be complete; even if
982
   an exception of type B would be caught by a handler for A, there could
983
   be a derived class C for which A is an ambiguous base but B is not, so
984
   the handler for B would catch an exception of type C.  */
985
 
986
static void
987
check_handlers_1 (tree master, tree_stmt_iterator i)
988
{
989
  tree type = TREE_TYPE (master);
990
 
991
  for (; !tsi_end_p (i); tsi_next (&i))
992
    {
993
      tree handler = tsi_stmt (i);
994
      if (TREE_TYPE (handler) && can_convert_eh (type, TREE_TYPE (handler)))
995
        {
996
          warning_at (EXPR_LOCATION (handler), 0,
997
                      "exception of type %qT will be caught",
998
                      TREE_TYPE (handler));
999
          warning_at (EXPR_LOCATION (master), 0,
1000
                      "   by earlier handler for %qT", type);
1001
          break;
1002
        }
1003
    }
1004
}
1005
 
1006
/* Given a STATEMENT_LIST of HANDLERs, make sure that they're OK.  */
1007
 
1008
void
1009
check_handlers (tree handlers)
1010
{
1011
  tree_stmt_iterator i;
1012
 
1013
  /* If we don't have a STATEMENT_LIST, then we've just got one
1014
     handler, and thus nothing to warn about.  */
1015
  if (TREE_CODE (handlers) != STATEMENT_LIST)
1016
    return;
1017
 
1018
  i = tsi_start (handlers);
1019
  if (!tsi_end_p (i))
1020
    while (1)
1021
      {
1022
        tree handler = tsi_stmt (i);
1023
        tsi_next (&i);
1024
 
1025
        /* No more handlers; nothing to shadow.  */
1026
        if (tsi_end_p (i))
1027
          break;
1028
        if (TREE_TYPE (handler) == NULL_TREE)
1029
          permerror (EXPR_LOCATION (handler), "%<...%>"
1030
                     " handler must be the last handler for its try block");
1031
        else
1032
          check_handlers_1 (handler, i);
1033
      }
1034
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.