cp-tree.h (build_java_class_ref): Declare.
authorTom Tromey <tromey@cygnus.com>
Thu, 2 Mar 2000 19:58:49 +0000 (19:58 +0000)
committerTom Tromey <tromey@gcc.gnu.org>
Thu, 2 Mar 2000 19:58:49 +0000 (19:58 +0000)
* cp-tree.h (build_java_class_ref): Declare.
* init.c (build_java_class_ref): No longer static.
* except.c (expand_throw): Generate a Java-style `throw' if the
thrown object is a "Java" object.
(initialize_handler_parm): Generate a Java-style lookup of
exception info if the caught object is a "Java" object.
(catch_language, catch_language_init): New globals.
(decl_is_java_type): New function.
(expand_start_catch_block): Don't call push_eh_info() or
push_eh_cleanup() when handling a Java-style "catch".  Pass Java
class reference to build_catch_block.

From-SVN: r32292

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/except.c
gcc/cp/init.c

index d7e697a..2e33286 100644 (file)
@@ -1,3 +1,17 @@
+2000-03-02  Tom Tromey  <tromey@cygnus.com>
+
+       * cp-tree.h (build_java_class_ref): Declare.
+       * init.c (build_java_class_ref): No longer static.
+       * except.c (expand_throw): Generate a Java-style `throw' if the
+       thrown object is a "Java" object.
+       (initialize_handler_parm): Generate a Java-style lookup of
+       exception info if the caught object is a "Java" object.
+       (catch_language, catch_language_init): New globals.
+       (decl_is_java_type): New function.
+       (expand_start_catch_block): Don't call push_eh_info() or
+       push_eh_cleanup() when handling a Java-style "catch".  Pass Java
+       class reference to build_catch_block.
+
 Thu Mar  2 13:32:01 2000  Richard Kenner  <kenner@vlsi1.ultra.nyu.edu>
 
        * typeck.c (comptypes): Treat sizetype like its language equivalent.
index 4af1704..3c46940 100644 (file)
@@ -3932,6 +3932,7 @@ extern tree create_temporary_var                PARAMS ((tree));
 extern void begin_init_stmts                    PARAMS ((tree *, tree *));
 extern tree finish_init_stmts                   PARAMS ((tree, tree));
 extern void initialize_vtbl_ptrs                PARAMS ((tree, tree));
+extern tree build_java_class_ref                PARAMS ((tree));
 
 /* in input.c */
 
index 5c5e508..81c4e0f 100644 (file)
@@ -55,6 +55,7 @@ static tree alloc_eh_object PARAMS ((tree));
 static int complete_ptr_ref_or_void_ptr_p PARAMS ((tree, tree));
 static void initialize_handler_parm PARAMS ((tree));
 static tree expand_throw PARAMS ((tree));
+static int decl_is_java_type PARAMS ((tree decl, int err));
 
 #if 0
 /* This is the startup, and finish stuff per exception table.  */
@@ -92,6 +93,14 @@ asm (TEXT_SECTION_ASM_OP);
 #include "insn-flags.h"
 #include "obstack.h"
 
+/* In a given translation unit we are constrained to catch only C++
+   types or only Java types.  `catch_language' holds the current type,
+   and `catch_language_init' registers whether `catch_language' has
+   been set.  */
+
+static int catch_language_init = 0;
+static int catch_language;
+
 /* ======================================================================
    Briefly the algorithm works like this:
 
@@ -450,6 +459,49 @@ build_terminate_handler ()
   return build_function_call (terminate_node, NULL_TREE);
 }
 
+/* Return nonzero value if DECL is a Java type suitable for catch or
+   throw.  */
+
+static int
+decl_is_java_type (decl, err)
+     tree decl;
+     int err;
+{
+  int r = (TREE_CODE (decl) == POINTER_TYPE
+          && TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE
+          && TYPE_FOR_JAVA (TREE_TYPE (decl)));
+
+  if (err)
+    {
+      if (TREE_CODE (decl) == REFERENCE_TYPE
+         && TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE
+         && TYPE_FOR_JAVA (TREE_TYPE (decl)))
+       {
+         /* Can't throw a reference.  */
+         cp_error ("type `%T' is disallowed in Java `throw' or `catch'",
+                   decl);
+       }
+
+      if (r)
+       {
+         tree jthrow_node
+           = IDENTIFIER_GLOBAL_VALUE (get_identifier ("jthrowable"));
+         if (jthrow_node == NULL_TREE)
+           fatal ("call to Java `catch' or `throw', while `jthrowable' undefined");
+         jthrow_node = TREE_TYPE (TREE_TYPE (jthrow_node));
+
+         if (! DERIVED_FROM_P (jthrow_node, TREE_TYPE (decl)))
+           {
+             /* Thrown object must be a Throwable.  */
+             cp_error ("type `%T' is not derived from `java::lang::Throwable'",
+                       TREE_TYPE (decl));
+           }
+       }
+    }
+
+  return r;
+}
+
 /* Initialize the catch parameter DECL.  */
 
 static void 
@@ -459,6 +511,7 @@ initialize_handler_parm (decl)
   tree exp;
   tree init;
   tree init_type;
+  int lang;
 
   /* Make sure we mark the catch param as used, otherwise we'll get a
      warning about an unused ((anonymous)).  */
@@ -470,7 +523,42 @@ initialize_handler_parm (decl)
       && TREE_CODE (init_type) != POINTER_TYPE)
     init_type = build_reference_type (init_type);
 
-  exp = get_eh_value ();
+  if (decl_is_java_type (init_type, 0))
+    {
+      tree fn
+       = builtin_function ("_Jv_exception_info", 
+                           build_function_type (ptr_type_node,
+                                                tree_cons (NULL_TREE,
+                                                           void_type_node,
+                                                           NULL_TREE)),
+                           0, NOT_BUILT_IN, NULL_PTR);
+
+      exp = build (CALL_EXPR, ptr_type_node,
+                  build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)),
+                          fn),
+                  NULL_TREE, NULL_TREE);
+      TREE_SIDE_EFFECTS (exp) = 1;
+      lang = EH_LANG_Java;
+
+      set_exception_lang_code (EH_LANG_Java);
+      set_exception_version_code (1);
+    }
+  else
+    {
+      exp = get_eh_value ();
+      lang = EH_LANG_C_plus_plus;
+    }
+
+  if (catch_language_init)
+    {
+      if (lang != catch_language)
+       error ("mixing C++ and Java `catch'es in single translation unit");
+    }
+  else
+    {
+      catch_language_init = 1;
+      catch_language = lang;
+    }
 
   /* Since pointers are passed by value, initialize a reference to
      pointer catch parm with the address of the value slot.  */ 
@@ -524,14 +612,27 @@ expand_start_catch_block (decl)
      cleanup.  */
   compound_stmt_1 = begin_compound_stmt (/*has_no_scope=*/0);
 
-  if (decl)
-    type = build_eh_type_type_ref (TREE_TYPE (decl));
-  else
-    type = NULL_TREE;
-  begin_catch_block (type);
+  if (! decl || ! decl_is_java_type (TREE_TYPE (decl), 1))
+    {
+      /* The ordinary C++ case.  */
+
+      if (decl)
+       type = build_eh_type_type_ref (TREE_TYPE (decl));
+      else
+       type = NULL_TREE;
+      begin_catch_block (type);
 
-  push_eh_info ();
-  push_eh_cleanup ();
+      push_eh_info ();
+      push_eh_cleanup ();
+    }
+  else
+    {
+      /* The Java case.  In this case, the match_info is a pointer to
+        the Java class object.  We assume that the class is a
+        compiled class.  */
+      tree ref = build_java_class_ref (TREE_TYPE (TREE_TYPE (decl)));
+      begin_catch_block (build1 (ADDR_EXPR, jclass_node, ref));
+    }
 
   /* Create a binding level for the parm.  */
   compound_stmt_2 = begin_compound_stmt (/*has_no_scope=*/0);
@@ -734,7 +835,35 @@ expand_throw (exp)
   if (! doing_eh (1))
     return error_mark_node;
 
-  if (exp)
+  if (exp
+      && decl_is_java_type (TREE_TYPE (exp), 1))
+    {
+      /* A Java `throw' statement.  */
+      tree args = tree_cons (NULL_TREE, exp, NULL);
+
+      fn = get_identifier (exceptions_via_longjmp
+                          ? "_Jv_Sjlj_throw"
+                          : "_Jv_Throw");
+      if (IDENTIFIER_GLOBAL_VALUE (fn))
+       fn = IDENTIFIER_GLOBAL_VALUE (fn);
+      else
+       {
+         /* Declare _Jv_Throw (void *), as defined in Java's
+            exception.cc.  */
+         tree tmp;
+         tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
+         fn = build_lang_decl (FUNCTION_DECL, fn,
+                               build_function_type (ptr_type_node, tmp));
+         DECL_EXTERNAL (fn) = 1;
+         TREE_PUBLIC (fn) = 1;
+         DECL_ARTIFICIAL (fn) = 1;
+         pushdecl_top_level (fn);
+         make_function_rtl (fn);
+       }
+
+      exp = build_function_call (fn, args);
+    }
+  else if (exp)
     {
       tree throw_type;
       tree cleanup = NULL_TREE, e;
index b559054..e9f02d8 100644 (file)
@@ -46,7 +46,6 @@ static int member_init_ok_or_else PARAMS ((tree, tree, const char *));
 static void expand_virtual_init PARAMS ((tree, tree));
 static tree sort_member_init PARAMS ((tree));
 static tree initializing_context PARAMS ((tree));
-static tree build_java_class_ref PARAMS ((tree));
 static void expand_cleanup_for_base PARAMS ((tree, tree));
 static tree get_temp_regvar PARAMS ((tree, tree));
 static tree dfs_initialize_vtbl_ptrs PARAMS ((tree, void *));
@@ -2071,7 +2070,7 @@ build_new (placement, decl, init, use_global_new)
 
 /* Given a Java class, return a decl for the corresponding java.lang.Class. */
 
-static tree
+tree
 build_java_class_ref (type)
      tree type;
 {