OSDN Git Service

* except.c (expand_start_eh_spec): Use the try/catch code.
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 21 Nov 1997 20:29:06 +0000 (20:29 +0000)
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 21 Nov 1997 20:29:06 +0000 (20:29 +0000)
(expand_end_eh_spec): Likewise.  Call __check_eh_spec instead of
doing everything inline.
(init_exception_processing): throw_type_match now takes
  const void pointers.
* exception.cc (__check_eh_spec): New fn.
* inc/exception: Neither terminate nor unexpected return.
* decl.c: Make const_ptr_type_node public.
* tinfo2.cc (__throw_type_match_rtti): Take the typeinfos constly.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@16651 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/decl.c
gcc/cp/except.c
gcc/cp/exception.cc
gcc/cp/inc/exception
gcc/cp/tinfo2.cc

index c88e084..88c9d2e 100644 (file)
@@ -1,5 +1,15 @@
 Fri Nov 21 12:22:07 1997  Jason Merrill  <jason@yorick.cygnus.com>
 
+       * except.c (expand_start_eh_spec): Use the try/catch code.
+       (expand_end_eh_spec): Likewise.  Call __check_eh_spec instead of
+       doing everything inline.
+       (init_exception_processing): throw_type_match now takes
+       const void pointers.
+       * exception.cc (__check_eh_spec): New fn.
+       * inc/exception: Neither terminate nor unexpected return.
+       * decl.c: Make const_ptr_type_node public.
+       * tinfo2.cc (__throw_type_match_rtti): Take the typeinfos constly.
+
        * except.c (expand_start_catch_block): We only need the rethrow
        region for non-sjlj exceptions.
        (expand_end_catch_block): Likewise.  Use outer_context_label_stack.
index 39e7a5a..7b2e1c2 100644 (file)
@@ -239,7 +239,7 @@ tree void_zero_node;
 /* Nodes for types `void *' and `const void *'.  */
 
 tree ptr_type_node;
-static tree const_ptr_type_node;
+tree const_ptr_type_node;
 
 /* Nodes for types `char *' and `const char *'.  */
 
index 5c2344d..bd26053 100644 (file)
@@ -197,6 +197,7 @@ static tree saved_pc;
 
 extern int throw_used;
 extern rtx catch_clauses;
+extern tree const_ptr_type_node;
 
 /* ========================================================================= */
 
@@ -263,8 +264,8 @@ init_exception_processing ()
                        ? "__throw_type_match_rtti"
                        : "__throw_type_match",
                        build_function_type (ptr_type_node,
-                                            tree_cons (NULL_TREE, ptr_type_node,
-                                                       tree_cons (NULL_TREE, ptr_type_node,
+                                            tree_cons (NULL_TREE, const_ptr_type_node,
+                                                       tree_cons (NULL_TREE, const_ptr_type_node,
                                                                   tree_cons (NULL_TREE, ptr_type_node,
                                                                              void_list_node)))),
                        NOT_BUILT_IN, NULL_PTR);
@@ -1020,101 +1021,84 @@ expand_builtin_throw ()
 #endif /* DWARF2_UNWIND_INFO */
 }
 
+/* An exception spec is implemented more or less like:
+
+   try {
+     function body;
+   } catch (...) {
+     void *p[] = { typeid(raises) };
+     __check_eh_spec (p, count);
+   }
+
+   __check_eh_spec in exception.cc handles all the details.  */
 
 void
 expand_start_eh_spec ()
 {
-  expand_eh_region_start ();
+  expand_start_try_stmts ();
 }
 
 static void
 expand_end_eh_spec (raises)
      tree raises;
 {
-  tree expr, second_try;
-  rtx check = gen_label_rtx ();
-  rtx cont;
-  rtx ret = gen_reg_rtx (Pmode);
-  rtx flag = gen_reg_rtx (TYPE_MODE (integer_type_node));
-  rtx end = gen_label_rtx ();
-
-  expr = make_node (RTL_EXPR);
-  TREE_TYPE (expr) = void_type_node;
-  RTL_EXPR_RTL (expr) = const0_rtx;
-  TREE_SIDE_EFFECTS (expr) = 1;
-  do_pending_stack_adjust ();
-  start_sequence_for_rtl_expr (expr);
-  cont = gen_label_rtx ();
-  emit_move_insn (ret, gen_rtx (LABEL_REF, Pmode, cont));
-  emit_jump (check);
-  emit_label (cont);
-  jumpif (make_tree (integer_type_node, flag), end);
-  do_function_call (Terminate, NULL_TREE, NULL_TREE);
-  assemble_external (TREE_OPERAND (Terminate, 0));
-  emit_barrier ();
-  do_pending_stack_adjust ();
-  RTL_EXPR_SEQUENCE (expr) = get_insns ();
-  end_sequence ();
-  
-  second_try = expr;
+  tree tmp, fn, decl, types = NULL_TREE;
+  int count = 0;
 
-  expr = make_node (RTL_EXPR);
-  TREE_TYPE (expr) = void_type_node;
-  RTL_EXPR_RTL (expr) = const0_rtx;
-  TREE_SIDE_EFFECTS (expr) = 1;
-  do_pending_stack_adjust ();
-  start_sequence_for_rtl_expr (expr);
+  expand_start_all_catch ();
+  expand_start_catch_block (NULL_TREE, NULL_TREE);
 
-  cont = gen_label_rtx ();
-  emit_move_insn (ret, gen_rtx (LABEL_REF, Pmode, cont));
-  emit_jump (check);
-  emit_label (cont);
-  jumpif (make_tree (integer_type_node, flag), end);
-  expand_eh_region_start ();
-  do_function_call (Unexpected, NULL_TREE, NULL_TREE);
-  assemble_external (TREE_OPERAND (Unexpected, 0));
-  emit_barrier ();
+  /* Build up an array of type_infos.  */
+  for (; raises && TREE_VALUE (raises); raises = TREE_CHAIN (raises))
+    {
+      types = expr_tree_cons
+       (NULL_TREE, build_eh_type_type (TREE_VALUE (raises)), types);
+      ++count;
+    }
 
-  expand_eh_region_end (second_try);
-  
-  emit_label (check);
-  emit_move_insn (flag, const1_rtx);
-  cont = gen_label_rtx ();
+  types = build_nt (CONSTRUCTOR, NULL_TREE, types);
+  TREE_HAS_CONSTRUCTOR (types) = 1;
 
-  push_eh_info ();
+  /* We can't pass the CONSTRUCTOR directly, so stick it in a variable.  */
+  tmp = build_array_type (const_ptr_type_node, NULL_TREE);
+  decl = build_decl (VAR_DECL, NULL_TREE, tmp);
+  DECL_ARTIFICIAL (decl) = 1;
+  DECL_INITIAL (decl) = types;
+  cp_finish_decl (decl, types, NULL_TREE, 0, 0);
+
+  decl = decay_conversion (decl);
 
-  while (raises)
+  fn = get_identifier ("__check_eh_spec");
+  if (IDENTIFIER_GLOBAL_VALUE (fn))
+    fn = IDENTIFIER_GLOBAL_VALUE (fn);
+  else
     {
-      tree exp;
-      tree match_type = TREE_VALUE (raises);
-      
-      if (match_type)
-       {
-         /* check TREE_VALUE (raises) here */
-         exp = get_eh_value ();
-         exp = expr_tree_cons (NULL_TREE,
-                          build_eh_type_type (match_type),
-                          expr_tree_cons (NULL_TREE,
-                                     get_eh_type (),
-                                     expr_tree_cons (NULL_TREE, exp, NULL_TREE)));
-         exp = build_function_call (CatchMatch, exp);
-         assemble_external (TREE_OPERAND (CatchMatch, 0));
-
-         jumpif (exp, cont);
-       }
+      push_obstacks_nochange ();
+      end_temporary_allocation ();
 
-      raises = TREE_CHAIN (raises);
-    }
-  emit_move_insn (flag, const0_rtx);
-  emit_label (cont);
-  emit_indirect_jump (ret);
-  emit_label (end);
-  
-  do_pending_stack_adjust ();
-  RTL_EXPR_SEQUENCE (expr) = get_insns ();
-  end_sequence ();
+      tmp = tree_cons
+       (NULL_TREE, integer_type_node, tree_cons
+        (NULL_TREE, TREE_TYPE (decl), void_list_node));
+      tmp = build_function_type        (void_type_node, tmp);
   
-  expand_eh_region_end (expr);
+      fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
+      DECL_EXTERNAL (fn) = 1;
+      TREE_PUBLIC (fn) = 1;
+      DECL_ARTIFICIAL (fn) = 1;
+      TREE_THIS_VOLATILE (fn) = 1;
+      pushdecl_top_level (fn);
+      make_function_rtl (fn);
+      assemble_external (fn);
+      pop_obstacks ();
+    }
+
+  tmp = expr_tree_cons (NULL_TREE, build_int_2 (count, 0), expr_tree_cons
+                       (NULL_TREE, decl, NULL_TREE));
+  tmp = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), tmp);
+  expand_expr (tmp, const0_rtx, VOIDmode, EXPAND_NORMAL);
+
+  expand_end_catch_block ();
+  expand_end_all_catch ();
 }
 
 /* This is called to expand all the toplevel exception handling
index 2d1ae08..2807118 100644 (file)
@@ -47,7 +47,8 @@ __default_unexpected ()
   terminate ();
 }
 
-static unexpected_handler __unexpected_func = __default_unexpected;
+static unexpected_handler __unexpected_func __attribute__((__noreturn__))
+  = __default_unexpected;
 
 terminate_handler
 set_terminate (terminate_handler func)
@@ -159,6 +160,54 @@ __uncatch_exception (void)
   /* otherwise __throw will call terminate(); don't crash here.  */
 }
 
+/* As per [except.unexpected]:
+   If an exception is thrown, we check it against the spec.  If it doesn't
+   match, we call unexpected ().  If unexpected () throws, we check that
+   exception against the spec.  If it doesn't match, if the spec allows
+   bad_exception we throw that; otherwise we call terminate ().
+
+   The compiler treats an exception spec as a try block with a generic
+   handler that just calls this function with a list of the allowed
+   exception types, so we have an active exception that can be rethrown.
+
+   This function does not return.  */   
+
+extern "C" void
+__check_eh_spec (int n, const void **spec)
+{
+  cp_eh_info *p = __cp_exception_info ();
+
+  for (int i = 0; i < n; ++i)
+    {
+      if (__throw_type_match_rtti (spec[i], p->type, p->value))
+       throw;
+    }
+
+  try
+    {
+      unexpected ();
+    }
+  catch (...)
+    {
+      // __exception_info is an artificial var pushed into each catch block.
+      p = __exception_info;
+      for (int i = 0; i < n; ++i)
+       {
+         if (__throw_type_match_rtti (spec[i], p->type, p->value))
+           throw;
+       }
+
+      const type_info &bad_exc = typeid (bad_exception);
+      for (int i = 0; i < n; ++i)
+       {
+         if (__throw_type_match_rtti (spec[i], &bad_exc, p->value))
+           throw bad_exception ();
+       }
+
+      terminate ();
+    }
+}
+
 extern "C" void
 __throw_bad_cast (void)
 {
index d38806b..3e66bee 100644 (file)
@@ -29,9 +29,9 @@ typedef void (*terminate_handler) ();
 typedef void (*unexpected_handler) ();
 
 terminate_handler set_terminate (terminate_handler);
-void terminate (void);
+void terminate (void) __attribute__ ((__noreturn__));
 unexpected_handler set_unexpected (unexpected_handler);
-void unexpected (void);
+void unexpected (void) __attribute__ ((__noreturn__));
 bool uncaught_exception ();
 } // extern "C++"
 
index 128661c..5313488 100644 (file)
@@ -119,7 +119,8 @@ struct __array_type_info : public type_info {
    variables and thrown objects.  */
 
 extern "C" void*
-__throw_type_match_rtti (void *catch_type_r, void *throw_type_r, void *objptr)
+__throw_type_match_rtti (const void *catch_type_r, const void *throw_type_r,
+                        void *objptr)
 {
   const type_info &catch_type = *(const type_info *)catch_type_r;
   const type_info &throw_type = *(const type_info *)throw_type_r;