decl.c (runtime_exception_type_node, [...]): New global variables.
authorAlexandre Petit-Bianco <apbianco@cygnus.com>
Wed, 14 Oct 1998 15:11:04 +0000 (15:11 +0000)
committerAlexandre Petit-Bianco <apbianco@gcc.gnu.org>
Wed, 14 Oct 1998 15:11:04 +0000 (08:11 -0700)
Tue Oct 13 03:50:28 1998  Alexandre Petit-Bianco  <apbianco@cygnus.com>
* decl.c (runtime_exception_type_node, error_exception_type_node):
  New global variables.
(init_decl_processing): Initialized.
* expr.c (java_lang_expand_expr): Set caught exception type to
  null if catch handler argument doesn't exit.
* java-tree.def (SYNCHRONIZED_EXPR, THROW_EXPR): New Java specific
  tree codes.
* java-tree.h (runtime_exception_type_node,
  error_exception_type_node): Global variables declared.
(DECL_FUNCTION_THROWS): New macro.
(DECL_FUNCTION_BODY): Modified comment.
(DECL_SPECIFIC_COUNT): Likewise.
(struct lang_decl): New field throws_list.
(IS_UNCHECKED_EXPRESSION_P): New macro.
* lex.c (java_lex): Generate location information for THROW_TK.
* parse.h (PUSH_EXCEPTIONS, POP_EXCEPTIONS, IN_TRY_BLOCK_P,
  EXCEPTIONS_P): New macros.
(enum jdep_code): New value JDEP_EXCEPTION.
(BUILD_MONITOR_ENTER, BUILD_MONITOR_EXIT,
  BUILD_ASSIGN_EXCEPTION_INFO, BUILD_THROW, SET_WFL_OPERATOR,
  PATCH_METHOD_RETURN_ERROR): New macros.
(patch_method_invocation_stmt): Added new argument to prototype.
(patch_synchronized_statement, patch_throw_statement,
  check_thrown_exceptions, check_thrown_exceptions_do,
  purge_unchecked_exceptions, check_throws_clauses): New function
  prototypes.
* parse.y Fixed typo in keyword section.
(throw:): Rule tagged <node>.
(THROW_TK): Keyword tagged <operator>.
(method_header:): Last argument to call to method_header passed
  from throws: rule.
(throws:, class_type_list:, throw_statement:,
  synchronized_statement:, synchronized:): Defined actions.
(method_header): New local variable current. Register exceptions
  from throws clause.
(java_complete_tree): Complete and verify exceptions from throws
  clause.
(complete_class_report_errors): Error message on exceptions not
  found
(java_check_regular_methods): Fixed typo. Shortcut on private
  overriding methods. Changed error message on method
  redefinition. Check for throws clause compatibility.
(check_throws_clauses): New function.
(java_check_abstract_methods): Use DECL_NAME for wfl or current
  method. Changed error message on method redefinition.
(currently_caught_type_list): New static variable.
(java_complete_expand_methods): Purge unchecked exceptions from
  throws clause list. Call PUSH_EXCEPTIONS before walk and
  POP_EXCEPTIONS after.
(resolve_qualified_expression_name): Pass new argument as NULL to
  patch_method_invocation_stmt.
(patch_method_invocation_stmt): New argument ref_decl. Invoke
  PATCH_METHOD_RETURN_ERROR when returning with error. Reverse
  argument list when appropriate. Use new argument if non null to
  store selected method decl.
(patch_invoke): Convert if necessary args of builtin types before
  forming CALL_EXPR. Argument list no longer reversed here.
(invocation_mode): Treat final methods as static methods.
(java_complete_tree): New cases for THROW_EXPR: and
  SYNCHRONIZED_EXPR:. Check thrown exceptions when completing
  function call.
(complete_function_arguments): No more RECORD_TYPE
  conversion. Function parameter nodes no longer saved.
(valid_ref_assignconv_cast_p): Avoid handling null type.
(patch_binop): Fixed null constant reference handling.
(build_try_statement): Use BUILD_ASSIGN_EXCEPTION_INFO and
  BUILD_THROW macros.
(patch_try_statement): Fixed comments. Record caught types in
  list, push the list, expand try block and pop the list.
(patch_synchronized_statement, patch_throw_statement,
  check_thrown_exceptions, check_thrown_exceptions_do,
  purge_unchecked_exceptions): New functions.
* typeck.c (lookup_argument_method): Allow WFL in place of method
  DECL_NAME during method definition check
Implements the `synchronized' statement, the `throw' statements and
the `throws' clause. Fixes method invocation bugs.

From-SVN: r23087

gcc/java/ChangeLog
gcc/java/decl.c
gcc/java/expr.c
gcc/java/java-tree.def
gcc/java/java-tree.h
gcc/java/lex.c
gcc/java/parse.h
gcc/java/parse.y
gcc/java/typeck.c

index 3e496ae..64aa6e0 100644 (file)
@@ -47,6 +47,83 @@ Tue Oct 13 23:34:12 1998  Jeffrey A Law  (law@cygnus.com)
        (disassemble_method): Undefine RET to avoid clash with
        config/i386/i386.h.
 
+Tue Oct 13 03:50:28 1998  Alexandre Petit-Bianco  <apbianco@cygnus.com>
+
+       * decl.c (runtime_exception_type_node, error_exception_type_node):
+       New global variables.
+       (init_decl_processing): Initialized.
+       * expr.c (java_lang_expand_expr): Set caught exception type to
+       null if catch handler argument doesn't exit.
+       * java-tree.def (SYNCHRONIZED_EXPR, THROW_EXPR): New Java specific
+       tree codes.
+       * java-tree.h (runtime_exception_type_node,
+       error_exception_type_node): Global variables declared.
+       (DECL_FUNCTION_THROWS): New macro.
+       (DECL_FUNCTION_BODY): Modified comment.
+       (DECL_SPECIFIC_COUNT): Likewise.
+       (struct lang_decl): New field throws_list.
+       (IS_UNCHECKED_EXPRESSION_P): New macro.
+       * lex.c (java_lex): Generate location information for THROW_TK.
+       * parse.h (PUSH_EXCEPTIONS, POP_EXCEPTIONS, IN_TRY_BLOCK_P,
+       EXCEPTIONS_P): New macros.
+       (enum jdep_code): New value JDEP_EXCEPTION.
+       (BUILD_MONITOR_ENTER, BUILD_MONITOR_EXIT,
+       BUILD_ASSIGN_EXCEPTION_INFO, BUILD_THROW, SET_WFL_OPERATOR,
+       PATCH_METHOD_RETURN_ERROR): New macros.
+       (patch_method_invocation_stmt): Added new argument to prototype.
+       (patch_synchronized_statement, patch_throw_statement,
+       check_thrown_exceptions, check_thrown_exceptions_do,
+       purge_unchecked_exceptions, check_throws_clauses): New function
+       prototypes.
+       * parse.y Fixed typo in keyword section.
+       (throw:): Rule tagged <node>.
+       (THROW_TK): Keyword tagged <operator>.
+       (method_header:): Last argument to call to method_header passed
+       from throws: rule.
+       (throws:, class_type_list:, throw_statement:,
+       synchronized_statement:, synchronized:): Defined actions.
+       (method_header): New local variable current. Register exceptions
+       from throws clause.
+       (java_complete_tree): Complete and verify exceptions from throws
+       clause.
+       (complete_class_report_errors): Error message on exceptions not
+       found
+       (java_check_regular_methods): Fixed typo. Shortcut on private
+       overriding methods. Changed error message on method
+       redefinition. Check for throws clause compatibility.
+       (check_throws_clauses): New function.
+       (java_check_abstract_methods): Use DECL_NAME for wfl or current
+       method. Changed error message on method redefinition.
+       (currently_caught_type_list): New static variable.
+       (java_complete_expand_methods): Purge unchecked exceptions from
+       throws clause list. Call PUSH_EXCEPTIONS before walk and
+       POP_EXCEPTIONS after.
+       (resolve_qualified_expression_name): Pass new argument as NULL to
+       patch_method_invocation_stmt.
+       (patch_method_invocation_stmt): New argument ref_decl. Invoke
+       PATCH_METHOD_RETURN_ERROR when returning with error. Reverse
+       argument list when appropriate. Use new argument if non null to
+       store selected method decl.
+       (patch_invoke): Convert if necessary args of builtin types before
+       forming CALL_EXPR. Argument list no longer reversed here.
+       (invocation_mode): Treat final methods as static methods.
+       (java_complete_tree): New cases for THROW_EXPR: and
+       SYNCHRONIZED_EXPR:. Check thrown exceptions when completing
+       function call.
+       (complete_function_arguments): No more RECORD_TYPE
+       conversion. Function parameter nodes no longer saved.
+       (valid_ref_assignconv_cast_p): Avoid handling null type.
+       (patch_binop): Fixed null constant reference handling.
+       (build_try_statement): Use BUILD_ASSIGN_EXCEPTION_INFO and
+       BUILD_THROW macros.
+       (patch_try_statement): Fixed comments. Record caught types in
+       list, push the list, expand try block and pop the list.
+       (patch_synchronized_statement, patch_throw_statement,
+       check_thrown_exceptions, check_thrown_exceptions_do,
+       purge_unchecked_exceptions): New functions.
+       * typeck.c (lookup_argument_method): Allow WFL in place of method
+       DECL_NAME during method definition check
+       
 1998-10-09  Tom Tromey  <tromey@cygnus.com>
 
        * gjavah.c (decode_signature_piece): New function.
index 16dd234..4ec6639 100644 (file)
@@ -250,6 +250,8 @@ tree object_type_node;
 tree object_ptr_type_node;
 tree string_type_node;
 tree throwable_type_node;
+tree runtime_exception_type_node;
+tree error_exception_type_node;
 
 tree boolean_type_node;
 
@@ -518,6 +520,10 @@ init_decl_processing ()
   string_type_node = lookup_class (get_identifier ("java.lang.String"));
   class_type_node = lookup_class (get_identifier ("java.lang.Class"));
   throwable_type_node = lookup_class (get_identifier ("java.lang.Throwable"));
+  runtime_exception_type_node = 
+    lookup_class (get_identifier ("java.lang.RuntimeException"));
+  error_exception_type_node = 
+    lookup_class (get_identifier ("java.lang.Error"));
 
   methodtable_type = make_node (RECORD_TYPE);
   layout_type (methodtable_type);
index 8322d61..5759b6b 100644 (file)
@@ -1750,7 +1750,7 @@ java_lang_expand_expr (exp, target, tmode, modifier)
            {
              tree catch = java_get_catch_block (current, has_finally_p);
              tree decl = BLOCK_EXPR_DECLS (catch);
-             type = TREE_TYPE (TREE_TYPE (decl));
+             type = (decl ? TREE_TYPE (TREE_TYPE (decl)) : NULL_TREE);
            }
          start_catch_handler (prepare_eh_table_type (type));
          expand_expr_stmt (TREE_OPERAND (current, 0));
@@ -1772,7 +1772,8 @@ java_lang_expand_expr (exp, target, tmode, modifier)
       if (has_finally_p)
        {
          tree finally = TREE_OPERAND (exp, 2);
-         emit_label (label_rtx (FINALLY_EXPR_LABEL (finally)));
+         if (FINALLY_EXPR_LABEL (finally))
+           emit_label (label_rtx (FINALLY_EXPR_LABEL (finally)));
          expand_expr_stmt (FINALLY_EXPR_BLOCK (finally));
        }
       expand_end_all_catch ();
index db64229..bdaf300 100644 (file)
@@ -55,3 +55,12 @@ DEFTREECODE (CATCH_EXPR, "catch", '1', 1)
    Operand 0 is the finally label.
    Operand 1 is the finally block.  */
 DEFTREECODE (FINALLY_EXPR, "finally", 'e', 2) 
+
+/* Synchronized statement.
+   Operand 0 is the expression on which we whish to synchronize,
+   Operand 1 is the synchronized expression block.  */
+DEFTREECODE (SYNCHRONIZED_EXPR, "synchronized", 'e', 2)
+
+/* Throw statement.
+   Operand 0 is the throw expresion.  */
+DEFTREECODE (THROW_EXPR, "throw", '1', 1)
index 1cc5f46..926d7e3 100644 (file)
@@ -175,6 +175,8 @@ extern tree object_type_node;
 extern tree object_ptr_type_node;
 extern tree string_type_node;
 extern tree throwable_type_node;
+extern tree runtime_exception_type_node;
+extern tree error_exception_type_node;
 
 extern tree byte_array_type_node;
 extern tree short_array_type_node;
@@ -317,8 +319,14 @@ struct lang_identifier
 #define DECL_MAX_STACK(DECL) (DECL_LANG_SPECIFIC(DECL)->max_stack)
 /* Number of local variable slots needed for the arguments of this function. */
 #define DECL_ARG_SLOT_COUNT(DECL) (DECL_LANG_SPECIFIC(DECL)->arg_slot_count)
-/* Pointer to the function's COMPOUND_EXPR tree */
+/* List of checked thrown exceptions, as specified with the `throws'
+   keyword */
+#define DECL_FUNCTION_THROWS(DECL) (DECL_LANG_SPECIFIC(DECL)->throws_list)
+/* Pointer to the function's current's COMPOUND_EXPR tree (while
+   completing its body) or the function's block */
 #define DECL_FUNCTION_BODY(DECL) (DECL_LANG_SPECIFIC(DECL)->function_decl_body)
+/* How specific the function is (for method selection - Java source
+   code front-end */
 #define DECL_SPECIFIC_COUNT(DECL) DECL_ARG_SLOT_COUNT(DECL)
 
 /* In a LABEL_DECL, a TREE_VEC that saves the type_map at that point. */
@@ -391,6 +399,7 @@ struct lang_decl
   long localvariables_offset;
   int arg_slots;
   int max_locals, max_stack, arg_slot_count;
+  tree throws_list;            /* Exception specified by `throws' */
   tree function_decl_body;     /* Hold all function's statements */
 };
 
@@ -726,3 +735,8 @@ extern tree *type_map;
 
 /* Using a CATCH_EXPR node */
 #define CATCH_EXPR_GET_EXPR(NODE, V) (V ? LABELED_BLOCK_BODY (NODE) : (NODE))
+
+/* Non zero if TYPE is an unchecked expression */
+#define IS_UNCHECKED_EXPRESSION_P(TYPE)                                \
+  (inherits_from_p ((TYPE), runtime_exception_type_node)       \
+   || inherits_from_p ((TYPE), error_exception_type_node))
index a54688b..6ab4e4d 100644 (file)
@@ -1209,6 +1209,7 @@ java_lex (java_lval)
            case CONTINUE_TK:
            case TRY_TK:
            case CATCH_TK:
+           case THROW_TK:
              BUILD_OPERATOR (kw->token);
 
            default:
index 1e78e32..09d25ba 100644 (file)
@@ -262,6 +262,24 @@ extern tree stabilize_reference PROTO ((tree));
   }
 #define POP_LOOP() ctxp->current_loop = TREE_CHAIN (ctxp->current_loop)
 
+#define PUSH_EXCEPTIONS(E)                                     \
+  currently_caught_type_list =                                 \
+    tree_cons (NULL_TREE, (E), currently_caught_type_list);
+
+#define POP_EXCEPTIONS()                                               \
+  currently_caught_type_list = TREE_CHAIN (currently_caught_type_list)
+
+/* Check that we're inside a try block */
+#define IN_TRY_BLOCK_P()                               \
+  (currently_caught_type_list                          \
+   && ((TREE_VALUE (currently_caught_type_list) !=     \
+       DECL_FUNCTION_THROWS (current_function_decl))   \
+       || TREE_CHAIN (currently_caught_type_list)))
+
+/* Check that we have exceptions in E */
+#define EXCEPTIONS_P(E) ((E) ? TREE_VALUE (E) : NULL_TREE)
+
+
 /* Invocation modes, as returned by invocation_mode (). */
 enum {
   INVOKE_STATIC,
@@ -317,6 +335,7 @@ enum jdep_code {
   JDEP_TYPE,                   /* Patch a random tree node type,
                                    without the need for any specific
                                    actions */
+  JDEP_EXCEPTION,              /* Patch exceptions specified by `throws' */
 };
 
 typedef struct _jdep {
@@ -431,6 +450,51 @@ static jdeplist *reverse_jdep_list ();
   build_new_invocation (wfl_string_buffer,                                   \
                        (ARG ? build_tree_list (NULL, (ARG)) : NULL_TREE))
 
+/* For exception handling, build diverse function calls */
+#define BUILD_MONITOR_ENTER(WHERE, ARG)                                \
+  {                                                            \
+    (WHERE) = build (CALL_EXPR, int_type_node,                 \
+                    build_address_of (soft_monitorenter_node), \
+                    build_tree_list (NULL_TREE, (ARG)));       \
+    TREE_SIDE_EFFECTS (WHERE) = 1;                             \
+  }
+
+#define BUILD_MONITOR_EXIT(WHERE, ARG)                         \
+  {                                                            \
+    (WHERE) = build (CALL_EXPR, int_type_node,                 \
+                    build_address_of (soft_monitorexit_node),  \
+                    build_tree_list (NULL_TREE, (ARG)));       \
+    TREE_SIDE_EFFECTS (WHERE) = 1;                             \
+  }
+
+#define BUILD_ASSIGN_EXCEPTION_INFO(WHERE, TO)         \
+  {                                                    \
+    (WHERE) = build (MODIFY_EXPR, void_type_node, (TO),        \
+                    soft_exceptioninfo_call_node);     \
+    TREE_SIDE_EFFECTS (WHERE) = 1;                     \
+  }
+
+#define BUILD_THROW(WHERE, WHAT)                                       \
+  {                                                                    \
+    (WHERE) = build (CALL_EXPR, void_type_node,                                \
+                 build_address_of (throw_node),                        \
+                 build_tree_list (NULL_TREE, (WHAT)), NULL_TREE);      \
+    TREE_SIDE_EFFECTS ((WHERE)) = 1;                                   \
+  }
+
+/* Set wfl_operator for the most accurate error location */
+#define SET_WFL_OPERATOR(WHICH, NODE, WFL)             \
+  EXPR_WFL_LINECOL (WHICH) =                           \
+    (TREE_CODE (WFL) == EXPR_WITH_FILE_LOCATION ?      \
+     EXPR_WFL_LINECOL (WFL) : EXPR_WFL_LINECOL (NODE))
+
+#define PATCH_METHOD_RETURN_ERROR()            \
+  {                                            \
+    if (ret_decl)                              \
+      *ret_decl = NULL_TREE;                   \
+    return error_mark_node;                    \
+  }
+     
 /* Parser context data structure. */
 struct parser_ctxt {
 
@@ -527,7 +591,7 @@ static tree lookup_java_interface_method2 PROTO ((tree, tree));
 static tree resolve_expression_name PROTO ((tree));
 static tree maybe_create_class_interface_decl PROTO ((tree, tree, tree));
 static int check_class_interface_creation PROTO ((int, int, tree, tree, tree, tree));
-static tree patch_method_invocation_stmt PROTO ((tree, tree, tree, int *));
+static tree patch_method_invocation_stmt PROTO ((tree, tree, tree, int *, tree *));
 static int breakdown_qualified PROTO ((tree *, tree *, tree));
 static tree resolve_and_layout PROTO ((tree, tree));
 static tree resolve_no_layout PROTO ((tree, tree));
@@ -613,6 +677,12 @@ static tree patch_string PROTO ((tree));
 static tree build_jump_to_finally PROTO ((tree, tree, tree, tree));
 static tree build_try_statement PROTO ((int, tree, tree, tree));
 static tree patch_try_statement PROTO ((tree));
+static tree patch_synchronized_statement PROTO ((tree, tree));
+static tree patch_throw_statement PROTO ((tree, tree));
+static void check_thrown_exceptions PROTO ((int, tree));
+static int check_thrown_exceptions_do PROTO ((int, tree));
+static void purge_unchecked_exceptions PROTO ((tree));
+static void check_throws_clauses PROTO ((tree, tree, tree));
 
 void safe_layout_class PROTO ((tree));
 void java_complete_class PROTO ((void));
index 9dd9e58..ebca948 100644 (file)
@@ -195,7 +195,7 @@ static tree wfl_to_string = NULL_TREE;
 %type   <node>         class_body_declarations
 %type    <node>                class_or_interface_type class_type class_type_list
                        constructor_declarator explicit_constructor_invocation
-%type    <node>         dim_expr dim_exprs this_or_super
+%type    <node>         dim_expr dim_exprs this_or_super throws
 
 %type   <node>         variable_declarator_id variable_declarator
                        variable_declarators variable_initializer
@@ -245,8 +245,9 @@ static tree wfl_to_string = NULL_TREE;
 %token   <operator>     BOOL_AND_TK AND_TK BOOL_OR_TK OR_TK INCR_TK PLUS_TK
 %token   <operator>     DECR_TK MINUS_TK MULT_TK DIV_TK XOR_TK REM_TK NEQ_TK
 %token   <operator>     NEG_TK REL_QM_TK REL_CL_TK NOT_TK LT_TK
-%token   <operator>     OP_TK OSB_TK DOT_TK
-%type    <operator>    THIS_TK SUPER_TK RETURN_TK BREAK_TK CONTINUE_TK CASE_TK%type    <operator>     DEFAULT_TK TRY_TK CATCH_TK
+%token   <operator>     OP_TK OSB_TK DOT_TK THROW_TK
+%type    <operator>    THIS_TK SUPER_TK RETURN_TK BREAK_TK CONTINUE_TK 
+%type   <operator>     CASE_TK DEFAULT_TK TRY_TK CATCH_TK SYNCHRONIZED_TK
 
 %type   <node>         method_body 
        
@@ -661,13 +662,13 @@ method_declaration:
 
 method_header: 
        type method_declarator throws
-               { $$ = method_header (0, $1, $2, NULL); }
+               { $$ = method_header (0, $1, $2, $3); }
 |      VOID_TK method_declarator throws
-               { $$ = method_header (0, void_type_node, $2, NULL); }
+               { $$ = method_header (0, void_type_node, $2, $3); }
 |      modifiers type method_declarator throws
-               { $$ = method_header ($1, $2, $3, NULL); }
+               { $$ = method_header ($1, $2, $3, $4); }
 |      modifiers VOID_TK method_declarator throws
-               { $$ = method_header ($1, void_type_node, $3, NULL); }
+               { $$ = method_header ($1, void_type_node, $3, $4); }
 |      type error
                {RECOVER;}
 |      modifiers type error
@@ -730,14 +731,18 @@ formal_parameter:
 ;
 
 throws:
+               { $$ = NULL_TREE; }
 |      THROWS_TK class_type_list
+               { $$ = $2; }
 |      THROWS_TK error
                {yyerror ("Missing class type term"); RECOVER;}
 ;
 
 class_type_list:
        class_type
+               { $$ = build_tree_list (NULL_TREE, $1); }
 |      class_type_list C_TK class_type
+               { $$ = tree_cons (NULL_TREE, $3, $1); }
 |      class_type_list C_TK error
                {yyerror ("Missing class type term"); RECOVER;}
 ;
@@ -1395,7 +1400,10 @@ return_statement:
 
 throw_statement:
        THROW_TK expression SC_TK
-               { $$ = NULL_TREE;               /* FIXME */ }
+               { 
+                 $$ = build1 (THROW_EXPR, NULL_TREE, $2);
+                 EXPR_WFL_LINECOL ($$) = $1.location;
+               }
 |      THROW_TK error
                {yyerror ("Missing term"); RECOVER;}
 |      THROW_TK expression error
@@ -1404,7 +1412,11 @@ throw_statement:
 
 synchronized_statement:
        synchronized OP_TK expression CP_TK block
-               { $$ = NULL_TREE;               /* FIXME */ }
+               { 
+                 $$ = build (SYNCHRONIZED_EXPR, NULL_TREE, $3, $5);
+                 EXPR_WFL_LINECOL ($$) = 
+                   EXPR_WFL_LINECOL (MODIFIER_WFL (SYNCHRONIZED_TK));
+               }
 |      synchronized OP_TK expression CP_TK error
                {yyerror ("'{' expected"); RECOVER;}
 |      synchronized error
@@ -1415,10 +1427,11 @@ synchronized_statement:
                {yyerror ("Missing term"); RECOVER;}
 ;
 
-synchronized:                  /* Test lval.sub_token here */
+synchronized:
        MODIFIER_TK
                {
-                 SOURCE_FRONTEND_DEBUG (("Modifiers: %d", $1));
+                 if ((1 << $1) != ACC_SYNCHRONIZED)
+                   fatal ("synchronized was '%d' - yyparse", (1 << $1));
                }
 ;
 
@@ -2852,7 +2865,7 @@ method_header (flags, type, mdecl, throws)
   tree id = TREE_PURPOSE (mdecl);
   tree this_class = TREE_TYPE (ctxp->current_parsed_class);
   tree handle_class = CLASS_TO_HANDLE_TYPE (this_class);
-  tree meth_name, returned_type;
+  tree meth_name, returned_type, current;
   int saved_lineno;
   
   check_modifiers_consistency (flags);
@@ -2957,6 +2970,24 @@ method_header (flags, type, mdecl, throws)
     }
   DECL_MAX_LOCALS (meth) = ctxp->formal_parameter_number+1;
   lineno = saved_lineno;
+
+  /* Register exception specified by the `throws' keyword for
+     resolution and set the method decl appropriate field to the list.
+     Note: the grammar ensures that what we get here are class
+     types. */
+  if (throws)
+    {
+      throws = nreverse (throws);
+      for (current = throws; current; current = TREE_CHAIN (current))
+       {
+         register_incomplete_type (JDEP_EXCEPTION, TREE_VALUE (current),
+                                   NULL_TREE, NULL_TREE);
+         JDEP_GET_PATCH (CLASSD_LAST (ctxp->classd_list)) = 
+           &TREE_VALUE (current);
+       }
+      DECL_FUNCTION_THROWS (meth) = throws;
+    }
+
   /* We set the DECL_NAME to ID so we can track the location where
      the function was declared. This allow us to report
      redefinition error accurately. When method are verified,
@@ -3456,6 +3487,24 @@ java_complete_class ()
                  tree_code_name [TREE_CODE (JDEP_DECL (dep))]));
              break;
 
+           case JDEP_EXCEPTION:
+             /* Check for righteous inheritance here */
+             if (!inherits_from_p (TREE_TYPE (decl), throwable_type_node))
+                {
+                  parse_error_context 
+                    (JDEP_WFL (dep), "Class `%s' in `throws' clause must be "
+                     "a subclass of class `java.lang.Throwable'",
+                     IDENTIFIER_POINTER (EXPR_WFL_NODE (JDEP_WFL (dep))));
+                }
+             else 
+               {
+                 JDEP_APPLY_PATCH (dep, TREE_TYPE (decl));
+                 SOURCE_FRONTEND_DEBUG 
+                   (("Completing `%s' `throws' argument node",
+                     IDENTIFIER_POINTER (EXPR_WFL_NODE (JDEP_WFL (dep)))));
+               }
+             break;
+
            default:
              fatal ("incomplete switch - java_complete_class");
            }
@@ -3664,6 +3713,11 @@ complete_class_report_errors (dep)
                           (EXPR_WFL_NODE (JDEP_WFL (dep)))),
         IDENTIFIER_POINTER (DECL_NAME (JDEP_DECL (dep))));
       break;
+    case JDEP_EXCEPTION:       /* As specified by `throws' */
+      parse_error_context 
+         (JDEP_WFL (dep), "Class `%s' not found in `throws'",
+        IDENTIFIER_POINTER (EXPR_WFL_NODE (JDEP_WFL (dep))));
+      break;
     }
 }
 
@@ -3731,7 +3785,7 @@ java_check_regular_methods (class_decl)
       tree method_wfl = DECL_NAME (method);
       int aflags;
 
-      if (DECL_CONSTRUCTOR_P (method))
+     if (DECL_CONSTRUCTOR_P (method))
        seen_constructor = 1;
 
       /* Check for redefinitions */
@@ -3741,16 +3795,24 @@ java_check_regular_methods (class_decl)
       sig = build_java_argument_signature (TREE_TYPE (method));
 
       found = lookup_argument_method (super_class, DECL_NAME (method), sig);
-      if (! found)
+
+      /* Nothing overrides or it's a private method */
+      if (!found || (found && METHOD_PRIVATE (found)))
         continue;
       /* Can't override a method with the same name and different return
         types. */
       if (TREE_TYPE (TREE_TYPE (found)) != TREE_TYPE (TREE_TYPE (method)))
-       parse_warning_context 
-         (method_wfl,
-          "Method `%s' redefined with different return type in class `%s'",
-          lang_printable_name (found),
-          IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (DECL_CONTEXT (found)))));
+       {
+         char *t = strdup ((char *)lang_printable_name (TREE_TYPE 
+                                                        (TREE_TYPE (found))));
+         parse_error_context 
+           (method_wfl, 
+            "Method `%s' was defined with return type `%s' in class `%s'", 
+            lang_printable_name (found), t,
+            IDENTIFIER_POINTER 
+              (DECL_NAME (TYPE_NAME (DECL_CONTEXT (found)))));
+         free (t);
+       }
 
       /* Can't override final. Can't override static. */
       if (METHOD_FINAL (found) || METHOD_STATIC (found))
@@ -3796,9 +3858,13 @@ java_check_regular_methods (class_decl)
          continue;
        }
 
+      /* Overriding methods must have compatible `throws' clauses on checked
+        exceptions, if any */
+      check_throws_clauses (method, method_wfl, found);
+
       /* If the method has default access in an other package, then
-      issue a warning that the current method doesn't override the one
-      that was found elsewhere */
+        issue a warning that the current method doesn't override the
+        one that was found elsewhere */
       aflags = get_access_flags_from_decl (found);
       if ((!aflags || (aflags > ACC_PROTECTED))
          && !class_in_current_package (DECL_CONTEXT (found)))
@@ -3832,6 +3898,40 @@ java_check_regular_methods (class_decl)
     }
 }
 
+/* Return a non zero value if the `throws' clause of METHOD (if any)
+   is incompatible with the `throws' clause of FOUND (if any).  */
+
+static void
+check_throws_clauses (method, method_wfl, found)
+     tree method, method_wfl, found;
+{
+  tree mthrows, fthrows;
+
+  for (mthrows = DECL_FUNCTION_THROWS (method);
+       mthrows; mthrows = TREE_CHAIN (mthrows))
+    {
+      /* We don't verify unchecked expressions */
+      if (IS_UNCHECKED_EXPRESSION_P (TREE_VALUE (mthrows)))
+       continue;
+      /* Checked expression must be compatible */
+      for (fthrows = DECL_FUNCTION_THROWS (found); 
+          fthrows; fthrows = TREE_CHAIN (fthrows))
+       if (inherits_from_p (TREE_VALUE (mthrows), TREE_VALUE (fthrows)))
+         break;
+      if (!fthrows)
+       {
+         parse_error_context 
+           (method_wfl, "Invalid checked exception class `%s' in "
+            "`throws' clause. The exception must be a subclass of an "
+            "exception thrown by `%s' from class `%s'",
+            IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (TREE_VALUE (mthrows)))),
+            lang_printable_name (found),
+            IDENTIFIER_POINTER 
+              (DECL_NAME (TYPE_NAME (DECL_CONTEXT (found)))));
+       }
+    }
+}
+
 /* Check abstract method of interface INTERFACE */
 
 static void
@@ -3844,24 +3944,26 @@ java_check_abstract_methods (interface)
   for (method = TYPE_METHODS (interface); method; method = TREE_CHAIN (method))
     {
       char *csig;
-      tree name = DECL_NAME (method);
+      tree method_wfl = DECL_NAME (method);
 
       /* 2- Check for double definition inside the defining interface */
       if (check_method_redefinition (interface, method))
        continue;
 
       /* 3- Overriding is OK as far as we preserve the return type and
-        the thrown exceptions */
+        the thrown exceptions (FIXME) */
       found = lookup_java_interface_method2 (interface, method);
       if (found)
        {
+         char *t = strdup ((char *)lang_printable_name (TREE_TYPE 
+                                                        (TREE_TYPE (found))));
          parse_error_context 
-           (lookup_cl (method),
-            "Method `%s' previously defined in interface `%s' is "
-            "redefined with different return type in interface `%s'",
-            lang_printable_name (found),
-            IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (DECL_CONTEXT (found)))),
-            IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (interface))));
+           (method_wfl,
+            "Method `%s' was defined with return type `%s' in class `%s ",
+            lang_printable_name (found), t,
+            IDENTIFIER_POINTER 
+              (DECL_NAME (TYPE_NAME (DECL_CONTEXT (found)))));
+         free (t);
          continue;
        }
     }
@@ -4659,6 +4761,10 @@ java_complete_expand_methods ()
     }
 }
 
+/* Hold a list of catch clauses list. The first element of this list is
+   the list of the catch clauses of the currently analysed try block. */
+static tree currently_caught_type_list;
+
 /* Complete and expand a method.  */
 
 static void
@@ -4720,12 +4826,23 @@ java_complete_expand_method (mdecl)
        = (!METHOD_STATIC (mdecl) ? 
           BLOCK_EXPR_DECLS (DECL_FUNCTION_BODY (mdecl)) : NULL_TREE);
 
+      /* Purge the `throws' list of unchecked exceptions */
+      purge_unchecked_exceptions (mdecl);
+
+      /* Install exceptions thrown with `throws' */
+      PUSH_EXCEPTIONS (DECL_FUNCTION_THROWS (mdecl));
+
       if (BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (mdecl)) && no_ac_found)
        java_complete_tree (BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (mdecl)));
       /* Don't go any further if we've found error(s) during the
          expansion */
       if (!java_error_count)
        source_end_java_method ();
+
+      /* Pop the exceptions and sanity check */
+      POP_EXCEPTIONS();
+      if (currently_caught_type_list)
+       fatal ("Exception list non empty - java_complete_expand_method");
     }
 }
 
@@ -5007,7 +5124,8 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found)
          if (complete_function_arguments (qual_wfl))
            return 1;
          *where_found = 
-           patch_method_invocation_stmt (qual_wfl, decl, type, &is_static);
+           patch_method_invocation_stmt (qual_wfl, decl, type,
+                                         &is_static, NULL);
          if (*where_found == error_mark_node)
            return 1;
          *type_found = type = QUAL_DECL_TYPE (*where_found);
@@ -5352,9 +5470,10 @@ maybe_access_field (decl, where, type)
    used. IS_STATIC is set to 1 if the invoked function is static. */
 
 static tree
-patch_method_invocation_stmt (patch, primary, where, is_static)
+patch_method_invocation_stmt (patch, primary, where, is_static, ret_decl)
      tree patch, primary, where;
      int *is_static;
+     tree *ret_decl;
 {
   tree wfl = TREE_OPERAND (patch, 0);
   tree args = TREE_OPERAND (patch, 1);
@@ -5396,7 +5515,7 @@ patch_method_invocation_stmt (patch, primary, where, is_static)
          parse_error_context (wfl, "Can't search method `%s' in package "
                               "`%s'",IDENTIFIER_POINTER (identifier),
                               IDENTIFIER_POINTER (remainder));
-         return error_mark_node;
+         PATCH_METHOD_RETURN_ERROR ();
        }
       /* We're resolving a call from a type */
       else if (RESOLVE_TYPE_NAME_P (wfl))
@@ -5412,7 +5531,7 @@ patch_method_invocation_stmt (patch, primary, where, is_static)
                (identifier_wfl, "Can't make static reference to method "
                 "`%s' in interface `%s'", IDENTIFIER_POINTER (identifier), 
                 IDENTIFIER_POINTER (name));
-             return error_mark_node;
+             PATCH_METHOD_RETURN_ERROR ();
            }
          /* Look the method up in the type selector. The method ought
              to be static. */
@@ -5427,7 +5546,7 @@ patch_method_invocation_stmt (patch, primary, where, is_static)
                 lang_printable_name (TREE_TYPE (TREE_TYPE (list))), fct_name, 
                 IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))));
              free (fct_name);
-             return error_mark_node;
+             PATCH_METHOD_RETURN_ERROR ();
            }
        }
       /* We're resolving an expression name */
@@ -5438,7 +5557,7 @@ patch_method_invocation_stmt (patch, primary, where, is_static)
          /* 1- Find the field to which the call applies */
          field = resolve_field_access (wfl, NULL, &type);
          if (field == error_mark_node)
-           return error_mark_node;
+           PATCH_METHOD_RETURN_ERROR ();
          
          /* 2- Do the layout of the class where the last field
             was found, so we can search it. */
@@ -5451,7 +5570,7 @@ patch_method_invocation_stmt (patch, primary, where, is_static)
                                       identifier, args);
 
          /* 4- Add the field as an argument */
-         args = tree_cons (NULL_TREE, field, args);
+         args = tree_cons (NULL_TREE, field, nreverse (args));
        }
 
       /* CLASS_TYPE is used during the call to not_accessible_p and
@@ -5475,7 +5594,7 @@ patch_method_invocation_stmt (patch, primary, where, is_static)
              parse_error_context 
                (wfl, "Class `%s' not found in type declaration",
                 IDENTIFIER_POINTER (EXPR_WFL_NODE (wfl)));
-             return error_mark_node;
+             PATCH_METHOD_RETURN_ERROR ();
            }
          
          /* Can't instantiate an abstract class */
@@ -5484,7 +5603,7 @@ patch_method_invocation_stmt (patch, primary, where, is_static)
              parse_error_context 
                (wfl, "Class `%s' is an abstract class. It can't be "
                 "instantiated", IDENTIFIER_POINTER (EXPR_WFL_NODE (wfl)));
-             return error_mark_node;
+             PATCH_METHOD_RETURN_ERROR ();
            }
          class_to_search = TREE_TYPE (class_to_search);
          lc = 1;
@@ -5504,16 +5623,18 @@ patch_method_invocation_stmt (patch, primary, where, is_static)
 
       /* Don't continue if no method were found, as the next statement
          can't be executed then. */
-      if (!list) return error_mark_node;
+      if (!list)
+       PATCH_METHOD_RETURN_ERROR ();
 
       /* Check for static reference if non static methods */
       if (check_for_static_method_reference (wfl, patch, list, 
                                             class_to_search, primary))
-       return error_mark_node;
+       PATCH_METHOD_RETURN_ERROR ();
 
       /* Non static/constructor methods are called with the current
         object extra argument. If method is resolved as a primary,
         use the primary otherwise use the current THIS. */
+      args = nreverse (args);
       if (!CALL_CONSTRUCTOR_P (patch) && !METHOD_STATIC (list))
        args = tree_cons (NULL_TREE, primary ? primary : current_this, args);
 
@@ -5522,7 +5643,8 @@ patch_method_invocation_stmt (patch, primary, where, is_static)
 
   /* Merge point of all resolution schemes. If we have nothing, this
      is an error, already signaled */
-  if (!list) return error_mark_node;
+  if (!list) 
+    PATCH_METHOD_RETURN_ERROR ();
 
   /* Check accessibility, position the is_static flag, build and
      return the call */
@@ -5536,12 +5658,16 @@ patch_method_invocation_stmt (patch, primary, where, is_static)
         IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (class_type))), fct_name,
         IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (current_class))));
       free (fct_name);
-      return error_mark_node;
+      PATCH_METHOD_RETURN_ERROR ();
     }
   
   if (is_static) 
     *is_static = METHOD_STATIC (list);
   java_parser_context_restore_global ();
+  /* Sometimes, we want the decl of the selected method. Such as for
+     EH checking */
+  if (ret_decl)
+    *ret_decl = list;
   return patch_invoke (patch, list, args, wfl);
 }
 
@@ -5574,21 +5700,28 @@ patch_invoke (patch, method, args, cl)
      tree patch, method, args;
      tree cl;
 {
+  int im;
   tree dtable, func;
   tree signature = build_java_signature (TREE_TYPE (method));
-  tree original_call;
+  tree original_call, node, t, ta;
 
-  switch (invocation_mode (method, 0))
+  /* Last step for args: convert build-in types */
+  for (t = TYPE_ARG_TYPES (TREE_TYPE (method)),
+       ta = args; t && ta; t = TREE_CHAIN (t), ta = TREE_CHAIN (ta))
+    if (JPRIMITIVE_TYPE_P (TREE_TYPE (TREE_VALUE (ta))) &&
+       TREE_TYPE (TREE_VALUE (ta)) != TREE_VALUE (t))
+      TREE_VALUE (ta) = convert (TREE_VALUE (t), TREE_VALUE (ta));
+       
+  switch ((im = invocation_mode (method, 0)))
     {
     case INVOKE_VIRTUAL:
       dtable = invoke_build_dtable (0, args);
       func = build_invokevirtual (dtable, method);
       break;
+
     case INVOKE_STATIC:
       func = build_known_method_ref (method, TREE_TYPE (method),
-                                    DECL_CONTEXT (method),
-                                    signature, args);
-      args = nreverse (args);
+                                    DECL_CONTEXT (method), signature, args);
       break;
 
     default:
@@ -5596,7 +5729,6 @@ patch_invoke (patch, method, args, cl)
       return NULL_TREE;
     }
 
-
   /* Ensure self_type is initialized, (invokestatic). FIXME */
   func = build1 (NOP_EXPR, build_pointer_type (TREE_TYPE (method)), func);
   TREE_TYPE (patch) = TREE_TYPE (TREE_TYPE (method));
@@ -5638,7 +5770,7 @@ invocation_mode (method, super)
 {
   int access = get_access_flags_from_decl (method);
 
-  if (access & ACC_STATIC)
+  if (access & ACC_STATIC || access & ACC_FINAL)
     return INVOKE_STATIC;
 
   if (CLASS_FINAL (TYPE_NAME (DECL_CONTEXT (method))))
@@ -6113,6 +6245,17 @@ java_complete_tree (node)
 
       /* 2- They are expressions but ultimately deal with statements */
 
+    case THROW_EXPR:
+      wfl_op1 = TREE_OPERAND (node, 0);
+      COMPLETE_CHECK_OP_0 (node);
+      return patch_throw_statement (node, wfl_op1);
+
+    case SYNCHRONIZED_EXPR:
+      wfl_op1 = TREE_OPERAND (node, 0);
+      COMPLETE_CHECK_OP_0 (node);
+      COMPLETE_CHECK_OP_1 (node);
+      return patch_synchronized_statement (node, wfl_op1);
+
     case TRY_EXPR:
       return patch_try_statement (node);
 
@@ -6219,7 +6362,7 @@ java_complete_tree (node)
            }
          else
            {
-             TREE_VALUE (cn) = save_expr (dim);
+             TREE_VALUE (cn) = dim;
              /* Setup the location of the current dimension, for
                 later error report. */
              TREE_PURPOSE (cn) = 
@@ -6237,7 +6380,14 @@ java_complete_tree (node)
       if (complete_function_arguments (node))
        return error_mark_node;
       else
-       return patch_method_invocation_stmt (node, NULL_TREE, NULL_TREE, NULL);
+       {
+         tree decl;
+         node = patch_method_invocation_stmt (node, NULL_TREE, 
+                                              NULL_TREE, 0, &decl);
+         if (node != error_mark_node)
+           check_thrown_exceptions (EXPR_WFL_LINECOL (node), decl);
+         return node;
+       }
 
     case MODIFY_EXPR:
       /* Save potential wfls */
@@ -6407,12 +6557,9 @@ complete_function_arguments (node)
         crafted string buffer, as a result of use of the the String
         `+' operator. Build `parm.toString()' and expand it. */
       if ((temp = patch_string (parm)))
-       parm = TREE_VALUE (cn) = temp;
-      
-      if (TREE_CODE (TREE_TYPE (parm)) == RECORD_TYPE)
-       TREE_VALUE (cn) = convert (promote_type (TREE_TYPE (parm)), parm);
-      else
-       TREE_VALUE (cn) = save_expr (parm);
+       parm = temp;
+      TREE_VALUE (cn) = parm;
+
       if (not_initialized_as_it_should_p (parm))
        {
          ERROR_VARIABLE_NOT_INITIALIZED (wfl, EXPR_WFL_NODE (wfl));
@@ -6943,6 +7090,9 @@ valid_ref_assignconv_cast_p (source, dest, cast)
          tree source_element_type = TYPE_ARRAY_ELEMENT (source);
          tree dest_element_type = TYPE_ARRAY_ELEMENT (dest);
          
+         /* In case of severe errors, they turn out null */
+         if (!dest_element_type || !source_element_type)
+           return 0;
          if (source_element_type == dest_element_type)
            return 1;
          return valid_ref_assignconv_cast_p (source_element_type,
@@ -7289,12 +7439,9 @@ patch_binop (node, wfl_op1, wfl_op2)
       
       /* 15.20.3 Reference Equality Operators == and != */
       /* Types have to be either references or the null type */
-      else if ((op1 == null_pointer_node || op2 == null_pointer_node 
-               || JREFERENCE_TYPE_P (op1_type) 
-               || JREFERENCE_TYPE_P (op2_type))
-              && ((op1_type == op2_type)
-                  /* There should use a valid_cast_to_p() */
-                  ))
+      else if (op1 == null_pointer_node || op2 == null_pointer_node 
+              || (JREFERENCE_TYPE_P (op1_type) && JREFERENCE_TYPE_P (op2_type)
+                  && ((op1_type == op2_type))))
        ;                       /* Nothing to do here */
          
       /* Else we have an error figure what can't be converted into
@@ -8768,18 +8915,13 @@ build_try_statement (location, try_block, catches, finally)
                   exception_parameter */
          catch_decl = build_decl_no_layout (VAR_DECL, generate_name (),
                                             ptr_type_node);
-         stmt = build (MODIFY_EXPR, void_type_node, catch_decl,
-                       soft_exceptioninfo_call_node);
-         TREE_SIDE_EFFECTS (stmt) = 1;
+         BUILD_ASSIGN_EXCEPTION_INFO (stmt, catch_decl);
          catch_block = build_expr_block (stmt, NULL_TREE);
          catch_block = build_jump_to_finally (catch_block, rff, 
                                               FINALLY_EXPR_LABEL (finally), 
                                               void_type_node);
-         stmt = build (CALL_EXPR, void_type_node,
-                       build_address_of (throw_node),
-                       build_tree_list (NULL_TREE, catch_decl), NULL_TREE);
+         BUILD_THROW (stmt, catch_decl);
          catch_block = build_expr_block (catch_block, catch_decl);
-         TREE_SIDE_EFFECTS (stmt) = 1;
          add_stmt_to_block (catch_block, void_type_node, stmt);
 
          /* Link the new handler to the existing list as the first
@@ -8822,14 +8964,12 @@ patch_try_statement (node)
   tree catch = nreverse (TREE_OPERAND (node, 1));
   tree finally = TREE_OPERAND (node, 2);
   int finally_p = (finally ? 1 : 0);
-  tree current;
-
-  /* Walk the try block */
-  if ((try = java_complete_tree (try)) == error_mark_node)
-    error_found = 1;
+  tree current, caught_type_list = NULL_TREE;
 
   /* Check catch clauses, if any. Every time we find an error, we try
-     to process the next catch clause. */
+     to process the next catch clause. We process the catch clause before
+     the try block so that when processing the try block we can check thrown
+     exceptions againts the caught type list. */
   for (current = catch; current; current = TREE_CHAIN (current))
     {
       tree carg_decl, carg_type;
@@ -8908,6 +9048,11 @@ patch_try_statement (node)
       if (unreachable)
        continue;
 
+      /* Things to do here: the exception must be thrown */
+
+      /* Link this type to the caught type list */
+      caught_type_list = tree_cons (NULL_TREE, carg_type, caught_type_list);
+
       /* Complete the catch clause block */
       catch_block = java_complete_tree (TREE_OPERAND (current, 0));
       if (catch_block == error_mark_node)
@@ -8918,6 +9063,11 @@ patch_try_statement (node)
       TREE_OPERAND (current, 0) = catch_block;
     }
 
+  PUSH_EXCEPTIONS (caught_type_list);
+  if ((try = java_complete_tree (try)) == error_mark_node)
+    error_found = 1;
+  POP_EXCEPTIONS ();
+
   /* Process finally */
   if (finally)
     {
@@ -8937,3 +9087,208 @@ patch_try_statement (node)
   TREE_TYPE (node) = void_type_node;
   return node;
 }
+
+/* 14.17 The synchronized Statement */
+
+static tree
+patch_synchronized_statement (node, wfl_op1)
+    tree node, wfl_op1;
+{
+  tree expr = TREE_OPERAND (node, 0);
+  tree block = TREE_OPERAND (node, 1);
+  tree try_block, catch_all, stmt, compound, decl;
+
+  /* The TYPE of expr must be a reference type */
+  if (!JREFERENCE_TYPE_P (TREE_TYPE (TREE_OPERAND (node, 0))))
+    {
+      SET_WFL_OPERATOR (wfl_operator, node, wfl_op1);
+      parse_error_context (wfl_operator, "Incompatible type for `synchronized'"
+                          ". Can't convert `%s' to `java.lang.Object'",
+                          lang_printable_name (TREE_TYPE (expr)));
+      return error_mark_node;
+    }
+
+  /* Generate a try-finally for the synchronized statement, except
+     that the handler that catches all throw exception calls
+     _Jv_MonitorExit and then rethrow the exception.
+     The synchronized statement is then implemented as:
+     TRY 
+       {
+         _Jv_MonitorEnter (expression)
+        synchronized_block
+         _Jv_MonitorExit (expression)
+       }
+     CATCH_ALL
+       {
+         e = _Jv_exception_info ();
+        _Jv_MonitorExit (expression)
+        Throw (e);
+       } */
+
+  /* TRY block */
+  BUILD_MONITOR_ENTER (stmt, expr);
+  compound = add_stmt_to_compound (NULL_TREE, int_type_node, stmt);
+  compound = add_stmt_to_compound (compound, void_type_node, block);
+  BUILD_MONITOR_EXIT (stmt, expr);
+  compound = add_stmt_to_compound (compound, int_type_node, stmt);
+  try_block = build_expr_block (compound, NULL_TREE);
+
+  /* CATCH_ALL block */
+  decl = build_decl_no_layout (VAR_DECL, generate_name (), ptr_type_node);
+  BUILD_ASSIGN_EXCEPTION_INFO (stmt, decl);
+  compound = add_stmt_to_compound (NULL_TREE, void_type_node, stmt);
+  BUILD_MONITOR_EXIT (stmt, expr);
+  compound = add_stmt_to_compound (compound, int_type_node, stmt);
+  BUILD_THROW (stmt, decl);
+  compound = add_stmt_to_compound (compound, void_type_node, stmt);
+  catch_all = build_expr_block (compound, decl);
+  catch_all = build_expr_block (catch_all, NULL_TREE);
+  catch_all = build1 (CATCH_EXPR, void_type_node, catch_all);
+
+  /* TRY-CATCH statement */
+  return build (TRY_EXPR, void_type_node, try_block, catch_all, NULL_TREE);
+}
+
+/* 14.16 The throw Statement */
+
+static tree
+patch_throw_statement (node, wfl_op1)
+    tree node, wfl_op1;
+{
+  tree expr = TREE_OPERAND (node, 0);
+  tree type = TREE_TYPE (expr);
+  int unchecked_ok = 0, tryblock_throws_ok = 0;
+
+  /* Thrown expression must be assignable to java.lang.Throwable */
+  if (!try_reference_assignconv (throwable_type_node, expr))
+    {
+      SET_WFL_OPERATOR (wfl_operator, node, wfl_op1);
+      parse_error_context (wfl_operator, "Can't throw `%s'; it must be a "
+                          "subclass of class `java.lang.Throwable'",
+                          lang_printable_name (type));
+      /* If the thrown expression was a reference, we further the
+         compile-time check. */
+      if (!JREFERENCE_TYPE_P (type))
+       return error_mark_node;
+    }
+
+  /* At least one of the following must be true */
+
+  /* The type of the throw expression is a not checked exception,
+     i.e. is a unchecked expression. */
+  unchecked_ok = IS_UNCHECKED_EXPRESSION_P (TREE_TYPE (type));
+
+  /* Throw is contained in a try statement and at least one catch
+     clause can receive the thrown expression or the current method is
+     declared to throw such an exception. Or, the throw statement is
+     contained in a method or constructor declaration and the type of
+     the Expression is assignable to at least one type listed in the
+     throws clause the declaration. */
+  SET_WFL_OPERATOR (wfl_operator, node, wfl_op1);
+  if (!unchecked_ok)
+    tryblock_throws_ok = 
+      check_thrown_exceptions_do (EXPR_WFL_LINECOL (wfl_operator), 
+                                 TREE_TYPE (expr));
+  if (!(unchecked_ok || tryblock_throws_ok))
+    {
+      /* If there is a surrounding try block that has no matching
+        clatch clause, report it first. A surrounding try block exits
+        only if there is something after the list of checked
+        exception thrown by the current function (if any). */
+      if (IN_TRY_BLOCK_P ())
+       parse_error_context (wfl_operator, "Checked exception `%s' can't be "
+                            "caught by any of the catch clause(s) "
+                            "of the surrounding `try' block",
+                            lang_printable_name (type));
+      /* If we have no surrounding try statement and the method doesn't have
+        any throws, report it now. FIXME */
+      else if (!EXCEPTIONS_P (currently_caught_type_list) 
+              && !tryblock_throws_ok)
+       parse_error_context (wfl_operator, "Checked exception `%s' isn't "
+                            "thrown from a `try' block", 
+                            lang_printable_name (type));
+      /* Otherwise, the current method doesn't have the appropriate
+         throws declaration */
+      else
+       parse_error_context (wfl_operator, "Checked exception `%s' doesn't "
+                            "match any of current method's `throws' "
+                            "declaration(s)", 
+                            lang_printable_name (type));
+      return error_mark_node;
+    }
+
+  /* If a throw statement is contained in a static initializer, then a
+     compile-time check ensures that either its value is always an
+     unchecked exception or its value is always caught by some try
+     statement that contains it. FIXME, static initializer. */
+  
+  BUILD_THROW (node, expr);
+  return node;
+}
+
+/* Check that exception said to be thrown by method DECL can be
+   effectively caught from where DECL is invoked.  */
+
+static void
+check_thrown_exceptions (location, decl)
+     int location;
+     tree decl;
+{
+  tree throws;
+  /* For all the unchecked exceptions thrown by DECL */
+  for (throws = DECL_FUNCTION_THROWS (decl); throws; 
+       throws = TREE_CHAIN (throws)) 
+    if (!check_thrown_exceptions_do (location, TREE_VALUE (throws)))
+      {
+       EXPR_WFL_LINECOL (wfl_operator) = location;
+       parse_error_context 
+         (wfl_operator, "Exception `%s' must be caught, or it must be "
+          "declared in the `throws' clause of `%s'", 
+          lang_printable_name (TREE_VALUE (throws)),
+          IDENTIFIER_POINTER (DECL_NAME (current_function_decl)));
+      }
+}
+
+/* Return 1 if EXCEPTION is caught at the current nesting level of
+   try-catch blocks, OR is listed in the `throws' clause of the
+   current method.  */
+
+static int
+check_thrown_exceptions_do (location, exception)
+     int location;
+     tree exception;
+{
+  tree list = currently_caught_type_list;
+  /* First, all the nested try-catch-finally at that stage. The
+     last element contains `throws' clause exceptions, if any. */
+  while (list)
+    {
+      tree caught;
+      for (caught = TREE_VALUE (list); caught; caught = TREE_CHAIN (caught))
+       if (valid_ref_assignconv_cast_p (exception, TREE_VALUE (caught), 0))
+         return 1;
+      list = TREE_CHAIN (list);
+    }
+  return 0;
+}
+
+static void
+purge_unchecked_exceptions (mdecl)
+     tree mdecl;
+{
+  tree throws = DECL_FUNCTION_THROWS (mdecl);
+  tree new = NULL_TREE;
+
+  while (throws)
+    {
+      tree next = TREE_CHAIN (throws);
+      if (!IS_UNCHECKED_EXPRESSION_P (TREE_VALUE (throws)))
+       {
+         TREE_CHAIN (throws) = new;
+         new = throws;
+       }
+      throws = next;
+    }
+  /* List is inverted here, but it doesn't matter */
+  DECL_FUNCTION_THROWS (mdecl) = new;
+}
index 08acf12..3a8d81f 100644 (file)
@@ -662,7 +662,10 @@ lookup_argument_method (clas, method_name, method_signature)
           method != NULL_TREE;  method = TREE_CHAIN (method))
        {
          tree method_sig = build_java_argument_signature (TREE_TYPE (method));
-         if (DECL_NAME (method) == method_name && method_sig == method_signature)
+         tree name = DECL_NAME (method);
+         if ((TREE_CODE (name) == EXPR_WITH_FILE_LOCATION ?
+              EXPR_WFL_NODE (DECL_NAME (method)) : name) == method_name 
+             && method_sig == method_signature)
            return method;
        }
       clas = CLASSTYPE_SUPER (clas);
@@ -686,7 +689,8 @@ lookup_java_method (clas, method_name, method_signature)
           method != NULL_TREE;  method = TREE_CHAIN (method))
        {
          tree method_sig = build_java_signature (TREE_TYPE (method));
-         if (DECL_NAME (method) == method_name && method_sig == method_signature)
+         if (DECL_NAME (method) == method_name 
+             && method_sig == method_signature)
            return method;
        }
       clas = CLASSTYPE_SUPER (clas);