[multiple changes]
[platform/upstream/gcc.git] / gcc / java / parse.y
index 7e5eeca..5357003 100644 (file)
@@ -61,6 +61,8 @@ definitions and other extensions.  */
 #include "zipfile.h"
 #include "convert.h"
 #include "buffer.h"
+#include "xref.h"
+#include "except.h"
 
 #ifndef DIR_SEPARATOR
 #define DIR_SEPARATOR '/'
@@ -118,6 +120,8 @@ static tree resolve_no_layout PROTO ((tree, tree));
 static int invocation_mode PROTO ((tree, int));
 static tree find_applicable_accessible_methods_list PROTO ((int, tree, 
                                                            tree, tree));
+static void search_applicable_methods_list PROTO ((int, tree, tree, tree, 
+                                                  tree *, tree *));
 static tree find_most_specific_methods_list PROTO ((tree));
 static int argument_types_convertible PROTO ((tree, tree));
 static tree patch_invoke PROTO ((tree, tree, tree));
@@ -184,22 +188,20 @@ static tree add_stmt_to_compound PROTO ((tree, tree, tree));
 static tree add_stmt_to_block PROTO ((tree, tree, tree));
 static tree patch_exit_expr PROTO ((tree));
 static tree build_labeled_block PROTO ((int, tree));
-static tree generate_labeled_block PROTO (());
-static tree complete_labeled_statement PROTO ((tree, tree));
+static tree finish_labeled_statement PROTO ((tree, tree));
 static tree build_bc_statement PROTO ((int, int, tree));
 static tree patch_bc_statement PROTO ((tree));
 static tree patch_loop_statement PROTO ((tree));
 static tree build_new_loop PROTO ((tree));
 static tree build_loop_body PROTO ((int, tree, int));
-static tree complete_loop_body PROTO ((int, tree, tree, int));
+static tree finish_loop_body PROTO ((int, tree, tree, int));
 static tree build_debugable_stmt PROTO ((int, tree));
-static tree complete_for_loop PROTO ((int, tree, tree, tree));
+static tree finish_for_loop PROTO ((int, tree, tree, tree));
 static tree patch_switch_statement PROTO ((tree));
 static tree string_constant_concatenation PROTO ((tree, tree));
 static tree build_string_concatenation PROTO ((tree, tree));
 static tree patch_string_cst PROTO ((tree));
 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));
 static tree build_try_finally_statement PROTO ((int, tree, tree));
 static tree patch_try_statement PROTO ((tree));
@@ -209,7 +211,7 @@ static void check_thrown_exceptions PROTO ((int, tree));
 static int check_thrown_exceptions_do PROTO ((tree));
 static void purge_unchecked_exceptions PROTO ((tree));
 static void check_throws_clauses PROTO ((tree, tree, tree));
-static void complete_method_declaration PROTO ((tree));
+static void finish_method_declaration PROTO ((tree));
 static tree build_super_invocation PROTO (());
 static int verify_constructor_circularity PROTO ((tree, tree));
 static char *constructor_circularity_msg PROTO ((tree, tree));
@@ -236,19 +238,22 @@ static tree patch_new_array_init PROTO ((tree, tree));
 static tree maybe_build_array_element_wfl PROTO ((tree));
 static int array_constructor_check_entry PROTO ((tree, tree));
 static char *purify_type_name PROTO ((char *));
-static tree patch_initialized_static_field PROTO ((tree));
 static tree fold_constant_for_init PROTO ((tree, tree));
 static tree strip_out_static_field_access_decl PROTO ((tree));
+static jdeplist *reverse_jdep_list PROTO ((struct parser_ctxt *));
+static void static_ref_err PROTO ((tree, tree, tree));
 
 /* Number of error found so far. */
 int java_error_count; 
 /* Number of warning found so far. */
 int java_warning_count;
+/* Tell when not to fold, when doing xrefs */
+int do_not_fold;
 
 /* The current parser context */
-static struct parser_ctxt *ctxp;
+struct parser_ctxt *ctxp;
 
-/* List of things that were anlyzed for which code will be generated */
+/* List of things that were analyzed for which code will be generated */
 static struct parser_ctxt *ctxp_for_generation = NULL;
 
 /* binop_lookup maps token to tree_code. It is used where binary
@@ -289,6 +294,10 @@ static tree java_lang_id = NULL_TREE;
 
 /* The "java.lang.Cloneable" qualified name.  */
 static tree java_lang_cloneable = NULL_TREE;
+
+/* Context and flag for static blocks */
+static tree current_static_block = NULL_TREE;
+
 %}
 
 %union {
@@ -301,6 +310,10 @@ static tree java_lang_cloneable = NULL_TREE;
   int value;
 }
 
+%{
+#include "lex.c"
+%}
+
 %pure_parser
 
 /* Things defined here have to match the order of what's in the
@@ -383,7 +396,7 @@ static tree java_lang_cloneable = NULL_TREE;
                        variable_initializers constructor_body
                        array_initializer
 
-%type   <node>         class_body block_end
+%type   <node>         class_body block_end constructor_block_end
 %type   <node>         statement statement_without_trailing_substatement
                        labeled_statement if_then_statement label_decl
                        if_then_else_statement while_statement for_statement
@@ -421,7 +434,7 @@ static tree java_lang_cloneable = NULL_TREE;
 %token   <operator>     EQ_TK GTE_TK ZRS_TK SRS_TK GT_TK LTE_TK LS_TK 
 %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 OCB_TK
+%token   <operator>     NEG_TK REL_QM_TK REL_CL_TK NOT_TK LT_TK OCB_TK CCB_TK
 %token   <operator>     OP_TK OSB_TK DOT_TK THROW_TK INSTANCEOF_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
@@ -622,6 +635,10 @@ type_declaration:
                  $$ = $1;
                }
 |      interface_declaration
+               {
+                 maybe_generate_clinit ();
+                 $$ = $1;
+               }
 |      SC_TK
                { $$ = NULL; }
 |      error
@@ -718,9 +735,21 @@ interface_type_list:
 
 class_body:
        OCB_TK CCB_TK
-               { $$ = ctxp->current_parsed_class; }
+               { 
+                 /* Store the location of the `}' when doing xrefs */
+                 if (flag_emit_xref)
+                   DECL_END_SOURCE_LINE (ctxp->current_parsed_class) = 
+                     EXPR_WFL_ADD_COL ($2.location, 1);
+                 $$ = ctxp->current_parsed_class;
+               }
 |      OCB_TK class_body_declarations CCB_TK
-               { $$ = ctxp->current_parsed_class; }
+               { 
+                 /* Store the location of the `}' when doing xrefs */
+                 if (flag_emit_xref)
+                   DECL_END_SOURCE_LINE (ctxp->current_parsed_class) = 
+                     EXPR_WFL_ADD_COL ($3.location, 1);
+                 $$ = ctxp->current_parsed_class;
+               }
 ;
 
 class_body_declarations:
@@ -819,7 +848,7 @@ method_declaration:
                  source_start_java_method (current_function_decl);
                }
        method_body
-               { complete_method_declaration ($3); }
+               { finish_method_declaration ($3); }
 |      method_header error
                {YYNOT_TWICE yyerror ("'{' expected"); RECOVER;}
 ;
@@ -888,7 +917,10 @@ formal_parameter:
                  $$ = build_tree_list ($2, $1);
                }
 |      modifiers type variable_declarator_id /* Added, JDK1.1 final parms */
-               { $$ = parse_jdk1_1_error ("final parameters"); }
+               { 
+                 parse_jdk1_1_error ("final parameters");
+                 $$ = build_tree_list ($3, $2);
+               }
 |      type error
                {yyerror ("Missing identifier"); RECOVER;}
 |      modifiers type error
@@ -926,11 +958,13 @@ method_body:
 static_initializer:
        static block
                {
-                 RULE ("STATIC_INITIALIZER");
+                 TREE_CHAIN ($2) = ctxp->static_initialized;
+                 ctxp->static_initialized = $2;
                }
 |      static block SC_TK      /* Shouldn't be here. FIXME */
                {
-                 RULE ("STATIC_INITIALIZER");
+                 TREE_CHAIN ($2) = ctxp->static_initialized;
+                 ctxp->static_initialized = $2;
                }
 ;
 
@@ -949,7 +983,7 @@ constructor_declaration:
                  source_start_java_method (current_function_decl);
                }
        constructor_body
-               { complete_method_declaration ($3); }
+               { finish_method_declaration ($3); }
 ;
 
 constructor_header:
@@ -970,19 +1004,23 @@ constructor_body:
        /* Unlike regular method, we always need a complete (empty)
           body so we can safely perform all the required code
           addition (super invocation and field initialization) */
-       block_begin block_end
+       block_begin constructor_block_end
                { 
                  BLOCK_EXPR_BODY ($2) = empty_stmt_node;
                  $$ = $2;
                }
-|      block_begin explicit_constructor_invocation block_end
+|      block_begin explicit_constructor_invocation constructor_block_end
                { $$ = $3; }
-|      block_begin block_statements block_end
+|      block_begin block_statements constructor_block_end
                { $$ = $3; }
-|       block_begin explicit_constructor_invocation block_statements block_end
+|       block_begin explicit_constructor_invocation block_statements constructor_block_end
                { $$ = $4; }
 ;
 
+constructor_block_end:
+       block_end
+|      block_end SC_TK
+
 /* Error recovery for that rule moved down expression_statement: rule.  */
 explicit_constructor_invocation:
        this_or_super OP_TK CP_TK SC_TK
@@ -1008,15 +1046,13 @@ explicit_constructor_invocation:
 this_or_super:                 /* Added, simplifies error diagnostics */
        THIS_TK
                {
-                 tree wfl = build_wfl_node (this_identifier_node, 
-                                            input_filename, 0, 0);
+                 tree wfl = build_wfl_node (this_identifier_node);
                  EXPR_WFL_LINECOL (wfl) = $1.location;
                  $$ = wfl;
                }
 |      SUPER_TK
                {
-                 tree wfl = build_wfl_node (super_identifier_node,
-                                            input_filename, 0, 0);
+                 tree wfl = build_wfl_node (super_identifier_node);
                  EXPR_WFL_LINECOL (wfl) = $1.location;
                  $$ = wfl;
                }
@@ -1134,7 +1170,13 @@ variable_initializers:
 /* 19.11 Production from 14: Blocks and Statements  */
 block:
        OCB_TK CCB_TK
-               { $$ = empty_stmt_node; }
+               { 
+                 /* Store the location of the `}' when doing xrefs */
+                 if (current_function_decl && flag_emit_xref)
+                   DECL_END_SOURCE_LINE (current_function_decl) = 
+                     EXPR_WFL_ADD_COL ($2.location, 1);
+                 $$ = empty_stmt_node; 
+               }
 |      block_begin block_statements block_end
                { $$ = $3; }
 ;
@@ -1148,6 +1190,10 @@ block_end:
        CCB_TK
                { 
                  maybe_absorb_scoping_blocks ();
+                 /* Store the location of the `}' when doing xrefs */
+                 if (current_function_decl && flag_emit_xref)
+                   DECL_END_SOURCE_LINE (current_function_decl) = 
+                     EXPR_WFL_ADD_COL ($1.location, 1);                  
                  $$ = exit_block ();
                }
 ;
@@ -1183,13 +1229,7 @@ statement:
 |      if_then_else_statement
 |      while_statement
 |      for_statement
-               { 
-                 /* If the for loop is unlabeled, we must return the
-                    block it was defined it. It our last chance to
-                    get a hold on it. */
-                 if (!LOOP_HAS_LABEL_P ($$))
-                   $$ = exit_block ();
-               }
+               { $$ = exit_block (); }
 ;
 
 statement_nsi:
@@ -1198,6 +1238,7 @@ statement_nsi:
 |      if_then_else_statement_nsi
 |      while_statement_nsi
 |      for_statement_nsi
+               { $$ = exit_block (); }
 ;
 
 statement_without_trailing_substatement:
@@ -1232,22 +1273,14 @@ label_decl:
 
 labeled_statement:
        label_decl statement
-               { 
-                 $$ = complete_labeled_statement ($1, $2);
-                 pop_labeled_block ();
-                 POP_LABELED_BLOCK ();
-               }
+               { $$ = finish_labeled_statement ($1, $2); }
 |      identifier error
                {yyerror ("':' expected"); RECOVER;}
 ;
 
 labeled_statement_nsi:
        label_decl statement_nsi
-               { 
-                 $$ = complete_labeled_statement ($1, $2);
-                 pop_labeled_block ();
-                 POP_LABELED_BLOCK ();
-               }
+               { $$ = finish_labeled_statement ($1, $2); }
 ;
 
 /* We concentrate here a bunch of error handling rules that we couldn't write
@@ -1320,7 +1353,10 @@ statement_expression:
 
 if_then_statement:
        IF_TK OP_TK expression CP_TK statement
-       { $$ = build_if_else_statement ($2.location, $3, $5, NULL_TREE); }
+               { 
+                 $$ = build_if_else_statement ($2.location, $3, 
+                                               $5, NULL_TREE);
+               }
 |      IF_TK error
                {yyerror ("'(' expected"); RECOVER;}
 |      IF_TK OP_TK error
@@ -1331,12 +1367,12 @@ if_then_statement:
 
 if_then_else_statement:
        IF_TK OP_TK expression CP_TK statement_nsi ELSE_TK statement
-       { $$ = build_if_else_statement ($2.location, $3, $5, $7); }
+               { $$ = build_if_else_statement ($2.location, $3, $5, $7); }
 ;
 
 if_then_else_statement_nsi:
        IF_TK OP_TK expression CP_TK statement_nsi ELSE_TK statement_nsi
-       { $$ = build_if_else_statement ($2.location, $3, $5, $7); }
+               { $$ = build_if_else_statement ($2.location, $3, $5, $7); }
 ;
 
 switch_statement:
@@ -1428,7 +1464,7 @@ while_expression:
 
 while_statement:
        while_expression statement
-               { $$ = complete_loop_body (0, NULL_TREE, $2, 0); }
+               { $$ = finish_loop_body (0, NULL_TREE, $2, 0); }
 |      WHILE_TK error
                {YYERROR_NOW; yyerror ("'(' expected"); RECOVER;}
 |      WHILE_TK OP_TK error
@@ -1439,7 +1475,7 @@ while_statement:
 
 while_statement_nsi:
        while_expression statement_nsi
-               { $$ = complete_loop_body (0, NULL_TREE, $2, 0); }
+               { $$ = finish_loop_body (0, NULL_TREE, $2, 0); }
 ;
 
 do_statement_begin:
@@ -1453,15 +1489,15 @@ do_statement_begin:
 
 do_statement: 
        do_statement_begin statement WHILE_TK OP_TK expression CP_TK SC_TK
-               { $$ = complete_loop_body ($4.location, $5, $2, 1); }
+               { $$ = finish_loop_body ($4.location, $5, $2, 1); }
 ;
 
 for_statement:
        for_begin SC_TK expression SC_TK for_update CP_TK statement
-               { $$ = complete_for_loop (EXPR_WFL_LINECOL ($3), $3, $5, $7);}
+               { $$ = finish_for_loop (EXPR_WFL_LINECOL ($3), $3, $5, $7); }
 |      for_begin SC_TK SC_TK for_update CP_TK statement
                { 
-                 $$ = complete_for_loop (0, NULL_TREE, $4, $6);
+                 $$ = finish_for_loop (0, NULL_TREE, $4, $6);
                  /* We have not condition, so we get rid of the EXIT_EXPR */
                  LOOP_EXPR_BODY_CONDITION_EXPR (LOOP_EXPR_BODY ($$), 0) = 
                    empty_stmt_node;
@@ -1476,10 +1512,10 @@ for_statement:
 
 for_statement_nsi:
        for_begin SC_TK expression SC_TK for_update CP_TK statement_nsi
-               { $$ = complete_for_loop (EXPR_WFL_LINECOL ($3), $3, $5, $7);}
+               { $$ = finish_for_loop (EXPR_WFL_LINECOL ($3), $3, $5, $7);}
 |      for_begin SC_TK SC_TK for_update CP_TK statement_nsi
                { 
-                 $$ = complete_for_loop (0, NULL_TREE, $4, $6);
+                 $$ = finish_for_loop (0, NULL_TREE, $4, $6);
                  /* We have not condition, so we get rid of the EXIT_EXPR */
                  LOOP_EXPR_BODY_CONDITION_EXPR (LOOP_EXPR_BODY ($$), 0) = 
                    empty_stmt_node;
@@ -1621,10 +1657,10 @@ try_statement:
 |      TRY_TK block finally
                { $$ = build_try_finally_statement ($1.location, $2, $3); }
 |      TRY_TK block catches finally
-               { $$ = build_try_finally_statement ($1.location,
-                                                   build_try_statement ($1.location,
-                                                                        $2, $3),
-                                                   $4); }
+               { $$ = build_try_finally_statement 
+                   ($1.location, build_try_statement ($1.location,
+                                                      $2, $3), $4);
+               }
 |      TRY_TK error
                {yyerror ("'{' expected"); DRECOVER (try_statement);}
 ;
@@ -1856,8 +1892,7 @@ field_access:
 |      SUPER_TK DOT_TK identifier
                {
                  tree super_wfl = 
-                   build_wfl_node (super_identifier_node, 
-                                   input_filename, 0, 0);
+                   build_wfl_node (super_identifier_node);
                  EXPR_WFL_LINECOL (super_wfl) = $1.location;
                  $$ = make_qualified_name (super_wfl, $3, $2.location);
                }
@@ -2273,8 +2308,6 @@ constant_expression:
 %%
 \f
 
-#include "lex.c"
-
 /* Flag for the error report routine to issue the error the first time
    it's called (overriding the default behavior which is to drop the
    first invocation and honor the second one, taking advantage of a
@@ -2289,7 +2322,7 @@ java_push_parser_context ()
   struct parser_ctxt *new = 
     (struct parser_ctxt *)xmalloc(sizeof (struct parser_ctxt));
 
-  bzero (new, sizeof (struct parser_ctxt));
+  bzero ((PTR) new, sizeof (struct parser_ctxt));
   new->next = ctxp;
   ctxp = new;
   if (ctxp->next)
@@ -2537,20 +2570,24 @@ find_expr_with_wfl (node)
       switch (TREE_CODE (node))
        {
        case BLOCK:
-         return find_expr_with_wfl (BLOCK_EXPR_BODY (node));
+         node = BLOCK_EXPR_BODY (node);
+         continue;
 
        case COMPOUND_EXPR:
          to_return = find_expr_with_wfl (TREE_OPERAND (node, 0));
          if (to_return)
            return to_return;
-         to_return = find_expr_with_wfl (TREE_OPERAND (node, 1));
-         return to_return;
+         node = TREE_OPERAND (node, 1);
+         continue;
 
        case LOOP_EXPR:
-         return find_expr_with_wfl (TREE_OPERAND (node, 0));
+         node = TREE_OPERAND (node, 0);
+         continue;
          
        case LABELED_BLOCK_EXPR:
-         return find_expr_with_wfl (TREE_OPERAND (node, 1));
+         node = TREE_OPERAND (node, 1);
+         continue;
+
        default:
          code = TREE_CODE_CLASS (TREE_CODE (node));
          if (((code == '1') || (code == '2') || (code == 'e'))
@@ -2684,7 +2721,7 @@ build_array_from_name (type, type_wfl, name, ret_name)
   /* If we have, then craft a new type for this variable */
   if (more_dims)
     {
-      name = get_identifier (&more_dims [string]);
+      name = get_identifier (&string [more_dims]);
 
       /* If we have a pointer, use its type */
       if (TREE_CODE (type) == POINTER_TYPE)
@@ -2851,7 +2888,11 @@ maybe_create_class_interface_decl (decl, qualified_name, cl)
   
   /* Take care of the file and line business */
   DECL_SOURCE_FILE (decl) = EXPR_WFL_FILENAME (cl);
-  DECL_SOURCE_LINE (decl) = EXPR_WFL_LINENO (cl);
+  /* If we're emiting xrefs, store the line/col number information */
+  if (flag_emit_xref)
+    DECL_SOURCE_LINE (decl) = EXPR_WFL_LINECOL (cl);
+  else
+    DECL_SOURCE_LINE (decl) = EXPR_WFL_LINENO (cl);
   CLASS_FROM_SOURCE_P (TREE_TYPE (decl)) = 1;
   CLASS_FROM_CURRENTLY_COMPILED_SOURCE_P (TREE_TYPE (decl)) =
     IS_A_COMMAND_LINE_FILENAME_P (EXPR_WFL_FILENAME_NODE (cl));
@@ -2933,7 +2974,7 @@ create_interface (flags, id, super)
   decl = maybe_create_class_interface_decl (decl, q_name, id);
 
   /* Set super info and mark the class a complete */
-  set_super_info (ACC_ABSTRACT | ACC_INTERFACE | flags, TREE_TYPE (decl), 
+  set_super_info (ACC_INTERFACE | flags, TREE_TYPE (decl), 
                  object_type_node, ctxp->interface_number);
   ctxp->interface_number = 0;
   CLASS_COMPLETE_P (decl) = 1;
@@ -2952,7 +2993,7 @@ create_class (flags, id, super, interfaces)
 {
   tree raw_name = EXPR_WFL_NODE (id);
   tree class_id, decl;
-  tree super_decl = NULL, super_decl_type;
+  tree super_decl_type;
 
   class_id = parser_qualified_classname (id);
   decl = IDENTIFIER_CLASS_VALUE (class_id);
@@ -2984,17 +3025,8 @@ create_class (flags, id, super, interfaces)
          return NULL_TREE;
        }
 
-      /* The class is known and exists if there is a decl. Otherwise,
-         postpone the operation and do it later. */
-      super_decl = IDENTIFIER_CLASS_VALUE (EXPR_WFL_NODE (super));
-      if (super_decl)
-       {
-         parser_check_super (super_decl, decl, id);
-         super_decl_type = TREE_TYPE (super_decl);
-       }
-      else
-       super_decl_type = 
-         register_incomplete_type (JDEP_SUPER, super, decl, NULL_TREE);
+      super_decl_type = 
+       register_incomplete_type (JDEP_SUPER, super, decl, NULL_TREE);
     }
   else if (TREE_TYPE (decl) != object_type_node)
     super_decl_type = object_type_node;
@@ -3009,6 +3041,11 @@ create_class (flags, id, super, interfaces)
   CLASS_COMPLETE_P (decl) = 1;
   add_superinterfaces (decl, interfaces);
 
+  /* If doing xref, store the location at which the inherited class
+     (if any) was seen. */
+  if (flag_emit_xref && super)
+    DECL_INHERITED_SOURCE_LINE (decl) = EXPR_WFL_LINECOL (super);
+
   /* Eventually sets the @deprecated tag flag */
   CHECK_DEPRECATED (decl);
 
@@ -3152,7 +3189,10 @@ register_fields (flags, type, variable_list)
 
       /* Set lineno to the line the field was found and create a
          declaration for it. Eventually sets the @deprecated tag flag. */
-      lineno = EXPR_WFL_LINENO (cl);
+      if (flag_emit_xref)
+       lineno = EXPR_WFL_LINECOL (cl);
+      else
+       lineno = EXPR_WFL_LINENO (cl);
       field_decl = add_field (class_type, current_name, real_type, flags);
       CHECK_DEPRECATED (field_decl);
       
@@ -3160,11 +3200,6 @@ register_fields (flags, type, variable_list)
       if (must_chain)
        register_incomplete_type (JDEP_FIELD, wfl, field_decl, type);
          
-      /* Default value of a static field is 0 and it is considered
-        initialized. */
-      if (flags & ACC_STATIC)
-       INITIALIZED_P (field_decl) = 1;
-      
       /* If we have an initialization value tied to the field */
       if (init)
        {
@@ -3180,7 +3215,8 @@ register_fields (flags, type, variable_list)
              TREE_CHAIN (init) = ctxp->static_initialized;
              ctxp->static_initialized = init;
              DECL_INITIAL (field_decl) = TREE_OPERAND (init, 1);
-             if (TREE_CODE (TREE_OPERAND (init, 1)) == NEW_ARRAY_INIT)
+             if (TREE_OPERAND (init, 1) 
+                 && TREE_CODE (TREE_OPERAND (init, 1)) == NEW_ARRAY_INIT)
                TREE_STATIC (TREE_OPERAND (init, 1)) = 1;
            }
          /* A non-static field declared with an immediate initialization is
@@ -3191,7 +3227,6 @@ register_fields (flags, type, variable_list)
              TREE_CHAIN (init) = ctxp->non_static_initialized;
              ctxp->non_static_initialized = init;
            }
-         INITIALIZED_P (field_decl) = 1;
          MODIFY_EXPR_FROM_INITIALIZATION_P (init) = 1;
        }
     }
@@ -3299,7 +3334,8 @@ method_header (flags, type, mdecl, throws)
       ABSTRACT_CHECK (flags, ACC_FINAL, id, "Final");
       ABSTRACT_CHECK (flags, ACC_NATIVE, id, "Native");
       ABSTRACT_CHECK (flags, ACC_SYNCHRONIZED,id, "Synchronized");
-      if (!CLASS_ABSTRACT (TYPE_NAME (this_class)))
+      if (!CLASS_ABSTRACT (TYPE_NAME (this_class))
+         && !CLASS_INTERFACE (TYPE_NAME (this_class)))
        parse_error_context 
          (id, "Class `%s' must be declared abstract to define abstract "
           "method `%s'", 
@@ -3333,7 +3369,7 @@ method_header (flags, type, mdecl, throws)
 
   /* Method declared within the scope of an interface are implicitly
      abstract and public. Conflicts with other erroneously provided
-     modifiers are check right after. */
+     modifiers are checked right after. */
 
   if (CLASS_INTERFACE (TYPE_NAME (this_class)))
     {
@@ -3451,6 +3487,11 @@ method_header (flags, type, mdecl, throws)
   /* Eventually set the @deprecated tag flag */
   CHECK_DEPRECATED (meth);
 
+  /* If doing xref, store column and line number information instead
+     of the line number only. */
+  if (flag_emit_xref)
+    DECL_SOURCE_LINE (meth) = EXPR_WFL_LINECOL (id);
+
   return meth;
 }
 
@@ -3475,16 +3516,43 @@ fix_method_argument_names (orig_arg, meth)
 /* Complete the method declaration with METHOD_BODY.  */
 
 static void
-complete_method_declaration (method_body)
+finish_method_declaration (method_body)
      tree method_body;
 {
+  int flags = get_access_flags_from_decl (current_function_decl);
+
+  /* 8.4.5 Method Body */
+  if ((flags & ACC_ABSTRACT || flags & ACC_NATIVE) && method_body)
+    {
+      tree wfl = DECL_NAME (current_function_decl);
+      parse_error_context (wfl, 
+                          "%s method `%s' can't have a body defined",
+                          (METHOD_NATIVE (current_function_decl) ?
+                           "Native" : "Abstract"),
+                          IDENTIFIER_POINTER (EXPR_WFL_NODE (wfl)));
+      method_body = NULL_TREE;
+    }
+  else if (!(flags & ACC_ABSTRACT) && !(flags & ACC_NATIVE) && !method_body)
+    {
+      tree wfl = DECL_NAME (current_function_decl);
+      parse_error_context (wfl, 
+                          "Non native and non abstract method `%s' must "
+                          "have a body defined",
+                          IDENTIFIER_POINTER (EXPR_WFL_NODE (wfl)));
+      method_body = NULL_TREE;
+    }
+
   BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (current_function_decl)) = method_body;
   maybe_absorb_scoping_blocks ();
   /* Exit function's body */
   exit_block ();
   /* Merge last line of the function with first line, directly in the
      function decl. It will be used to emit correct debug info. */
-  DECL_SOURCE_LINE_MERGE (current_function_decl, ctxp->last_ccb_indent1);
+  if (!flag_emit_xref)
+    DECL_SOURCE_LINE_MERGE (current_function_decl, ctxp->last_ccb_indent1);
+  /* So we don't have an irrelevant function declaration context for
+     the next static block we'll see. */
+  current_function_decl = NULL_TREE;
 }
 
 /* Build a an error message for constructor circularity errors.  */
@@ -4380,7 +4448,7 @@ get_printable_method_name (decl)
      tree decl;
 {
   char *to_return;
-  tree name;
+  tree name = NULL_TREE;
 
   if (DECL_CONSTRUCTOR_P (decl))
     {
@@ -4402,8 +4470,7 @@ static int
 reset_method_name (method)
      tree method;
 {
-  if (DECL_NAME (method) != clinit_identifier_node
-      && DECL_NAME (method) != finit_identifier_node)
+  if (!IS_CLINIT (method) && DECL_NAME (method) != finit_identifier_node)
     {
       /* NAME is just the plain name when Object is being defined */
       if (DECL_CONTEXT (method) != object_type_node)
@@ -4565,7 +4632,7 @@ java_check_regular_methods (class_decl)
          char *t = strdup (lang_printable_name (TREE_TYPE (TREE_TYPE (found)),
                                                 0));
          parse_error_context 
-           (method_wfl, 
+           (method_wfl,
             "Method `%s' was defined with return type `%s' in class `%s'", 
             lang_printable_name (found, 0), t,
             IDENTIFIER_POINTER 
@@ -4573,6 +4640,28 @@ java_check_regular_methods (class_decl)
          free (t);
        }
 
+      aflags = get_access_flags_from_decl (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. Do not issue this warning when
+        the match was found in java.lang.Object.  */
+      if (DECL_CONTEXT (found) != object_type_node
+         && ((aflags & 0x7) == 0)
+         && !class_in_current_package (DECL_CONTEXT (found))
+         && DECL_NAME (found) != clinit_identifier_node
+         && flag_not_overriding)
+        {
+         parse_warning_context 
+           (method_wfl, "Method `%s' in class `%s' does not "
+            "override the corresponding method in class `%s', which is "
+            "private to a different package",
+            lang_printable_name (found, 0),
+            IDENTIFIER_POINTER (DECL_NAME (class_decl)),
+            IDENTIFIER_POINTER (DECL_NAME 
+                                (TYPE_NAME (DECL_CONTEXT (found)))));
+         continue;
+       }
+
       /* Can't override final. Can't override static. */
       if (METHOD_FINAL (found) || METHOD_STATIC (found))
        {
@@ -4589,6 +4678,7 @@ java_check_regular_methods (class_decl)
               (DECL_NAME (TYPE_NAME (DECL_CONTEXT (found)))));
          continue;
        }
+
       /* Static method can't override instance method. */
       if (METHOD_STATIC (method))
        {
@@ -4602,7 +4692,6 @@ java_check_regular_methods (class_decl)
          continue;
        }
 
-      aflags = get_access_flags_from_decl (found);
       /* - Overriding/hiding public must be public
         - Overriding/hiding protected must be protected or public
          - If the overriden or hidden method has default (package)
@@ -4629,22 +4718,6 @@ java_check_regular_methods (class_decl)
         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. Do not issue this warning when
-        the match was found in java.lang.Object.  */
-      if (DECL_CONTEXT (found) != object_type_node 
-         && (!aflags || (aflags > ACC_PROTECTED))
-         && !class_in_current_package (DECL_CONTEXT (found))
-         && flag_not_overriding)
-       parse_warning_context 
-         (method_wfl, "Method `%s' in class `%s' does not "
-          "override the corresponding method in class `%s', which is "
-          "private to a different package",
-          lang_printable_name (found, 0),
-          IDENTIFIER_POINTER (DECL_NAME (class_decl)),
-          IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (DECL_CONTEXT (found)))));
-
       /* Inheriting multiple methods with the same signature. FIXME */
     }
   
@@ -5018,15 +5091,16 @@ read_import_dir (wfl)
                }
              *filename->ptr++ = '/';
 
-             for (; k < zipf->count;  k++, zipd = ZIPDIR_NEXT (zipd))
+             for (k = 0; k < zipf->count;  k++, zipd = ZIPDIR_NEXT (zipd))
                {
                  char *current_entry = ZIPDIR_FILENAME (zipd);
                  int current_entry_len = zipd->filename_length;
 
-                 if (strncmp (filename->data, current_entry, 
-                              BUFFER_LENGTH (filename)) != 0)
+                 if (current_entry_len >= BUFFER_LENGTH (filename)
+                     && strncmp (filename->data, current_entry, 
+                                 BUFFER_LENGTH (filename)) != 0)
                    continue;
-                 found += note_possible_classname (current_entry,
+                 found |= note_possible_classname (current_entry,
                                                    current_entry_len);
                }
            }
@@ -5059,7 +5133,7 @@ read_import_dir (wfl)
              len = strlen (direntp->d_name);
              buffer_grow (filename, len+1);
              strcpy (filename->ptr, d_name);
-             found += note_possible_classname (filename->data + entry_length,
+             found |= note_possible_classname (filename->data + entry_length,
                                                package_length+len+1);
            }
          if (dirp)
@@ -5101,9 +5175,9 @@ static int
 find_in_imports_on_demand (class_type)
      tree class_type;
 {
-  tree node, import, node_to_use;
+  tree node, import, node_to_use = NULL_TREE;
   int seen_once = -1;
-  tree cl;
+  tree cl = NULL_TREE;
 
   for (import = ctxp->import_demand_list; import; import = TREE_CHAIN (import))
     {
@@ -5249,13 +5323,13 @@ declare_local_variables (modifier, type, vlist)
   tree type_wfl = NULL_TREE;
   int must_chain = 0;
 
-  /* Push a new block if statement were seen between the last time we
+  /* Push a new block if statements were seen between the last time we
      pushed a block and now. Keep a cound of block to close */
-  if (BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (current_function_decl)))
+  if (BLOCK_EXPR_BODY (GET_CURRENT_BLOCK (current_function_decl)))
     {
-      tree body = DECL_FUNCTION_BODY (current_function_decl);
+      tree body = GET_CURRENT_BLOCK (current_function_decl);
       tree b = enter_block ();
-      BLOCK_EXPR_ORIGIN(b) = body;
+      BLOCK_EXPR_ORIGIN (b) = body;
     }
 
   if (modifier)
@@ -5317,6 +5391,11 @@ declare_local_variables (modifier, type, vlist)
       decl = build_decl (VAR_DECL, name, real_type);
       BLOCK_CHAIN_DECL (decl);
       
+      /* If doing xreferencing, replace the line number with the WFL
+         compound value */
+      if (flag_emit_xref)
+       DECL_SOURCE_LINE (decl) = EXPR_WFL_LINECOL (wfl);
+      
       /* Don't try to use an INIT statement when an error was found */
       if (init && java_error_count)
        init = NULL_TREE;
@@ -5456,7 +5535,6 @@ expand_start_java_method (fndecl)
       DECL_ARG_TYPE (tem) = type;
       layout_decl (tem, 0);
       pushdecl (tem);
-      INITIALIZED_P (tem) = 1; /* Parms are initialized */
       *ptr = tem;
       ptr = &TREE_CHAIN (tem);
       tem = next;
@@ -5464,7 +5542,6 @@ expand_start_java_method (fndecl)
   *ptr = NULL_TREE;
   pushdecl_force_head (DECL_ARGUMENTS (fndecl));
   lineno = DECL_SOURCE_LINE_FIRST (fndecl);
-  complete_start_java_method (fndecl); 
 }
 
 /* Terminate a function and expand its body.  */
@@ -5473,6 +5550,7 @@ static void
 source_end_java_method ()
 {
   tree fndecl = current_function_decl;
+  int flag_asynchronous_exceptions = asynchronous_exceptions;
 
   java_parser_context_save_global ();
   lineno = ctxp->last_ccb_indent1;
@@ -5480,9 +5558,16 @@ source_end_java_method ()
   /* Set EH language codes */
   java_set_exception_lang_code ();
 
+  /* Turn function bodies with only a NOP expr null, so they don't get
+     generated at all and we won't get warnings when using the -W
+     -Wall flags. */
+  if (BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (fndecl)) == empty_stmt_node)
+    BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (fndecl)) = NULL_TREE;
+
   /* Generate function's code */
   if (BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (fndecl))
-      && ! flag_emit_class_files)
+      && ! flag_emit_class_files
+      && ! flag_emit_xref)
     expand_expr_stmt (BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (fndecl)));
 
   /* pop out of its parameters */
@@ -5491,13 +5576,20 @@ source_end_java_method ()
   BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
 
   /* Generate rtl for function exit.  */
-  if (! flag_emit_class_files)
+  if (! flag_emit_class_files && ! flag_emit_xref)
     {
       lineno = DECL_SOURCE_LINE_LAST (fndecl);
       /* Emit catch-finally clauses */
       emit_handlers ();
       expand_function_end (input_filename, lineno, 0);
 
+      /* FIXME: If the current method contains any exception handlers,
+        force asynchronous_exceptions: this is necessary because signal
+        handlers in libjava may throw exceptions.  This is far from being
+        a perfect solution, but it's better than doing nothing at all.*/
+      if (catch_clauses)
+       asynchronous_exceptions = 1;
+
       /* Run the optimizers and output assembler code for this function. */
       rest_of_compilation (fndecl);
     }
@@ -5505,6 +5597,7 @@ source_end_java_method ()
   current_function_decl = NULL_TREE;
   /*  permanent_allocation (1); */
   java_parser_context_restore_global ();
+  asynchronous_exceptions = flag_asynchronous_exceptions;
 }
 
 /* Record EXPR in the current function block. Complements compound
@@ -5514,7 +5607,7 @@ tree
 java_method_add_stmt (fndecl, expr)
      tree fndecl, expr;
 {
-  return add_stmt_to_block (DECL_FUNCTION_BODY (fndecl), NULL_TREE, expr);
+  return add_stmt_to_block (GET_CURRENT_BLOCK (fndecl), NULL_TREE, expr);
 }
 
 static tree
@@ -5646,54 +5739,83 @@ void
 java_complete_expand_methods ()
 {
   tree current;
+
+  do_not_fold = flag_emit_xref;
   
   for (current = ctxp->class_list; current; current = TREE_CHAIN (current))
     {
+      int is_interface;
       tree class_type = CLASS_TO_HANDLE_TYPE (TREE_TYPE (current));
       tree decl;
 
       current_class = TREE_TYPE (current);
+      is_interface = CLASS_INTERFACE (TYPE_NAME (current_class));
 
       /* Initialize a new constant pool */
       init_outgoing_cpool ();
 
       /* We want <clinit> (if any) to be processed first. */
       decl = tree_last (TYPE_METHODS (class_type));
-      if (decl && DECL_NAME (decl) == clinit_identifier_node)
+      if (IS_CLINIT (decl))
        {
-         tree list = nreverse (TYPE_METHODS (class_type));
-         list = TREE_CHAIN (list);
-         TREE_CHAIN (decl) = NULL_TREE;
-         TYPE_METHODS (class_type) = chainon (decl, nreverse (list));
-       }
+         tree fbody = DECL_FUNCTION_BODY (decl);
+         tree list;
+         if (fbody != NULL_TREE)
+           {
+             /* First check if we can ignore empty <clinit> */
+             tree block_body = BLOCK_EXPR_BODY (fbody);
 
-      /* Don't process function bodies in interfaces */
-      if (!CLASS_INTERFACE (TYPE_NAME (current_class)))
-       for (decl = TYPE_METHODS (class_type); decl; decl = TREE_CHAIN (decl))
-         {
-           current_function_decl = decl;
-           /* Don't generate debug info on line zero when expanding a
-              generated constructor. */
-           if (DECL_CONSTRUCTOR_P (decl) && !DECL_FUNCTION_BODY (decl))
-             {
-               /* If we found errors, it's too dangerous to try to generate
-                  and expand a constructor */
-               if (!java_error_count)
-                 {
-                   restore_line_number_status (1);
-                   java_complete_expand_method (decl);
-                   restore_line_number_status (0);
+             current_this = NULL_TREE;
+             current_function_decl = decl;
+             if (block_body != NULL_TREE)
+               {
+                 /* Prevent the use of `this' inside <clinit> */
+                 ctxp->explicit_constructor_p = 1;
+
+                 block_body = java_complete_tree (block_body);
+                 ctxp->explicit_constructor_p = 0;
+                 BLOCK_EXPR_BODY (fbody) = block_body;
+                 if (block_body != NULL_TREE
+                     && TREE_CODE (block_body) == BLOCK
+                     && BLOCK_EXPR_BODY (block_body) == empty_stmt_node)
+                   decl = NULL_TREE;
+               }
+           }
+         list = nreverse (TREE_CHAIN (nreverse (TYPE_METHODS (class_type))));
+         if (decl != NULL_TREE)
+           {
+             TREE_CHAIN (decl) = list;
+             TYPE_METHODS (class_type) = decl;
+           }
+           else
+             TYPE_METHODS (class_type) = list;
+       }
+      
+      for (decl = TYPE_METHODS (class_type); decl; decl = TREE_CHAIN (decl))
+       {
+         current_function_decl = decl;
+         /* Don't generate debug info on line zero when expanding a
+            generated constructor. */
+         if (DECL_CONSTRUCTOR_P (decl) && !DECL_FUNCTION_BODY (decl))
+           {
+             /* If we found errors, it's too dangerous to try to
+                generate and expand a constructor */
+             if (!java_error_count)
+               {
+                 restore_line_number_status (1);
+                 java_complete_expand_method (decl);
+                 restore_line_number_status (0);
                  }
-             }
-           else if (METHOD_ABSTRACT (decl) || METHOD_NATIVE (decl))
-             continue;
-           else 
-             java_complete_expand_method (decl);
-         }
+           }
+         else if (METHOD_ABSTRACT (decl) || METHOD_NATIVE (decl))
+           continue;
+         else 
+           java_complete_expand_method (decl);
+       }
 
       /* Now verify constructor circularity (stop after the first one
          we find) */
-      if (!CLASS_INTERFACE (TYPE_NAME (current_class)))
+      if (!is_interface)
        for (decl = TYPE_METHODS (class_type); decl; decl = TREE_CHAIN (decl))
          if (DECL_CONSTRUCTOR_P (decl) && 
              verify_constructor_circularity (decl, decl))
@@ -5705,6 +5827,8 @@ java_complete_expand_methods ()
        {
          if (flag_emit_class_files)
            write_classfile (current_class);
+         if (flag_emit_xref)
+           expand_xref (current_class);
          else if (! flag_syntax_only)
            finish_class (current_class);
        }
@@ -5730,13 +5854,20 @@ java_complete_expand_method (mdecl)
     {
       tree fbody = DECL_FUNCTION_BODY (mdecl);
       tree block_body = BLOCK_EXPR_BODY (fbody);
+      tree exception_copy;
       expand_start_java_method (mdecl);
+      build_result_decl (mdecl);
 
       current_this 
        = (!METHOD_STATIC (mdecl) ? 
           BLOCK_EXPR_DECLS (DECL_FUNCTION_BODY (mdecl)) : NULL_TREE);
 
-      /* Purge the `throws' list of unchecked exceptions */
+      /* Purge the `throws' list of unchecked exceptions. If we're
+        doing xref, save a copy of the list and re-install it
+        later. */
+      if (flag_emit_xref)
+       exception_copy = copy_list (DECL_FUNCTION_THROWS (mdecl));
+
       purge_unchecked_exceptions (mdecl);
 
       /* Install exceptions thrown with `throws' */
@@ -5745,14 +5876,19 @@ java_complete_expand_method (mdecl)
       if (block_body != NULL_TREE)
        {
          block_body = java_complete_tree (block_body);
-         check_for_initialization (block_body);
+         if (!flag_emit_xref)
+           check_for_initialization (block_body);
+         ctxp->explicit_constructor_p = 0;
        }
       BLOCK_EXPR_BODY (fbody) = block_body;
 
       if ((block_body == NULL_TREE || CAN_COMPLETE_NORMALLY (block_body))
-         && TREE_CODE (TREE_TYPE (TREE_TYPE (mdecl))) != VOID_TYPE)
+         && TREE_CODE (TREE_TYPE (TREE_TYPE (mdecl))) != VOID_TYPE
+         && !flag_emit_xref)
        missing_return_error (current_function_decl);
 
+      complete_start_java_method (mdecl); 
+
       /* Don't go any further if we've found error(s) during the
          expansion */
       if (!java_error_count)
@@ -5767,6 +5903,9 @@ java_complete_expand_method (mdecl)
       POP_EXCEPTIONS();
       if (currently_caught_type_list)
        fatal ("Exception list non empty - java_complete_expand_method");
+
+      if (flag_emit_xref)
+       DECL_FUNCTION_THROWS (mdecl) = exception_copy;
     }
 }
 
@@ -5885,7 +6024,7 @@ java_expand_finals ()
 void
 java_expand_classes ()
 {
-  int save_error_count = java_error_count;
+  int save_error_count = 0;
   java_parse_abort_on_error ();
   if (!(ctxp = ctxp_for_generation))
     return;
@@ -5922,7 +6061,7 @@ make_qualified_primary (primary, right, location)
      different form than a SUPER. Turn THIS into something symbolic */
   if (TREE_CODE (primary) == THIS_EXPR)
     {
-      wfl = build_wfl_node (this_identifier_node, input_filename, 0, 0);
+      wfl = build_wfl_node (this_identifier_node);
       EXPR_WFL_LINECOL (wfl) = EXPR_WFL_LINECOL (primary);
       wfl = make_qualified_name (wfl, right, location);
       PRIMARY_P (wfl) = 1;
@@ -6054,12 +6193,7 @@ resolve_expression_name (id, orig)
                 a static variable. */
              if (!fs && METHOD_STATIC (current_function_decl))
                {
-                 parse_error_context 
-                   (id, "Can't make a static reference to nonstatic variable "
-                    "`%s' in class `%s'",
-                    IDENTIFIER_POINTER (name),
-                    IDENTIFIER_POINTER (DECL_NAME 
-                                        (TYPE_NAME (current_class))));
+                 static_ref_err (id, name, current_class);
                  return error_mark_node;
                }
              /* Instance variables can't appear as an argument of
@@ -6074,9 +6208,9 @@ resolve_expression_name (id, orig)
 
              /* Otherwise build what it takes to access the field */
              decl = build_field_ref ((fs ? NULL_TREE : current_this),
-                                     current_class, name);
-             if (fs && !flag_emit_class_files)
-               decl = build_class_init (current_class, decl);
+                                     DECL_CONTEXT (decl), name);
+             if (fs && !flag_emit_class_files && !flag_emit_xref)
+               decl = build_class_init (DECL_CONTEXT (decl), decl);
              /* We may be asked to save the real field access node */
              if (orig)
                *orig = decl;
@@ -6104,6 +6238,17 @@ resolve_expression_name (id, orig)
   return error_mark_node;
 }
 
+static void
+static_ref_err (wfl, field_id, class_type)
+    tree wfl, field_id, class_type;
+{
+  parse_error_context 
+    (wfl, 
+     "Can't make a static reference to nonstatic variable `%s' in class `%s'",
+     IDENTIFIER_POINTER (field_id), 
+     IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (class_type))));
+}
+
 /* 15.10.1 Field Acess Using a Primary and/or Expression Name.
    We return something suitable to generate the field access. We also
    return the field decl in FIELD_DECL and its type in FIELD_TYPE.  If
@@ -6124,7 +6269,7 @@ resolve_field_access (qual_wfl, field_decl, field_type)
 
   /* Resolve the LENGTH field of an array here */
   if (DECL_NAME (decl) == length_identifier_node && TYPE_ARRAY_P (type_found)
-      && ! flag_emit_class_files)
+      && ! flag_emit_class_files && ! flag_emit_xref)
     {
       tree length = build_java_array_length_access (where_found);
       field_ref =
@@ -6149,16 +6294,18 @@ resolve_field_access (qual_wfl, field_decl, field_type)
          static_final_found = 1;
        }
       else
-       field_ref = build_field_ref ((is_static ? NULL_TREE : where_found), 
+       field_ref = build_field_ref ((is_static && !flag_emit_xref? 
+                                     NULL_TREE : where_found), 
                                     type_found, DECL_NAME (decl));
       if (field_ref == error_mark_node)
        return error_mark_node;
-      if (is_static && !static_final_found && !flag_emit_class_files)
+      if (is_static && !static_final_found 
+         && !flag_emit_class_files && !flag_emit_xref)
        {
          field_ref = build_class_init (type_found, field_ref);
          /* If the static field was identified by an expression that
             needs to be generated, make the field access a compound
-            expression whose first part of the evaluation of the
+            expression whose first part is the evaluation of the
             field selector part. */
          if (where_found && TREE_CODE (where_found) != TYPE_DECL 
              && TREE_CODE (where_found) != RECORD_TYPE)
@@ -6305,6 +6452,7 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found)
        default:
          /* Fix for -Wall Just go to the next statement. Don't
              continue */
+         break;
        }
 
       /* If we fall here, we weren't processing a (static) function call. */
@@ -6394,7 +6542,7 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found)
              parse_error_context 
                (qual_wfl, "Can't access %s field `%s.%s' from `%s'",
                 java_accstring_lookup (get_access_flags_from_decl (decl)),
-                IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))),
+                GET_TYPE_NAME (type),
                 IDENTIFIER_POINTER (DECL_NAME (decl)),
                 IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (current_class))));
              return 1;
@@ -6418,8 +6566,17 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found)
              decl = QUAL_RESOLUTION (q);
              if (!type)
                {
-                 if (!FIELD_STATIC (decl))
-                   *where_found = current_this;
+                 if (TREE_CODE (decl) == FIELD_DECL && !FIELD_STATIC (decl))
+                   {
+                     if (current_this)
+                       *where_found = current_this;
+                     else
+                       {
+                         static_ref_err (qual_wfl, DECL_NAME (decl),
+                                         current_class);
+                         return 1;
+                       }
+                   }
                  else
                    {
                      *where_found = TREE_TYPE (decl);
@@ -6450,15 +6607,18 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found)
                  return 1;
                }
              
-             if (!(field_decl = 
-                   lookup_field_wrapper (type, EXPR_WFL_NODE (qual_wfl))))
+             field_decl = lookup_field_wrapper (type,
+                                                EXPR_WFL_NODE (qual_wfl));
+             if (field_decl == NULL_TREE)
                {
                  parse_error_context 
-                   (qual_wfl, "No variable `%s' defined in class `%s'",
+                   (qual_wfl, "No variable `%s' defined in type `%s'",
                     IDENTIFIER_POINTER (EXPR_WFL_NODE (qual_wfl)), 
-                    IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))));
+                    GET_TYPE_NAME (type));
                  return 1;
                }
+             if (field_decl == error_mark_node)
+               return 1;
 
              /* Layout the type of field_decl, since we may need
                  it. Don't do primitive types or loaded classes. The
@@ -6483,7 +6643,7 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found)
                     "Can't access %s field `%s.%s' from `%s'",
                     java_accstring_lookup 
                       (get_access_flags_from_decl (field_decl)),
-                    IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))),
+                    GET_TYPE_NAME (type),
                     IDENTIFIER_POINTER (DECL_NAME (field_decl)),
                     IDENTIFIER_POINTER 
                       (DECL_NAME (TYPE_NAME (current_class))));
@@ -6499,11 +6659,7 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found)
              if (!from_super && from_type 
                  && !TYPE_INTERFACE_P (type) && !is_static)
                {
-                 parse_error_context 
-                   (qual_wfl, "Can't make a static reference to nonstatic "
-                    "variable `%s' in class `%s'",
-                    IDENTIFIER_POINTER (EXPR_WFL_NODE (qual_wfl)),
-                    IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))));
+                 static_ref_err (qual_wfl, EXPR_WFL_NODE (qual_wfl), type);
                  return 1;
                }
              from_cast = from_super = 0;
@@ -6991,7 +7147,7 @@ patch_invoke (patch, method, args)
        TREE_TYPE (TREE_VALUE (ta)) != TREE_VALUE (t))
       TREE_VALUE (ta) = convert (TREE_VALUE (t), TREE_VALUE (ta));
   
-  if (flag_emit_class_files)
+  if (flag_emit_class_files || flag_emit_xref)
     func = method;
   else
     {
@@ -7037,7 +7193,7 @@ patch_invoke (patch, method, args)
     {
       tree class = DECL_CONTEXT (method);
       tree c1, saved_new, size, new;
-      if (flag_emit_class_files)
+      if (flag_emit_class_files || flag_emit_xref)
        {
          TREE_TYPE (patch) = build_pointer_type (class);
          return patch;
@@ -7166,40 +7322,101 @@ find_applicable_accessible_methods_list (lc, class, name, arglist)
      int lc;
      tree class, name, arglist;
 {
-  tree method;
   tree list = NULL_TREE, all_list = NULL_TREE;
 
-  while (class != NULL_TREE)
+  /* Search interfaces */
+  if (CLASS_INTERFACE (TYPE_NAME (class)))
     {
-      for (method = TYPE_METHODS (class);
-          method != NULL_TREE;  method = TREE_CHAIN (method))
+      static tree searched_interfaces = NULL_TREE;
+      static int search_not_done = 0;
+      int i, n;
+      tree basetype_vec = TYPE_BINFO_BASETYPES (class);
+
+      /* Have we searched this interface already? */
+      if (searched_interfaces)
+       {  
+         tree current;  
+         for (current = searched_interfaces; 
+              current; current = TREE_CHAIN (current))
+           if (TREE_VALUE (current) == class)
+             return NULL;
+       }
+      searched_interfaces = tree_cons (NULL_TREE, class, searched_interfaces);
+
+      search_applicable_methods_list 
+       (lc, TYPE_METHODS (class), name, arglist, &list, &all_list);
+
+      n = TREE_VEC_LENGTH (basetype_vec);
+      for (i = 0; i < n; i++)
        {
-         if (lc && !DECL_CONSTRUCTOR_P (method))
-           continue;
-         else if (!lc && (DECL_CONSTRUCTOR_P (method)
-                          || (GET_METHOD_NAME (method) != name)))
+         tree t = BINFO_TYPE (TREE_VEC_ELT (basetype_vec, i));
+         tree rlist;
+
+         /* Skip java.lang.Object (we'll search it once later.) */
+         if (t == object_type_node)
            continue;
-         
-         if (argument_types_convertible (method, arglist))
-           {
-             /* Retain accessible methods only */
-             if (!not_accessible_p (DECL_CONTEXT (current_function_decl), 
-                                    method, 0))
-               list = tree_cons (NULL_TREE, method, list);
-             else
-             /* Also retain all selected method here */
-               all_list = tree_cons (NULL_TREE, method, list);
-           }
+
+         search_not_done++;
+         rlist = find_applicable_accessible_methods_list (lc,  t, name, 
+                                                          arglist);
+         all_list = chainon (rlist, (list ? list : all_list)); 
+         search_not_done--;
+       }
+
+      /* We're done. Reset the searched interfaces list and finally search
+         java.lang.Object */
+      if (!search_not_done)
+       {  
+         searched_interfaces = NULL_TREE;  
+         search_applicable_methods_list (lc, TYPE_METHODS (object_type_node),
+                                         name, arglist, &list, &all_list);
        }
-      /* When dealing with constructor, stop here, otherwise search
-         other classes */
-      class = (lc ? NULL_TREE : CLASSTYPE_SUPER (class));
     }
+  /* Search classes */
+  else
+    while (class != NULL_TREE)
+      {
+       search_applicable_methods_list 
+         (lc, TYPE_METHODS (class), name, arglist, &list, &all_list);
+       class = (lc ? NULL_TREE : CLASSTYPE_SUPER (class));
+      }
+
   /* Either return the list obtained or all selected (but
      inaccessible) methods for better error report. */
   return (!list ? all_list : list);
 }
 
+/* Effectively search for the approriate method in method */
+
+static void 
+search_applicable_methods_list(lc, method, name, arglist, list, all_list)
+     int lc;
+     tree method, name, arglist;
+     tree *list, *all_list;
+{
+  for (; method; method = TREE_CHAIN (method))
+    {
+      /* When dealing with constructor, stop here, otherwise search
+         other classes */
+      if (lc && !DECL_CONSTRUCTOR_P (method))
+       continue;
+      else if (!lc && (DECL_CONSTRUCTOR_P (method) 
+                      || (GET_METHOD_NAME (method) != name)))
+       continue;
+         
+      if (argument_types_convertible (method, arglist))
+       {
+         /* Retain accessible methods only */
+         if (!not_accessible_p (DECL_CONTEXT (current_function_decl), 
+                                method, 0))
+           *list = tree_cons (NULL_TREE, method, *list);
+         else
+           /* Also retain all selected method here */
+           *all_list = tree_cons (NULL_TREE, method, *list);
+       }
+    }
+}    
+
 /* 15.11.2.2 Choose the Most Specific Method */
 
 static tree
@@ -7502,7 +7719,8 @@ java_complete_tree (node)
 {
   node = java_complete_lhs (node);
   if (TREE_CODE (node) == VAR_DECL && FIELD_STATIC (node)
-      && FIELD_FINAL (node) && DECL_INITIAL (node) != NULL_TREE)
+      && FIELD_FINAL (node) && DECL_INITIAL (node) != NULL_TREE
+      && !flag_emit_xref)
     {
       tree value = DECL_INITIAL (node);
       DECL_INITIAL (node) = NULL_TREE;
@@ -7514,6 +7732,22 @@ java_complete_tree (node)
   return node;
 }
 
+static tree
+java_stabilize_reference (node)
+     tree node;
+{
+  if (TREE_CODE (node) == COMPOUND_EXPR)
+    {
+      tree op0 = TREE_OPERAND (node, 0);
+      tree op1 = TREE_OPERAND (node, 1);
+      TREE_OPERAND (node, 0) = save_expr (op0);
+      TREE_OPERAND (node, 1) = java_stabilize_reference (op1);
+      return node;
+    }
+  else
+    return stabilize_reference (node);
+}
+
 /* Patch tree nodes in a function body. When a BLOCK is found, push
    local variable decls if present.
    Same as java_complete_tree, but does not resolve static finals to values. */
@@ -7545,7 +7779,6 @@ java_complete_lhs (node)
        {
          DECL_CONTEXT (cn) = current_function_decl;
          IDENTIFIER_LOCAL_VALUE (DECL_NAME (cn)) = cn;
-         INITIALIZED_P (cn) = 0;
        }
       if (BLOCK_EXPR_BODY (node) == NULL_TREE)
          CAN_COMPLETE_NORMALLY (node) = 1;
@@ -7576,11 +7809,19 @@ java_complete_lhs (node)
          /* Now do the actual complete, without deep recursion for
              long blocks. */
          ptr = &BLOCK_EXPR_BODY (node);
-         while (TREE_CODE (*ptr) == COMPOUND_EXPR)
+         while (TREE_CODE (*ptr) == COMPOUND_EXPR
+                && TREE_OPERAND (*ptr, 1) != empty_stmt_node)
            {
              tree cur = java_complete_tree (TREE_OPERAND (*ptr, 0));
              tree *next = &TREE_OPERAND (*ptr, 1);
              TREE_OPERAND (*ptr, 0) = cur;
+             if (cur == empty_stmt_node)
+               {
+                 /* Optimization;  makes it easier to detect empty bodies.
+                    Most useful for <clinit> with all-constant initializer. */
+                 *ptr = *next;
+                 continue;
+               }
              if (TREE_CODE (cur) == ERROR_MARK)
                error_seen++;
              else if (! CAN_COMPLETE_NORMALLY (cur))
@@ -7596,8 +7837,7 @@ java_complete_lhs (node)
                        break;
                    }
                  if (TREE_CODE (wfl_op2) != CASE_EXPR
-                     && TREE_CODE (wfl_op2) != DEFAULT_EXPR
-                     && wfl_op2 != empty_stmt_node)
+                     && TREE_CODE (wfl_op2) != DEFAULT_EXPR)
                    unreachable_stmt_error (*ptr);
                }
              ptr = next;
@@ -7642,13 +7882,15 @@ java_complete_lhs (node)
     case CLEANUP_POINT_EXPR:
       COMPLETE_CHECK_OP_0 (node);
       TREE_TYPE (node) = void_type_node;
-      CAN_COMPLETE_NORMALLY (node) = CAN_COMPLETE_NORMALLY (TREE_OPERAND (node, 0));
+      CAN_COMPLETE_NORMALLY (node) = 
+       CAN_COMPLETE_NORMALLY (TREE_OPERAND (node, 0));
       return node;
 
     case WITH_CLEANUP_EXPR:
       COMPLETE_CHECK_OP_0 (node);
       COMPLETE_CHECK_OP_2 (node);
-      CAN_COMPLETE_NORMALLY (node) = CAN_COMPLETE_NORMALLY (TREE_OPERAND (node, 0));
+      CAN_COMPLETE_NORMALLY (node) = 
+       CAN_COMPLETE_NORMALLY (TREE_OPERAND (node, 0));
       TREE_TYPE (node) = void_type_node;
       return node;
 
@@ -7658,7 +7900,13 @@ java_complete_lhs (node)
        COMPLETE_CHECK_OP_1 (node);
       TREE_TYPE (node) = void_type_node;
       POP_LABELED_BLOCK ();
-      if (CAN_COMPLETE_NORMALLY (LABELED_BLOCK_BODY (node)))
+
+      if (LABELED_BLOCK_BODY (node) == empty_stmt_node)
+       {
+         LABELED_BLOCK_BODY (node) = NULL_TREE;
+         CAN_COMPLETE_NORMALLY (node) = 1;
+       }
+      else if (CAN_COMPLETE_NORMALLY (LABELED_BLOCK_BODY (node)))
        CAN_COMPLETE_NORMALLY (node) = 1;
       return node;
 
@@ -7675,7 +7923,7 @@ java_complete_lhs (node)
       /* First, the case expression must be constant */
       cn = fold (cn);
 
-      if (!TREE_CONSTANT (cn))
+      if (!TREE_CONSTANT (cn) && !flag_emit_xref)
        {
          EXPR_WFL_LINECOL (wfl_operator) = EXPR_WFL_LINECOL (node);
          parse_error_context (node, "Constant expression required");
@@ -7740,15 +7988,18 @@ java_complete_lhs (node)
        node = patch_switch_statement (node);
 
       if (TREE_OPERAND (node, 0) == error_mark_node)
-       return error_mark_node;
-      TREE_TYPE (nn) = TREE_TYPE (node) = void_type_node;
-      /* If we returned something different, that's because we
-         inserted a label. Pop the label too. */
-      if (nn != node)
+       nn = error_mark_node;
+      else
        {
-         if (CAN_COMPLETE_NORMALLY (node))
-           CAN_COMPLETE_NORMALLY (nn) = 1;
-         POP_LABELED_BLOCK ();
+         TREE_TYPE (nn) = TREE_TYPE (node) = void_type_node;
+         /* If we returned something different, that's because we
+            inserted a label. Pop the label too. */
+         if (nn != node)
+           {
+             if (CAN_COMPLETE_NORMALLY (node))
+               CAN_COMPLETE_NORMALLY (nn) = 1;
+             POP_LABELED_BLOCK ();
+           }
        }
       POP_LOOP ();
       return nn;
@@ -7787,26 +8038,30 @@ java_complete_lhs (node)
       wfl_op2 = TREE_OPERAND (node, 1);
       TREE_OPERAND (node, 0) = nn = 
        java_complete_tree (TREE_OPERAND (node, 0));
-      if (! CAN_COMPLETE_NORMALLY (nn) && TREE_CODE (nn) != ERROR_MARK
-         && wfl_op2 != empty_stmt_node)
-       {
-         /* An unreachable condition in a do-while statement
-            is *not* (technically) an unreachable statement. */
-         nn = wfl_op2;
-         if (TREE_CODE (nn) == EXPR_WITH_FILE_LOCATION)
-           nn = EXPR_WFL_NODE (nn);
-         if (TREE_CODE (nn) != EXIT_EXPR)
+      if (wfl_op2 == empty_stmt_node)
+       CAN_COMPLETE_NORMALLY (node) = CAN_COMPLETE_NORMALLY (nn);
+      else
+       {
+         if (! CAN_COMPLETE_NORMALLY (nn) && TREE_CODE (nn) != ERROR_MARK)
            {
-             SET_WFL_OPERATOR (wfl_operator, node, wfl_op2);
-             parse_error_context (wfl_operator, "Unreachable statement");
+             /* An unreachable condition in a do-while statement
+                is *not* (technically) an unreachable statement. */
+             nn = wfl_op2;
+             if (TREE_CODE (nn) == EXPR_WITH_FILE_LOCATION)
+               nn = EXPR_WFL_NODE (nn);
+             if (TREE_CODE (nn) != EXIT_EXPR)
+               {
+                 SET_WFL_OPERATOR (wfl_operator, node, wfl_op2);
+                 parse_error_context (wfl_operator, "Unreachable statement");
+               }
            }
+         TREE_OPERAND (node, 1) = java_complete_tree (TREE_OPERAND (node, 1));
+         if (TREE_OPERAND (node, 1) == error_mark_node)
+           return error_mark_node;
+         CAN_COMPLETE_NORMALLY (node)
+           = CAN_COMPLETE_NORMALLY (TREE_OPERAND (node, 1));
        }
-      TREE_OPERAND (node, 1) = java_complete_tree (TREE_OPERAND (node, 1));
-      if (TREE_OPERAND (node, 1) == error_mark_node)
-       return error_mark_node;
       TREE_TYPE (node) = TREE_TYPE (TREE_OPERAND (node, 1));
-      CAN_COMPLETE_NORMALLY (node)
-       = CAN_COMPLETE_NORMALLY (TREE_OPERAND (node, 1));
       break;
 
     case RETURN_EXPR:
@@ -7817,7 +8072,17 @@ java_complete_lhs (node)
       if (!EXPR_WFL_NODE (node) /* Or a PRIMARY flag ? */
          || TREE_CODE (EXPR_WFL_NODE (node)) == IDENTIFIER_NODE)
        {
+         tree wfl = node;
          node = resolve_expression_name (node, NULL);
+         if (node == error_mark_node)
+           return node;
+         /* Keep line number information somewhere were it doesn't
+            disrupt the completion process. */
+         if (flag_emit_xref)
+           {
+             EXPR_WFL_NODE (wfl) = TREE_OPERAND (node, 1);
+             TREE_OPERAND (node, 1) = wfl;
+           }
          CAN_COMPLETE_NORMALLY (node) = 1;
        }
       else
@@ -7828,9 +8093,14 @@ java_complete_lhs (node)
          body = java_complete_tree (EXPR_WFL_NODE (node));
          lineno = save_lineno;
          EXPR_WFL_NODE (node) = body;
-         TREE_SIDE_EFFECTS (node) = 1;
+         TREE_SIDE_EFFECTS (node) = TREE_SIDE_EFFECTS (body);
          CAN_COMPLETE_NORMALLY (node) = CAN_COMPLETE_NORMALLY (body);
-         if (EXPR_WFL_NODE (node) == error_mark_node)
+         if (body == empty_stmt_node)
+           {
+             /* Optimization;  makes it easier to detect empty bodies. */
+             return body;
+           }
+         if (body == error_mark_node)
            {
              /* Its important for the evaluation of assignment that
                 this mark on the TREE_TYPE is propagated. */
@@ -7868,7 +8138,8 @@ java_complete_lhs (node)
       /* They complete the array creation expression, if no errors
          were found. */
       CAN_COMPLETE_NORMALLY (node) = 1;
-      return (flag ? error_mark_node : patch_newarray (node));
+      return (flag ? error_mark_node
+             : force_evaluation_order (patch_newarray (node)));
 
     case NEW_CLASS_EXPR:
     case CALL_EXPR:
@@ -7892,56 +8163,64 @@ java_complete_lhs (node)
              tree_cons (wfl, decl, 
                         DECL_CONSTRUCTOR_CALLS (current_function_decl));
          CAN_COMPLETE_NORMALLY (node) = 1;
-         return node;
+         return force_evaluation_order (node);
        }
 
     case MODIFY_EXPR:
       /* Save potential wfls */
       wfl_op1 = TREE_OPERAND (node, 0);
+      TREE_OPERAND (node, 0) = nn = java_complete_lhs (wfl_op1);
+      if (MODIFY_EXPR_FROM_INITIALIZATION_P (node)
+         && TREE_CODE (nn) == VAR_DECL && TREE_STATIC (nn)
+         && DECL_INITIAL (nn) != NULL_TREE)
+       {
+         tree value = fold_constant_for_init (nn, nn);
+         if (value != NULL_TREE)
+           {
+             tree type = TREE_TYPE (value);
+             if (JPRIMITIVE_TYPE_P (type) || type == string_ptr_type_node)
+               return empty_stmt_node;
+           }
+         DECL_INITIAL (nn) = NULL_TREE;
+       }
       wfl_op2 = TREE_OPERAND (node, 1);
-      TREE_OPERAND (node, 0) = java_complete_lhs (wfl_op1);
+
       if (TREE_OPERAND (node, 0) == error_mark_node)
        return error_mark_node;
 
       if (COMPOUND_ASSIGN_P (wfl_op2))
        {
-         tree lvalue;
-         tree other = 
-           java_complete_tree (TREE_OPERAND (wfl_op2, 0));
+         tree lvalue = java_stabilize_reference (TREE_OPERAND (node, 0)); 
 
          /* Hand stablize the lhs on both places */
-         lvalue = stabilize_reference (other); 
          TREE_OPERAND (node, 0) = lvalue;
          TREE_OPERAND (TREE_OPERAND (node, 1), 0) = lvalue;
+
+         /* Now complete the RHS. We write it back later on. */
+         nn = java_complete_tree (TREE_OPERAND (node, 1));
+
+         if ((cn = patch_string (nn)))
+           nn = cn;
+
+         /* The last part of the rewrite for E1 op= E2 is to have 
+            E1 = (T)(E1 op E2), with T being the type of E1. */
+         nn = java_complete_tree (build_cast (EXPR_WFL_LINECOL (wfl_op2), 
+                                              TREE_TYPE (lvalue), nn));
        }
 
       /* If we're about to patch a NEW_ARRAY_INIT, we call a special
         function to complete this RHS */
-      if (TREE_CODE (wfl_op2) == NEW_ARRAY_INIT)
+      else if (TREE_CODE (wfl_op2) == NEW_ARRAY_INIT)
        nn = patch_new_array_init (TREE_TYPE (TREE_OPERAND (node, 0)),
                                   TREE_OPERAND (node, 1));
+      /* Otherwise we simply complete the RHS */
       else
        nn = java_complete_tree (TREE_OPERAND (node, 1));
 
-      /* There are cases where the type of RHS is fixed. In those
-        cases, if the evaluation of the RHS fails, we further the
-        evaluation of the assignment to detect more errors. */
       if (nn == error_mark_node)
-       {
-         /* It's hopeless, but we can further things on to discover
-            an error during the assignment. In any cases, the
-            assignment operation fails. */
-         if (TREE_CODE (TREE_OPERAND (node, 1)) != EXPR_WITH_FILE_LOCATION
-             && TREE_CODE (TREE_OPERAND (node, 1)) != NEW_ARRAY_INIT
-             && TREE_TYPE (TREE_OPERAND (node, 1)) != error_mark_node)
-           patch_assignment (node, wfl_op1, wfl_op2);
-
-         /* Now, we still mark the lhs as initialized */
-         if (JDECL_P (TREE_OPERAND (node, 0)))
-           INITIALIZED_P (TREE_OPERAND (node, 0)) = 1;
+       return error_mark_node;
 
-         return error_mark_node;
-       }
+      /* Write back the RHS as we evaluated it. */
       TREE_OPERAND (node, 1) = nn;
 
       /* In case we're handling = with a String as a RHS, we need to
@@ -7951,16 +8230,6 @@ java_complete_lhs (node)
        TREE_OPERAND (node, 1) = nn;
       node = patch_assignment (node, wfl_op1, wfl_op2);
       CAN_COMPLETE_NORMALLY (node) = 1;
-
-      /* Before returning the node, in the context of a static field
-         assignment in <clinit>, we may want to carray further
-         optimizations. (VAR_DECL means it's a static field. See
-         add_field. */
-      if (DECL_NAME (current_function_decl) == clinit_identifier_node
-         && MODIFY_EXPR_FROM_INITIALIZATION_P (node)
-         && TREE_CODE (TREE_OPERAND (node, 0)) == VAR_DECL)
-       node = patch_initialized_static_field (node);
-
       return node;
 
     case MULT_EXPR:
@@ -7990,22 +8259,33 @@ java_complete_lhs (node)
       CAN_COMPLETE_NORMALLY (node) = 1;
       /* Don't complete string nodes if dealing with the PLUS operand. */
       if (TREE_CODE (node) != PLUS_EXPR || !JSTRING_P (wfl_op1))
-       {
-         TREE_OPERAND (node, 0) = java_complete_tree (wfl_op1);
-         if (TREE_OPERAND (node, 0) == error_mark_node)
-           return error_mark_node;
-       }
+        {
+          nn = java_complete_tree (wfl_op1);
+          if (nn == error_mark_node)
+            return error_mark_node;
+          if ((cn = patch_string (nn)))
+            nn = cn;
+          TREE_OPERAND (node, 0) = nn;
+        }
       if (TREE_CODE (node) != PLUS_EXPR || !JSTRING_P (wfl_op2))
-       {
-         TREE_OPERAND (node, 1) = java_complete_tree (wfl_op2);
-         if (TREE_OPERAND (node, 1) == error_mark_node)
-           return error_mark_node;
-       }
-      return patch_binop (node, wfl_op1, wfl_op2);
+        {
+          nn = java_complete_tree (wfl_op2);
+          if (nn == error_mark_node)
+            return error_mark_node;
+          if ((cn = patch_string (nn)))
+            nn = cn;
+          TREE_OPERAND (node, 1) = nn;
+        }
+      return force_evaluation_order (patch_binop (node, wfl_op1, wfl_op2));
 
     case INSTANCEOF_EXPR:
       wfl_op1 = TREE_OPERAND (node, 0);
       COMPLETE_CHECK_OP_0 (node);
+      if (flag_emit_xref)
+       {
+         TREE_TYPE (node) = boolean_type_node;
+         return node;
+       }
       return patch_binop (node, wfl_op1, TREE_OPERAND (node, 1));
 
     case UNARY_PLUS_EXPR:
@@ -8035,14 +8315,14 @@ java_complete_lhs (node)
       TREE_OPERAND (node, 0) = java_complete_tree (wfl_op1);
       if (TREE_OPERAND (node, 0) == error_mark_node)
        return error_mark_node;
-      if (!flag_emit_class_files)
+      if (!flag_emit_class_files && !flag_emit_xref)
        TREE_OPERAND (node, 0) = save_expr (TREE_OPERAND (node, 0));
       /* The same applies to wfl_op2 */
       wfl_op2 = TREE_OPERAND (node, 1);
       TREE_OPERAND (node, 1) = java_complete_tree (wfl_op2);
       if (TREE_OPERAND (node, 1) == error_mark_node)
        return error_mark_node;
-      if (!flag_emit_class_files)
+      if (!flag_emit_class_files && !flag_emit_xref)
        TREE_OPERAND (node, 1) = save_expr (TREE_OPERAND (node, 1));
       return patch_array_ref (node);
 
@@ -8192,7 +8472,12 @@ enter_a_block (b)
 {
   tree fndecl = current_function_decl; 
 
-  if (!DECL_FUNCTION_BODY (fndecl))
+  if (!fndecl) {
+    BLOCK_SUPERCONTEXT (b) = current_static_block;
+    current_static_block = b;
+  }
+
+  else if (!DECL_FUNCTION_BODY (fndecl))
     {
       BLOCK_SUPERCONTEXT (b) = fndecl;
       DECL_FUNCTION_BODY (fndecl) = b;
@@ -8212,11 +8497,20 @@ enter_a_block (b)
 static tree
 exit_block ()
 {
-  tree b = DECL_FUNCTION_BODY (current_function_decl);
-
-  if (BLOCK_SUPERCONTEXT (b) != current_function_decl)
-    DECL_FUNCTION_BODY (current_function_decl) = BLOCK_SUPERCONTEXT (b);
+  tree b;
+  if (current_function_decl)
+    {
+      b = DECL_FUNCTION_BODY (current_function_decl);
+      if (BLOCK_SUPERCONTEXT (b) != current_function_decl)
+       DECL_FUNCTION_BODY (current_function_decl) = BLOCK_SUPERCONTEXT (b);
+    }
+  else
+    {
+      b = current_static_block;
 
+      if (BLOCK_SUPERCONTEXT (b))
+       current_static_block = BLOCK_SUPERCONTEXT (b);
+    }
   return b;
 }
 
@@ -8228,7 +8522,7 @@ static tree
 lookup_name_in_blocks (name)
      tree name;
 {
-  tree b = DECL_FUNCTION_BODY (current_function_decl);
+  tree b = GET_CURRENT_BLOCK (current_function_decl);
 
   while (b != current_function_decl)
     {
@@ -8250,7 +8544,7 @@ lookup_name_in_blocks (name)
 static void
 maybe_absorb_scoping_blocks ()
 {
-  while (BLOCK_EXPR_ORIGIN (DECL_FUNCTION_BODY (current_function_decl)))
+  while (BLOCK_EXPR_ORIGIN (GET_CURRENT_BLOCK (current_function_decl)))
     {
       tree b = exit_block ();
       java_method_add_stmt (current_function_decl, b);
@@ -8273,8 +8567,7 @@ build_super_invocation ()
     return empty_stmt_node;
   else
     {
-      tree super_wfl = build_wfl_node (super_identifier_node, 
-                                      input_filename, 0, 0);
+      tree super_wfl = build_wfl_node (super_identifier_node);
       return build_method_invocation (super_wfl, NULL_TREE);
     }
 }
@@ -8290,8 +8583,7 @@ build_this_super_qualified_invocation (use_this, name, args, lloc, rloc)
 {
   tree invok;
   tree wfl = 
-    build_wfl_node ((use_this ? this_identifier_node : super_identifier_node),
-                   input_filename, 0, 0);
+    build_wfl_node (use_this ? this_identifier_node : super_identifier_node);
   EXPR_WFL_LINECOL (wfl) = lloc;
   invok = build_method_invocation (name, args);
   return make_qualified_primary (wfl, invok, rloc);
@@ -8371,14 +8663,15 @@ print_int_node (node)
   return buffer;
 }
 
-/* Return 1 if you an assignment of a FINAL is attempted */
+/* Return 1 if an assignment to a FINAL is attempted in a non suitable
+   context.  */
 
 static int
 check_final_assignment (lvalue, wfl)
      tree lvalue, wfl;
 {
-  if (JDECL_P (lvalue) && FIELD_FINAL (lvalue) &&
-      DECL_NAME (current_function_decl) != clinit_identifier_node)
+  if (JDECL_P (lvalue) 
+      && FIELD_FINAL (lvalue) && !IS_CLINIT (current_function_decl))
     {
       parse_error_context 
         (wfl, "Can't assign a value to the final variable `%s'",
@@ -8436,7 +8729,6 @@ patch_assignment (node, wfl_op1, wfl_op2)
   /* Lhs can be a named variable */
   if (JDECL_P (lvalue))
     {
-      INITIALIZED_P (lvalue) = 1;
       lhs_type = TREE_TYPE (lvalue);
     }
   /* Or Lhs can be a array acccess. Should that be lvalue ? FIXME +
@@ -8455,13 +8747,17 @@ patch_assignment (node, wfl_op1, wfl_op2)
   /* Otherwise, we might want to try to write into an optimized static
      final, this is an of a different nature, reported further on. */
   else if (TREE_CODE (wfl_op1) == EXPR_WITH_FILE_LOCATION
-          && resolve_expression_name (wfl_op1, &llvalue)
-          && check_final_assignment (llvalue, wfl_op1))
+          && resolve_expression_name (wfl_op1, &llvalue))
     {
-      error_found = 1;
-      /* What we should do instead is resetting the all the flags
-         previously set, exchange lvalue for llvalue and continue. */
-      return error_mark_node;
+      if (check_final_assignment (llvalue, wfl_op1))
+       {
+         /* What we should do instead is resetting the all the flags
+            previously set, exchange lvalue for llvalue and continue. */
+         error_found = 1;
+         return error_mark_node;
+       }
+      else 
+       lhs_type = TREE_TYPE (lvalue);
     }
   else 
     {
@@ -8529,43 +8825,64 @@ patch_assignment (node, wfl_op1, wfl_op2)
   if (error_found)
     return error_mark_node;
 
-  /* If we built a compound expression as the result of a reference
-     assignment into an array element, return it here. */
-  if (TREE_CODE (node) == COMPOUND_EXPR)
-    return node;
-
-  TREE_OPERAND (node, 0) = lvalue;
-  TREE_OPERAND (node, 1) = new_rhs;
-  TREE_TYPE (node) = lhs_type;
-  return node;
-}
+  /* 10.10: Array Store Exception runtime check */
+  if (!flag_emit_class_files
+      && !flag_emit_xref
+      && lvalue_from_array 
+      && JREFERENCE_TYPE_P (TYPE_ARRAY_ELEMENT (lhs_type))
+      && !CLASS_FINAL (TYPE_NAME (GET_SKIP_TYPE (rhs_type))))
+    {
+      tree check;
+      tree base = lvalue;
 
-/* Optimize static (final) field initialized upon declaration.
-     - If the field is static final and is assigned to a primitive
-       constant type, then set its DECL_INITIAL to the value.
-     - More to come.  */
+      /* We need to retrieve the right argument for _Jv_CheckArrayStore */
+      if (TREE_CODE (lvalue) == COMPOUND_EXPR)
+       base = TREE_OPERAND (lvalue, 0);
+      else
+       {
+         if (flag_bounds_check)
+           base = TREE_OPERAND (TREE_OPERAND (TREE_OPERAND (base, 0), 1), 0);
+         else
+           base = TREE_OPERAND (TREE_OPERAND (base, 0), 0);
+       }
 
-static tree
-patch_initialized_static_field (node)
-     tree node;
-{
-  tree field = TREE_OPERAND (node, 0);
-  tree value = TREE_OPERAND (node, 1);
+      /* Build the invocation of _Jv_CheckArrayStore */
+      check = build (CALL_EXPR, void_type_node,
+                    build_address_of (soft_checkarraystore_node),
+                    tree_cons (NULL_TREE, base,
+                               build_tree_list (NULL_TREE, new_rhs)),
+                    NULL_TREE);
+      TREE_SIDE_EFFECTS (check) = 1;
 
-  if (DECL_INITIAL (field) != NULL_TREE)
-    {
-      tree type = TREE_TYPE (value);
-      if (FIELD_FINAL (field) && TREE_CONSTANT (value)
-         && (JPRIMITIVE_TYPE_P (type)
-             || (flag_emit_class_files
-                 && TREE_CODE (type) == POINTER_TYPE
-                 && TREE_TYPE (type) == string_type_node)))
+      /* We have to decide on an insertion point */
+      if (TREE_CODE (lvalue) == COMPOUND_EXPR)
+       {
+         tree t;
+         if (flag_bounds_check)
+           {
+             t = TREE_OPERAND (TREE_OPERAND (TREE_OPERAND (lvalue, 1), 0), 0);
+             TREE_OPERAND (TREE_OPERAND (TREE_OPERAND (lvalue, 1), 0), 0) =
+               build (COMPOUND_EXPR, void_type_node, t, check);
+           }
+         else
+           TREE_OPERAND (lvalue, 1) = build (COMPOUND_EXPR, lhs_type,
+                                             check, TREE_OPERAND (lvalue, 1));
+       }
+      else 
        {
-         DECL_INITIAL (field) = value;
-         return empty_stmt_node;
+         /* Make sure the bound check will happen before the store check */
+         if (flag_bounds_check)
+           TREE_OPERAND (TREE_OPERAND (lvalue, 0), 0) =
+             build (COMPOUND_EXPR, void_type_node,
+                    TREE_OPERAND (TREE_OPERAND (lvalue, 0), 0), check);
+         else
+           lvalue = build (COMPOUND_EXPR, lhs_type, check, lvalue);
        }
-      DECL_INITIAL (field) = NULL_TREE;
     }
+
+  TREE_OPERAND (node, 0) = lvalue;
+  TREE_OPERAND (node, 1) = new_rhs;
+  TREE_TYPE (node) = lhs_type;
   return node;
 }
 
@@ -8934,7 +9251,7 @@ patch_binop (node, wfl_op1, wfl_op2)
   tree op2 = TREE_OPERAND (node, 1);
   tree op1_type = TREE_TYPE (op1);
   tree op2_type = TREE_TYPE (op2);
-  tree prom_type;
+  tree prom_type = NULL_TREE;
   int code = TREE_CODE (node);
 
   /* If 1, tell the routine that we have to return error_mark_node
@@ -8971,6 +9288,8 @@ patch_binop (node, wfl_op1, wfl_op2)
        {
          tree mod = build_java_binop (TRUNC_MOD_EXPR, prom_type, op1, op2);
          COMPOUND_ASSIGN_P (mod) = COMPOUND_ASSIGN_P (node);
+         TREE_SIDE_EFFECTS (mod)
+           = TREE_SIDE_EFFECTS (op1) | TREE_SIDE_EFFECTS (op2);
          return mod;
        }
       break;
@@ -9057,6 +9376,8 @@ patch_binop (node, wfl_op1, wfl_op2)
          to_return = convert (prom_type, node);
          /* Copy the original value of the COMPOUND_ASSIGN_P flag */
          COMPOUND_ASSIGN_P (to_return) = COMPOUND_ASSIGN_P (node);
+         TREE_SIDE_EFFECTS (to_return)
+           = TREE_SIDE_EFFECTS (op1) | TREE_SIDE_EFFECTS (op2);
          return to_return;
        }
       break;
@@ -9091,6 +9412,7 @@ patch_binop (node, wfl_op1, wfl_op2)
          else if (flag_emit_class_files)
            {
              TREE_OPERAND (node, 1) = op2_type;
+             TREE_SIDE_EFFECTS (node) = TREE_SIDE_EFFECTS (op1);
              return node;
            }
          /* Otherwise we have to invoke instance of to figure it out */
@@ -9104,7 +9426,7 @@ patch_binop (node, wfl_op1, wfl_op2)
                        build_tree_list (NULL_TREE,
                                         build_class_ref (op2_type))),
                       NULL_TREE);
-             TREE_SIDE_EFFECTS (call) = 1;
+             TREE_SIDE_EFFECTS (call) = TREE_SIDE_EFFECTS (op1);
              return call;
            }
        }
@@ -9241,7 +9563,19 @@ patch_binop (node, wfl_op1, wfl_op2)
   TREE_OPERAND (node, 0) = op1;
   TREE_OPERAND (node, 1) = op2;
   TREE_TYPE (node) = prom_type;
-  return fold (node);
+  TREE_SIDE_EFFECTS (node) = TREE_SIDE_EFFECTS (op1) | TREE_SIDE_EFFECTS (op2);
+  
+  if (flag_emit_xref)
+    return node;
+
+  /* fold does not respect side-effect order as required for Java but not C.
+   * Also, it sometimes create SAVE_EXPRs which are bad when emitting
+   * bytecode.
+   */
+  if (flag_emit_class_files ? (TREE_CONSTANT (op1) && TREE_CONSTANT (op2))
+      : ! TREE_SIDE_EFFECTS (node))
+    node = fold (node);
+  return node;
 }
 
 /* Concatenate the STRING_CST CSTE and STRING. When AFTER is a non
@@ -9360,18 +9694,22 @@ build_string_concatenation (op1, op2)
      tree op1, op2;
 {
   tree result;
+  int side_effects = TREE_SIDE_EFFECTS (op1) | TREE_SIDE_EFFECTS (op2);
+
+  if (flag_emit_xref)
+    return build (PLUS_EXPR, string_type_node, op1, op2);
   
   /* Try to do some static optimization */
   if ((result = string_constant_concatenation (op1, op2)))
     return result;
 
-  /* Discard null constants on either sides of the expression */
-  if (TREE_CODE (op1) == STRING_CST && !TREE_STRING_LENGTH (op1))
+  /* Discard empty strings on either side of the expression */
+  if (TREE_CODE (op1) == STRING_CST && TREE_STRING_LENGTH (op1) == 0)
     {
       op1 = op2;
       op2 = NULL_TREE;
     }
-  else if (TREE_CODE (op2) == STRING_CST && !TREE_STRING_LENGTH (op2))
+  else if (TREE_CODE (op2) == STRING_CST && TREE_STRING_LENGTH (op2) == 0)
     op2 = NULL_TREE;
 
   /* If operands are string constant, turn then into object references */
@@ -9412,7 +9750,8 @@ build_string_concatenation (op1, op2)
 
   /* Mark the last node holding a crafted StringBuffer */
   IS_CRAFTED_STRING_BUFFER_P (op1) = 1;
-  
+
+  TREE_SIDE_EFFECTS (op1) = side_effects;
   return op1;
 }
 
@@ -9457,7 +9796,7 @@ patch_string_cst (node)
       location = alloc_name_constant (CONSTANT_String, node);
       node = build_ref_from_constant_pool (location);
     }
-  TREE_TYPE (node) = promote_type (string_type_node);
+  TREE_TYPE (node) = string_ptr_type_node;
   TREE_CONSTANT (node) = 1;
   return node;
 }
@@ -9538,7 +9877,7 @@ patch_unaryop (node, wfl_op)
 {
   tree op = TREE_OPERAND (node, 0);
   tree op_type = TREE_TYPE (op);
-  tree prom_type, value, decl;
+  tree prom_type = NULL_TREE, value, decl;
   int code = TREE_CODE (node);
   int error_found = 0;
 
@@ -9555,10 +9894,14 @@ patch_unaryop (node, wfl_op)
       /* 15.14.2 Prefix Decrement Operator -- */
     case PREDECREMENT_EXPR:
       decl = strip_out_static_field_access_decl (op);
+      /* We really should have a JAVA_ARRAY_EXPR to avoid this */
       if (!JDECL_P (decl) 
-         && !((TREE_CODE (decl) == INDIRECT_REF 
-               || TREE_CODE (decl) == COMPONENT_REF) 
-              && JPRIMITIVE_TYPE_P (TREE_TYPE (decl))))
+         && TREE_CODE (decl) != COMPONENT_REF
+         && !(flag_emit_class_files && TREE_CODE (decl) == ARRAY_REF)
+         && TREE_CODE (decl) != INDIRECT_REF
+         && !(TREE_CODE (decl) == COMPOUND_EXPR
+              && TREE_OPERAND (decl, 1)
+              && (TREE_CODE (TREE_OPERAND (decl, 1)) == INDIRECT_REF)))
        {
          tree lvalue;
          /* Before screaming, check that we're not in fact trying to
@@ -9662,7 +10005,11 @@ patch_unaryop (node, wfl_op)
          error_found = 1;
        }
       else
-       return fold (value);
+       {
+         value = fold (value);
+         TREE_SIDE_EFFECTS (value) = TREE_SIDE_EFFECTS (op);
+         return value;
+       }
       break;
     }
   
@@ -9674,6 +10021,7 @@ patch_unaryop (node, wfl_op)
      CONVERT_EXPR, {POST,PRE}{INCR,DECR}EMENT_EXPR. */
   TREE_OPERAND (node, 0) = fold (op);
   TREE_TYPE (node) = prom_type;
+  TREE_SIDE_EFFECTS (node) = TREE_SIDE_EFFECTS (op);
   return fold (node);
 }
 
@@ -9856,13 +10204,22 @@ patch_array_ref (node)
 
   array_type = TYPE_ARRAY_ELEMENT (array_type);
 
-  if (flag_emit_class_files)
+  if (flag_emit_class_files || flag_emit_xref)
     {
       TREE_OPERAND (node, 0) = array;
       TREE_OPERAND (node, 1) = index;
     }
   else
-    node = build_java_arrayaccess (array, array_type, index);
+    {
+      /* The save_expr is for correct evaluation order.  It would be cleaner
+        to use force_evaluation_order (see comment there), but that is
+        difficult when we also have to deal with bounds checking. */
+      if (TREE_SIDE_EFFECTS (index))
+       array = save_expr (array);
+      node = build_java_arrayaccess (array, array_type, index);
+      if (TREE_SIDE_EFFECTS (index))
+       node = build (COMPOUND_EXPR, array_type, array, node);
+    }
   TREE_TYPE (node) = array_type;
   return node;
 }
@@ -10134,7 +10491,7 @@ static tree
 build_this (location)
      int location;
 {
-  tree node = build_wfl_node (this_identifier_node, input_filename, 0, 0);
+  tree node = build_wfl_node (this_identifier_node);
   TREE_SET_CODE (node, THIS_EXPR);
   EXPR_WFL_LINECOL (node) = location;
   return node;
@@ -10172,6 +10529,10 @@ patch_return (node)
   if (return_exp && (mtype == void_type_node || DECL_CONSTRUCTOR_P (meth)))
     error_found = 1;
 
+  /* It's invalid to use a return statement in a static block */
+  if (IS_CLINIT (current_function_decl))
+    error_found = 1;
+
   /* It's invalid to have a no return value within a function that
      isn't declared with the keyword `void' */
   if (!return_exp && (mtype != void_type_node && !DECL_CONSTRUCTOR_P (meth)))
@@ -10179,7 +10540,11 @@ patch_return (node)
 
   if (error_found)
     {
-      if (!DECL_CONSTRUCTOR_P (meth))
+      if (IS_CLINIT (current_function_decl))
+       parse_error_context (wfl_operator,
+                            "`return' inside static initializer.");
+
+      else if (!DECL_CONSTRUCTOR_P (meth))
        {
          char *t = strdup (lang_printable_name (mtype, 0));
          parse_error_context (wfl_operator, 
@@ -10283,30 +10648,35 @@ patch_if_else_statement (node)
 
 /* Action taken when a lableled statement is parsed. a new
    LABELED_BLOCK_EXPR is created. No statement is attached to the
-   label, yet.  */
+   label, yet.  LABEL can be NULL_TREE for artificially-generated blocks. */
 
 static tree
 build_labeled_block (location, label)
      int location;
      tree label;
 {
-  tree label_name = merge_qualified_name (label_id, label);
+  tree label_name ;
   tree label_decl, node;
-
-  /* Issue an error if we try to reuse a label that was previously
-     declared */
-  if (IDENTIFIER_LOCAL_VALUE (label_name))
+  if (label == NULL_TREE || label == continue_identifier_node)
+    label_name = label;
+  else
     {
-      EXPR_WFL_LINECOL (wfl_operator) = location;
-      parse_error_context (wfl_operator, "Declaration of `%s' shadows "
-                            "a previous label declaration",
-                            IDENTIFIER_POINTER (label));
-      EXPR_WFL_LINECOL (wfl_operator) = 
-        EXPR_WFL_LINECOL (IDENTIFIER_LOCAL_VALUE (label_name));
-      parse_error_context (wfl_operator, "This is the location of the "
-                          "previous declaration of label `%s'",
-                          IDENTIFIER_POINTER (label));
-      java_error_count--;
+      label_name = merge_qualified_name (label_id, label);
+      /* Issue an error if we try to reuse a label that was previously
+        declared */
+      if (IDENTIFIER_LOCAL_VALUE (label_name))
+       {
+         EXPR_WFL_LINECOL (wfl_operator) = location;
+         parse_error_context (wfl_operator, "Declaration of `%s' shadows "
+                              "a previous label declaration",
+                              IDENTIFIER_POINTER (label));
+         EXPR_WFL_LINECOL (wfl_operator) = 
+           EXPR_WFL_LINECOL (IDENTIFIER_LOCAL_VALUE (label_name));
+         parse_error_context (wfl_operator, "This is the location of the "
+                              "previous declaration of label `%s'",
+                              IDENTIFIER_POINTER (label));
+         java_error_count--;
+       }
     }
 
   label_decl = create_label_decl (label_name);
@@ -10316,35 +10686,17 @@ build_labeled_block (location, label)
   return node;
 }
 
-/* Generate a label crafting a unique name for it. This is used to
-   implicitely label loops that aren't the body part of labeled
-   statement.  */
-
-static tree
-generate_labeled_block ()
-{
-  return build_labeled_block (0, generate_name ());
-}
-
 /* A labeled statement LBE is attached a statement.  */
 
 static tree
-complete_labeled_statement (lbe, statement)
+finish_labeled_statement (lbe, statement)
      tree lbe;                 /* Labeled block expr */
      tree statement;
 {
   /* In anyways, tie the loop to its statement */
   LABELED_BLOCK_BODY (lbe) = statement;
-
-  /* Ok, if statement is a for loop, we have to attach the labeled
-     statement to the block the for loop belongs to and return the
-     block instead */
-  if (TREE_CODE (statement) == LOOP_EXPR && IS_FOR_LOOP_P (statement))
-    {
-      java_method_add_stmt (current_function_decl, lbe);
-      return exit_block ();
-    }
-
+  pop_labeled_block ();
+  POP_LABELED_BLOCK ();
   return lbe;
 }
 
@@ -10396,7 +10748,7 @@ build_loop_body (location, condition, reversed)
   condition = build_debugable_stmt (location, condition);
   TREE_SIDE_EFFECTS (condition) = 1;
 
-  body = generate_labeled_block ();
+  body = build_labeled_block (0, continue_identifier_node);
   first = (reversed ? body : condition);
   second = (reversed ? condition : body);
   return 
@@ -10409,7 +10761,7 @@ build_loop_body (location, condition, reversed)
    loop list.  */
 
 static tree
-complete_loop_body (location, condition, body, reversed)
+finish_loop_body (location, condition, body, reversed)
      int location;
      tree condition, body;
      int reversed;
@@ -10431,16 +10783,16 @@ complete_loop_body (location, condition, body, reversed)
   return to_return;
 }
 
-/* Tailored version of complete_loop_body for FOR loops, when FOR
+/* Tailored version of finish_loop_body for FOR loops, when FOR
    loops feature the condition part */
 
 static tree
-complete_for_loop (location, condition, update, body)
+finish_for_loop (location, condition, update, body)
     int location;
     tree condition, update, body;
 {
   /* Put the condition and the loop body in place */
-  tree loop = complete_loop_body (location, condition, body, 0);
+  tree loop = finish_loop_body (location, condition, body, 0);
   /* LOOP is the current loop which has been now popped of the loop
      stack. Install the update block */
   LOOP_EXPR_BODY_UPDATE_BLOCK (LOOP_EXPR_BODY (loop)) = update;
@@ -10448,28 +10800,40 @@ complete_for_loop (location, condition, update, body)
 }
 
 /* If the loop isn't surrounded by a labeled statement, create one and
-   insert LOOP as it's body.  */
+   insert LOOP as its body.  */
 
 static tree
 patch_loop_statement (loop)
      tree loop;
 {
-  tree loop_label, to_return_as_loop;
-
-  if (LOOP_HAS_LABEL_P (loop))
-    {
-      loop_label = ctxp->current_labeled_block;
-      to_return_as_loop = loop;
-    }
-  else
+  tree loop_label;
+  tree block = ctxp->current_labeled_block;
+  TREE_TYPE (loop) = void_type_node;
+  if (block != NULL_TREE)
     {
-      loop_label = generate_labeled_block ();
-      LABELED_BLOCK_BODY (loop_label) = loop;
-      PUSH_LABELED_BLOCK (loop_label);
-      to_return_as_loop = loop_label;
+      tree block_body = LABELED_BLOCK_BODY (block);
+      if (IS_FOR_LOOP_P (loop))
+       {
+         if (TREE_CODE (block_body) == BLOCK)
+           {
+             block_body = BLOCK_EXPR_BODY (block_body);
+             if (block_body == loop
+                 || (TREE_CODE (block_body) == COMPOUND_EXPR
+                     && TREE_OPERAND (block_body, 1) == loop))
+               return loop;
+           }
+       }
+      else
+       {
+         if (block_body == loop)
+           return loop;
+       }
     }
-  TREE_TYPE (to_return_as_loop) = void_type_node;
-  return to_return_as_loop;
+  loop_label = build_labeled_block (0, NULL_TREE);
+  LABELED_BLOCK_BODY (loop_label) = loop;
+  PUSH_LABELED_BLOCK (loop_label);
+  loop = loop_label;
+  return loop;
 }
 
 /* 14.13, 14.14: break and continue Statements */
@@ -10513,98 +10877,63 @@ patch_bc_statement (node)
      tree node;
 {
   tree bc_label = EXIT_BLOCK_LABELED_BLOCK (node), target_stmt;
-  int is_unlabeled = 0;
+  tree labeled_block = ctxp->current_labeled_block;
   EXPR_WFL_LINECOL (wfl_operator) = EXPR_WFL_LINECOL (node);
  
-  /* Not having a target means that the break/continue statement is
-     unlabeled. We try to find a decent label for it */
-  if (!bc_label)
-    {
-      is_unlabeled = 1;
-      /* There should be a loop/switch to branch to */
-      if (ctxp->current_loop)
-       {
-         if (TREE_CODE (ctxp->current_loop) == LOOP_EXPR)
-           {
-             /* At that stage, we're in the loop body, which is
-                encapsulated around a LABELED_BLOCK_EXPR. So searching
-                the current loop label requires us to consider the
-                labeled block before the current one. */
-             if (!LOOP_HAS_LABEL_SKIP_P (ctxp->current_loop))
-               fatal ("unlabeled loop has no installed label -- "
-                      "patch_bc_statement");
-             bc_label = TREE_CHAIN (ctxp->current_labeled_block);
-           }
-         /* For a SWITCH statement, this is the current one */
-         else
-           bc_label = ctxp->current_labeled_block;
-       }
-      /* Not having a loop to break/continue to is an error */
-      else
-       {
-         parse_error_context (wfl_operator, "`%s' must be in loop%s",
-                              (IS_BREAK_STMT_P (node) ? "break" : "continue"),
-                              (IS_BREAK_STMT_P (node) ? " or switch" : ""));
-         return error_mark_node;
-       }
-    }
   /* Having an identifier here means that the target is unknown. */
-  else if (TREE_CODE (bc_label) == IDENTIFIER_NODE)
+  if (bc_label != NULL_TREE && TREE_CODE (bc_label) == IDENTIFIER_NODE)
     {
       parse_error_context (wfl_operator, "No label definition found for `%s'",
                           IDENTIFIER_POINTER (bc_label));
       return error_mark_node;
     }
-
-  /* Find the statement we're targeting. */
-  target_stmt = LABELED_BLOCK_BODY (bc_label);
-
-  /* Target loop is slightly burrowed in the case of a for loop, it
-     appears at the first sight to be a block. */
-  if (TREE_CODE (target_stmt) == BLOCK)
-    {
-      tree sub = BLOCK_SUBBLOCKS (target_stmt);
-      if (sub && TREE_CODE (sub) == COMPOUND_EXPR && TREE_OPERAND (sub, 1)
-         && TREE_CODE (TREE_OPERAND (sub, 1)) == LOOP_EXPR)
-       target_stmt = TREE_OPERAND (sub, 1);
-    }
-
-  /* 14.13 The break Statement */
-  if (IS_BREAK_STMT_P (node))
+  if (! IS_BREAK_STMT_P (node))
     {
-      /* Named break are always fine, as far as they have a target
-         (already verified). Anonymous break need to target
-         while/do/for/switch */
-      if (is_unlabeled &&
-         !(TREE_CODE (target_stmt) == LOOP_EXPR        /* do/while/for */
-           || TREE_CODE (target_stmt) == SWITCH_EXPR)) /* switch */
+      /* It's a continue statement. */
+      for (;; labeled_block = TREE_CHAIN (labeled_block))
        {
-         parse_error_context (wfl_operator, 
-                              "`break' must be in loop or switch");
-         return error_mark_node;
+         if (labeled_block == NULL_TREE)
+           {
+             if (bc_label == NULL_TREE)
+               parse_error_context (wfl_operator,
+                                    "`continue' must be in loop");
+             else
+               parse_error_context 
+                 (wfl_operator, "continue label `%s' does not name a loop",
+                  IDENTIFIER_POINTER (bc_label));
+             return error_mark_node;
+           }
+         if ((DECL_NAME (LABELED_BLOCK_LABEL (labeled_block))
+              == continue_identifier_node)
+             && (bc_label == NULL_TREE
+                 || TREE_CHAIN (labeled_block) == bc_label))
+           {
+             bc_label = labeled_block;
+             break;
+           }
        }
-      /* If previously unlabeled, install the new found label */
-      if (is_unlabeled)
-       EXIT_BLOCK_LABELED_BLOCK (node) = bc_label;
     }
-  /* 14.14 The continue Statement */
-  /* The continue statement must always target a loop, unnamed or not. */
-  else 
+  else if (!bc_label)
     { 
-      if (TREE_CODE (target_stmt) != LOOP_EXPR) /* do/while/for */
+      for (;; labeled_block = TREE_CHAIN (labeled_block))
        {
-         parse_error_context (wfl_operator, "`continue' must be in loop");
-         return error_mark_node;
+         if (labeled_block == NULL_TREE)
+           {
+             parse_error_context (wfl_operator,
+                                    "`break' must be in loop or switch");
+             return error_mark_node;
+           }
+         target_stmt = LABELED_BLOCK_BODY (labeled_block);
+         if (TREE_CODE (target_stmt) == SWITCH_EXPR
+             || TREE_CODE (target_stmt) == LOOP_EXPR)
+           {
+             bc_label = labeled_block;
+             break;
+           }
        }
-      /* Everything looks good. We can fix the `continue' jump to go
-        at the place in the loop were the continue is.  For unlabeled
-        continue, the continuation point is the current labeled
-        block, by construction. */
-      if (is_unlabeled)
-       EXIT_BLOCK_LABELED_BLOCK (node) = 
-         bc_label = ctxp->current_labeled_block;
     }
 
+  EXIT_BLOCK_LABELED_BLOCK (node) = bc_label;
   CAN_COMPLETE_NORMALLY (bc_label) = 1;
 
   /* Our break/continue don't return values. */
@@ -10697,36 +11026,6 @@ patch_switch_statement (node)
 
 /* 14.18 The try statement */
 
-/* Wrap BLOCK around a LABELED_BLOCK, set DECL to the newly generated
-   exit labeld and issue a jump to FINALLY_LABEL:
-     
-   LABELED_BLOCK
-     BLOCK
-       <orignal_statments>
-       DECL = &LABEL_DECL
-       GOTO_EXPR
-         FINALLY_LABEL
-     LABEL_DECL */
-
-static tree
-build_jump_to_finally (block, decl, finally_label, type)
-     tree block, decl, finally_label, type;
-{
-  tree stmt;
-  tree new_block = build (LABELED_BLOCK_EXPR, type,
-                         create_label_decl (generate_name ()), block);
-
-  stmt = build (MODIFY_EXPR, void_type_node, decl,
-               build_address_of (LABELED_BLOCK_LABEL (new_block)));
-  TREE_SIDE_EFFECTS (stmt) = 1;
-  CAN_COMPLETE_NORMALLY (stmt) = 1;
-  add_stmt_to_block (block, type, stmt);
-  stmt = build (GOTO_EXPR, void_type_node, finally_label);
-  TREE_SIDE_EFFECTS (stmt) = 1;
-  add_stmt_to_block (block, type, stmt);
-  return new_block;
-}
-
 static tree
 build_try_statement (location, try_block, catches)
      int location;
@@ -10885,6 +11184,14 @@ patch_synchronized_statement (node, wfl_op1)
       return error_mark_node;
     }
 
+  if (flag_emit_xref)
+    {
+      TREE_OPERAND (node, 0) = expr;
+      TREE_OPERAND (node, 1) = java_complete_tree (block);
+      CAN_COMPLETE_NORMALLY (node) = 1;
+      return 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.
@@ -10958,8 +11265,7 @@ patch_throw_statement (node, wfl_op1)
      throws clause the declaration. */
   SET_WFL_OPERATOR (wfl_operator, node, wfl_op1);
   if (!unchecked_ok)
-    tryblock_throws_ok = 
-      check_thrown_exceptions_do (TREE_TYPE (expr));
+    tryblock_throws_ok = check_thrown_exceptions_do (TREE_TYPE (expr));
   if (!(unchecked_ok || tryblock_throws_ok))
     {
       /* If there is a surrounding try block that has no matching
@@ -10973,11 +11279,22 @@ patch_throw_statement (node, wfl_op1)
                             lang_printable_name (type, 0));
       /* If we have no surrounding try statement and the method doesn't have
         any throws, report it now. FIXME */
+
+      /* We report that the exception can't be throw from a try block
+         in all circumstances but when the `throw' is inside a static
+         block. */
       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, 0));
+       {
+         if (IS_CLINIT (current_function_decl))
+           parse_error_context (wfl_operator, "Checked exception `%s' can't "
+                                "be thrown in initializer",
+                                lang_printable_name (type, 0));
+         else
+           parse_error_context (wfl_operator, "Checked exception `%s' isn't "
+                                "thrown from a `try' block", 
+                                lang_printable_name (type, 0));
+       }
       /* Otherwise, the current method doesn't have the appropriate
          throws declaration */
       else
@@ -10988,13 +11305,12 @@ patch_throw_statement (node, wfl_op1)
       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. */
-  
-  if (! flag_emit_class_files)
+  if (! flag_emit_class_files && ! flag_emit_xref)
     BUILD_THROW (node, expr);
+
+  /* If doing xrefs, keep the location where the `throw' was seen. */
+  if (flag_emit_xref)
+    EXPR_WFL_LINECOL (node) = EXPR_WFL_LINECOL (wfl_op1);
   return node;
 }
 
@@ -11200,7 +11516,7 @@ fold_constant_for_init (node, context)
 
   if (code == INTEGER_CST || code == REAL_CST || code == STRING_CST)
     return node;
-  if (TREE_TYPE (node) != NULL_TREE)
+  if (TREE_TYPE (node) != NULL_TREE && code != VAR_DECL)
     return NULL_TREE;
 
   switch (code)
@@ -11272,7 +11588,7 @@ fold_constant_for_init (node, context)
       val = DECL_INITIAL (node);
       /* Guard against infinite recursion. */
       DECL_INITIAL (node) = NULL_TREE;
-      val = fold_constant_for_init (val, DECL_CONTEXT (node));
+      val = fold_constant_for_init (val, node);
       DECL_INITIAL (node) = val;
       return val;
 
@@ -11288,7 +11604,7 @@ fold_constant_for_init (node, context)
          else if (! QUALIFIED_P (name))
            {
              decl = lookup_field_wrapper (DECL_CONTEXT (context), name);
-             if (! FIELD_STATIC (decl))
+             if (decl == NULL_TREE || ! FIELD_STATIC (decl))
                return NULL_TREE;
              return fold_constant_for_init (decl, decl);
            }