]> gcc.gnu.org Git - gcc.git/blobdiff - gcc/java/parse.y
Daily bump.
[gcc.git] / gcc / java / parse.y
index 1680a688883c134f8110e2307743479ac369351e..75ffbc3cc6170092e0f778abb617b4a8c73d8a50 100644 (file)
@@ -86,8 +86,9 @@ static tree lookup_java_method2 PROTO ((tree, tree, int));
 static tree method_header PROTO ((int, tree, tree, tree));
 static void fix_method_argument_names PROTO ((tree ,tree));
 static tree method_declarator PROTO ((tree, tree));
-static void parse_warning_context VPROTO ((tree cl, char *msg, ...));
-static void issue_warning_error_from_context PROTO ((tree, char *msg, va_list));
+static void parse_warning_context PVPROTO ((tree cl, const char *msg, ...))
+  ATTRIBUTE_PRINTF_2;
+static void issue_warning_error_from_context PROTO ((tree, const char *msg, va_list));
 static tree parse_jdk1_1_error PROTO ((char *));
 static void complete_class_report_errors PROTO ((jdep *));
 static int process_imports PROTO ((void));
@@ -98,7 +99,6 @@ static int check_pkg_class_access PROTO ((tree, tree));
 static tree resolve_package PROTO ((tree, tree *));
 static tree lookup_package_type PROTO ((char *, int));
 static tree resolve_class PROTO ((tree, tree, tree));
-static tree do_resolve_class PROTO ((tree, tree, tree));
 static void declare_local_variables PROTO ((int, tree, tree));
 static void source_start_java_method PROTO ((tree));
 static void source_end_java_method PROTO ((void));
@@ -199,8 +199,8 @@ 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, 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));
 static tree patch_synchronized_statement PROTO ((tree, tree));
 static tree patch_throw_statement PROTO ((tree, tree));
@@ -237,6 +237,8 @@ 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 *));
 
 /* Number of error found so far. */
 int java_error_count; 
@@ -281,6 +283,12 @@ static tree wfl_append = NULL_TREE;
 
 /* The "toString" identifier used for String `+' operator. */
 static tree wfl_to_string = NULL_TREE;
+
+/* The "java.lang" import qualified name.  */
+static tree java_lang_id = NULL_TREE;
+
+/* The "java.lang.Cloneable" qualified name.  */
+static tree java_lang_cloneable = NULL_TREE;
 %}
 
 %union {
@@ -591,10 +599,14 @@ type_import_on_demand_declaration:
        IMPORT_TK name DOT_TK MULT_TK SC_TK
                {
                  tree name = EXPR_WFL_NODE ($2);
-                 tree node = build_tree_list ($2, NULL_TREE);
-                 read_import_dir ($2);
-                 TREE_CHAIN (node) = ctxp->import_demand_list;
-                 ctxp->import_demand_list = node;
+                 /* Don't import java.lang.* twice. */
+                 if (name != java_lang_id)
+                   {
+                     tree node = build_tree_list ($2, NULL_TREE);
+                     read_import_dir ($2);
+                     TREE_CHAIN (node) = ctxp->import_demand_list;
+                     ctxp->import_demand_list = node;
+                   }
                }
 |      IMPORT_TK name DOT_TK error
                {yyerror ("'*' expected"); RECOVER;}
@@ -660,7 +672,10 @@ class_declaration:
 |      CLASS_TK error
                {yyerror ("Missing class name"); RECOVER;}
 |       CLASS_TK identifier error
-               {if (!ctxp->class_err) yyerror ("'{' expected"); DRECOVER(class1);}
+               {
+                 if (!ctxp->class_err) yyerror ("'{' expected"); 
+                 DRECOVER(class1);
+               }
 |       modifiers CLASS_TK identifier error
                {if (!ctxp->class_err) yyerror ("'{' expected"); RECOVER;}
 ;
@@ -723,6 +738,8 @@ class_body_declaration:
 
 class_member_declaration:
        field_declaration
+|      field_declaration SC_TK
+               { $$ = $1; }
 |      method_declaration
 |      class_declaration       /* Added, JDK1.1 inner classes */
                { $$ = parse_jdk1_1_error ("inner classe declaration"); }
@@ -1033,9 +1050,9 @@ interface_declaration:
                  $$ = $6;
                }
 |      INTERFACE_TK identifier error
-               {yyerror ("(here)'{' expected"); RECOVER;}
+               {yyerror ("'{' expected"); RECOVER;}
 |      modifiers INTERFACE_TK identifier error
-               {yyerror ("(there)'{' expected"); RECOVER;}
+               {yyerror ("'{' expected"); RECOVER;}
 ;
 
 extends_interfaces:
@@ -1303,7 +1320,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
@@ -1314,12 +1334,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:
@@ -1441,7 +1461,7 @@ do_statement:
 
 for_statement:
        for_begin SC_TK expression SC_TK for_update CP_TK statement
-               { $$ = complete_for_loop (EXPR_WFL_LINECOL ($3), $3, $5, $7);}
+               { $$ = complete_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);
@@ -1600,11 +1620,14 @@ synchronized:
 
 try_statement:
        TRY_TK block catches
-               { $$ = build_try_statement ($1.location, $2, $3, NULL_TREE); }
+               { $$ = build_try_statement ($1.location, $2, $3); }
 |      TRY_TK block finally
-               { $$ = build_try_statement ($1.location, $2, NULL_TREE, $3); }
+               { $$ = build_try_finally_statement ($1.location, $2, $3); }
 |      TRY_TK block catches finally
-               { $$ = 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);}
 ;
@@ -1653,10 +1676,7 @@ catch_clause_parameter:
 
 finally:
        FINALLY_TK block
-               { 
-                 $$ = build (FINALLY_EXPR, NULL_TREE,
-                             create_label_decl (generate_name ()), $2);
-               }
+               { $$ = $2; }
 |      FINALLY_TK error
                {yyerror ("'{' expected"); RECOVER; }
 ;
@@ -1760,9 +1780,9 @@ array_creation_expression:
 |      NEW_TK class_or_interface_type dim_exprs
                { $$ = build_newarray_node ($2, $3, 0); }
 |      NEW_TK primitive_type dim_exprs dims
-               { $$ = build_newarray_node ($2, $3, ctxp->osb_number); }
+               { $$ = build_newarray_node ($2, $3, CURRENT_OSB (ctxp));}
 |      NEW_TK class_or_interface_type dim_exprs dims
-               { $$ = build_newarray_node ($2, $3, ctxp->osb_number); }
+               { $$ = build_newarray_node ($2, $3, CURRENT_OSB (ctxp));}
         /* Added, JDK1.1 anonymous array. Initial documentation rule
            modified */
 |      NEW_TK class_or_interface_type dims array_initializer
@@ -1800,9 +1820,33 @@ dim_expr:
 
 dims:                          
        OSB_TK CSB_TK
-               { ctxp->osb_number = 1; }
+               { 
+                 int allocate = 0;
+                 /* If not initialized, allocate memory for the osb
+                     numbers stack */
+                 if (!ctxp->osb_limit)
+                   {
+                     allocate = ctxp->osb_limit = 32;
+                     ctxp->osb_depth = -1;
+                   }
+                 /* If capacity overflown, reallocate a bigger chuck */
+                 else if (ctxp->osb_depth+1 == ctxp->osb_limit)
+                   allocate = ctxp->osb_limit << 1;
+                 
+                 if (allocate)
+                   {
+                     allocate *= sizeof (int);
+                     if (ctxp->osb_number)
+                       ctxp->osb_number = (int *)xrealloc (ctxp->osb_number,
+                                                           allocate);
+                     else
+                       ctxp->osb_number = (int *)xmalloc (allocate);
+                   }
+                 ctxp->osb_depth++;
+                 CURRENT_OSB (ctxp) = 1;
+               }
 |      dims OSB_TK CSB_TK
-               { ctxp->osb_number++; }
+               { CURRENT_OSB (ctxp)++; }
 |      dims OSB_TK error
                { yyerror ("']' expected"); RECOVER;}
 ;
@@ -1960,8 +2004,9 @@ cast_expression:          /* Error handling here is potentially weak */
        OP_TK primitive_type dims CP_TK unary_expression
                { 
                  tree type = $2;
-                 while (ctxp->osb_number--)
+                 while (CURRENT_OSB (ctxp)--)
                    type = build_java_array_type (type, -1);
+                 ctxp->osb_depth--;
                  $$ = build_cast ($1.location, type, $5); 
                }
 |      OP_TK primitive_type CP_TK unary_expression
@@ -1971,8 +2016,9 @@ cast_expression:          /* Error handling here is potentially weak */
 |      OP_TK name dims CP_TK unary_expression_not_plus_minus
                { 
                  char *ptr;
-                 while (ctxp->osb_number--)
+                 while (CURRENT_OSB (ctxp)--)
                    obstack_1grow (&temporary_obstack, '[');
+                 ctxp->osb_depth--;
                  obstack_grow0 (&temporary_obstack, 
                                 IDENTIFIER_POINTER (EXPR_WFL_NODE ($2)),
                                 IDENTIFIER_LENGTH (EXPR_WFL_NODE ($2)));
@@ -2414,7 +2460,7 @@ yyerror (msg)
 static void
 issue_warning_error_from_context (cl, msg, ap)
      tree cl;
-     char *msg;
+     const char *msg;
      va_list ap;
 {
   char *saved, *saved_input_filename;
@@ -2442,18 +2488,18 @@ issue_warning_error_from_context (cl, msg, ap)
 /* Issue an error message at a current source line CL */
 
 void
-parse_error_context VPROTO ((tree cl, char *msg, ...))
+parse_error_context VPROTO ((tree cl, const char *msg, ...))
 {
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
   tree cl;
-  char *msg;
+  const char *msg;
 #endif
   va_list ap;
 
   VA_START (ap, msg);
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
   cl = va_arg (ap, tree);
-  msg = va_arg (ap, char *);
+  msg = va_arg (ap, const char *);
 #endif
   issue_warning_error_from_context (cl, msg, ap);
   va_end (ap);
@@ -2462,18 +2508,18 @@ parse_error_context VPROTO ((tree cl, char *msg, ...))
 /* Issue a warning at a current source line CL */
 
 static void
-parse_warning_context VPROTO ((tree cl, char *msg, ...))
+parse_warning_context VPROTO ((tree cl, const char *msg, ...))
 {
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
   tree cl;
-  char *msg;
+  const char *msg;
 #endif
   va_list ap;
 
   VA_START (ap, msg);
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
   cl = va_arg (ap, tree);
-  msg = va_arg (ap, char *);
+  msg = va_arg (ap, const char *);
 #endif
 
   force_error = do_warning = 1;
@@ -2494,25 +2540,30 @@ 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'))
              && EXPR_WFL_LINECOL (node))
            return node;
+         return NULL_TREE;
        }
     }
   return NULL_TREE;
@@ -2640,12 +2691,11 @@ 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 type already is a reference on an array, get the base type */
-      if ((TREE_CODE (type) == POINTER_TYPE) && 
-         TYPE_ARRAY_P (TREE_TYPE (type)))
-       type = TREE_TYPE (type);
+      /* If we have a pointer, use its type */
+      if (TREE_CODE (type) == POINTER_TYPE)
+        type = TREE_TYPE (type);
 
       /* Building the first dimension of a primitive type uses this
          function */
@@ -2890,7 +2940,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;
@@ -2941,17 +2991,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;
@@ -3117,11 +3158,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)
        {
@@ -3130,15 +3166,15 @@ register_fields (flags, type, variable_list)
            {
              /* We include the field and its initialization part into
                 a list used to generate <clinit>. After <clinit> is
-                walked, fields initialization will be processed and
-                fields initialized with know constants will be taken
-                out of <clinit> and have ther DECL_INITIAL set
+                walked, field initializations will be processed and
+                fields initialized with known constants will be taken
+                out of <clinit> and have their DECL_INITIAL set
                 appropriately. */
              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)
-               TREE_STATIC (TREE_OPERAND (TREE_OPERAND (init, 1), 0)) = 1;
+               TREE_STATIC (TREE_OPERAND (init, 1)) = 1;
            }
          /* A non-static field declared with an immediate initialization is
             to be initialized in <init>, if any.  This field is remembered
@@ -3148,7 +3184,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;
        }
     }
@@ -3256,7 +3291,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'", 
@@ -3290,7 +3326,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)))
     {
@@ -3762,16 +3798,14 @@ obtain_incomplete_type (type_name)
     fatal ("invalid type name - obtain_incomplete_type");
 
   for (ptr = ctxp->incomplete_class; ptr; ptr = TREE_CHAIN (ptr))
-    if (TYPE_NAME (TREE_PURPOSE (ptr)) == name)
+    if (TYPE_NAME (ptr) == name)
       break;
 
   if (!ptr)
     {
-      tree core;
       push_obstacks (&permanent_obstack, &permanent_obstack);
-      BUILD_PTR_FROM_NAME (core, name);
-      layout_type (core);
-      ptr = build_tree_list (core, NULL_TREE);
+      BUILD_PTR_FROM_NAME (ptr, name);
+      layout_type (ptr);
       pop_obstacks ();
       TREE_CHAIN (ptr) = ctxp->incomplete_class;
       ctxp->incomplete_class = ptr;
@@ -4033,8 +4067,22 @@ resolve_class (class_type, decl, cl)
 {
   char *name = IDENTIFIER_POINTER (TYPE_NAME (class_type));
   char *base = name;
-  tree resolved_type, resolved_type_decl;
+  tree resolved_type = TREE_TYPE (class_type);
+  tree resolved_type_decl;
   
+  if (resolved_type != NULL_TREE)
+    {
+      tree resolved_type_decl = TYPE_NAME (resolved_type);
+      if (resolved_type_decl == NULL_TREE
+         || TREE_CODE (resolved_type_decl) == IDENTIFIER_NODE)
+       {
+         resolved_type_decl = build_decl (TYPE_DECL,
+                                          TYPE_NAME (class_type),
+                                          resolved_type);
+       }
+      return resolved_type_decl;
+    }
+
   /* 1- Check to see if we have an array. If true, find what we really
      want to resolve  */
   while (name[0] == '[')
@@ -4065,21 +4113,22 @@ resolve_class (class_type, decl, cl)
       /* Figure how those two things are important for error report. FIXME */
       DECL_SOURCE_LINE (resolved_type_decl) = 0;
       DECL_SOURCE_FILE (resolved_type_decl) = input_filename;
+      TYPE_NAME (class_type) = TYPE_NAME (resolved_type);
     }
+  TREE_TYPE (class_type) = resolved_type;
   return resolved_type_decl;
 }
 
 /* Effectively perform the resolution of class CLASS_TYPE. DECL or CL
    are used to report error messages.  */
 
-static tree
+tree
 do_resolve_class (class_type, decl, cl)
      tree class_type;
      tree decl;
      tree cl;
 {
   tree new_class_decl;
-  tree new_name;
   tree original_name = NULL_TREE;
 
   /* Do not try to replace TYPE_NAME (class_type) by a variable, since
@@ -4395,8 +4444,8 @@ check_method_redefinition (class, method)
   tree redef, name;
   tree cl = DECL_NAME (method);
   tree sig = TYPE_ARGUMENT_SIGNATURE (TREE_TYPE (method));
-  /* decl name of artificial <clinit> and $finit$ doesn't need to be fixed and
-     checked */
+  /* decl name of artificial <clinit> and $finit$ doesn't need to be
+     fixed and checked */
 
   /* Reset the method name before running the check. If it returns 1,
      the method doesn't need to be verified with respect to method
@@ -4454,7 +4503,10 @@ java_check_regular_methods (class_decl)
       /* If we previously found something and its name was saved,
          reinstall it now */
       if (found && saved_found_wfl)
-       DECL_NAME (found) = saved_found_wfl;
+       {
+         DECL_NAME (found) = saved_found_wfl;
+         saved_found_wfl = NULL_TREE;
+       }
 
       /* Check for redefinitions */
       if (check_method_redefinition (class, method))
@@ -4486,8 +4538,13 @@ java_check_regular_methods (class_decl)
       found = lookup_argument_method (super_class, DECL_NAME (method), sig);
 
       /* Nothing overrides or it's a private method. */
-      if (!found || (found && METHOD_PRIVATE (found)))
+      if (!found)
        continue;
+      if (METHOD_PRIVATE (found))
+       {
+         found = NULL_TREE;
+         continue;
+       }
 
       /* If found wasn't verified, it's DECL_NAME won't be set properly. 
         We set it temporarily for the sake of the error report. */
@@ -4915,7 +4972,7 @@ read_import_dir (wfl)
   char *package_name = IDENTIFIER_POINTER (package_id);
   int package_length = IDENTIFIER_LENGTH (package_id);
   DIR *dirp = NULL;
-  JCF jcfr, *jcf, *saved_jcf = current_jcf;
+  JCF *saved_jcf = current_jcf;
 
   int found = 0;
   int k;
@@ -4954,15 +5011,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);
                }
            }
@@ -4986,7 +5044,6 @@ read_import_dir (wfl)
          *filename->ptr++ = '/';
          for (;;)
            {
-             int java_or_class = 0;
              int len; 
              char *d_name;
              struct dirent *direntp = readdir (dirp);
@@ -4996,7 +5053,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)
@@ -5157,6 +5214,13 @@ check_pkg_class_access (class_name, cl)
 
   if (!CLASS_PUBLIC (TYPE_NAME (type)))
     {
+      /* Access to a private class within the same package is
+         allowed. */
+      tree l, r;
+      breakdown_qualified (&l, &r, class_name);
+      if (l == ctxp->package)
+       return 0;
+
       parse_error_context 
        (cl, "Can't access %s `%s'. Only public classes and interfaces in "
         "other packages can be accessed",
@@ -5179,7 +5243,7 @@ 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)))
     {
@@ -5386,7 +5450,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;
@@ -5394,7 +5457,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.  */
@@ -5635,7 +5697,7 @@ java_complete_expand_methods ()
        {
          if (flag_emit_class_files)
            write_classfile (current_class);
-         else
+         else if (! flag_syntax_only)
            finish_class (current_class);
        }
     }
@@ -5661,6 +5723,7 @@ java_complete_expand_method (mdecl)
       tree fbody = DECL_FUNCTION_BODY (mdecl);
       tree block_body = BLOCK_EXPR_BODY (fbody);
       expand_start_java_method (mdecl);
+      build_result_decl (mdecl);
 
       current_this 
        = (!METHOD_STATIC (mdecl) ? 
@@ -5683,6 +5746,8 @@ java_complete_expand_method (mdecl)
          && TREE_CODE (TREE_TYPE (TREE_TYPE (mdecl))) != VOID_TYPE)
        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)
@@ -6062,14 +6127,14 @@ resolve_field_access (qual_wfl, field_decl, field_type)
     }
   /* We might have been trying to resolve field.method(). In which
      case, the resolution is over and decl is the answer */
-  else if (DECL_P (decl) && IDENTIFIER_LOCAL_VALUE (DECL_NAME (decl)) == decl)
+  else if (JDECL_P (decl) && IDENTIFIER_LOCAL_VALUE (DECL_NAME (decl)) == decl)
     field_ref = decl;
-  else if (DECL_P (decl))
+  else if (JDECL_P (decl))
     {
       int static_final_found = 0;
       if (!type_found)
        type_found = DECL_CONTEXT (decl);
-      is_static = DECL_P (decl) && FIELD_STATIC (decl);
+      is_static = JDECL_P (decl) && FIELD_STATIC (decl);
       if (FIELD_FINAL (decl) 
          && JPRIMITIVE_TYPE_P (TREE_TYPE (decl))
          && DECL_LANG_SPECIFIC (decl)
@@ -6109,6 +6174,30 @@ resolve_field_access (qual_wfl, field_decl, field_type)
   return field_ref;
 }
 
+/* If NODE is an access to f static field, strip out the class
+   initialization part and return the field decl, otherwise, return
+   NODE. */
+
+static tree
+strip_out_static_field_access_decl (node)
+    tree node;
+{
+  if (TREE_CODE (node) == COMPOUND_EXPR)
+    {
+      tree op1 = TREE_OPERAND (node, 1);
+      if (TREE_CODE (op1) == COMPOUND_EXPR)
+        {
+          tree call = TREE_OPERAND (op1, 0);
+          if (TREE_CODE (call) == CALL_EXPR
+              && TREE_CODE (TREE_OPERAND (call, 0)) == ADDR_EXPR
+              && TREE_OPERAND (TREE_OPERAND (call, 0), 0)
+              == soft_initclass_node)
+            return TREE_OPERAND (op1, 1);
+        }
+    }
+  return node;
+}
+
 /* 6.5.5.2: Qualified Expression Names */
 
 static int
@@ -6134,7 +6223,7 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found)
        case NEW_CLASS_EXPR:
          /* If the access to the function call is a non static field,
             build the code to access it. */
-         if (DECL_P (decl) && !FIELD_STATIC (decl))
+         if (JDECL_P (decl) && !FIELD_STATIC (decl))
            {
              decl = maybe_access_field (decl, *where_found, 
                                         DECL_CONTEXT (decl));
@@ -6168,6 +6257,14 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found)
            }
          continue;
 
+       case NEW_ARRAY_EXPR:
+         *where_found = decl = java_complete_tree (qual_wfl);
+         if (decl == error_mark_node)
+           return 1;
+         *type_found = type = QUAL_DECL_TYPE (decl);
+         CLASS_LOADED_P (type) = 1;
+         continue;
+
        case CONVERT_EXPR:
          *where_found = decl = java_complete_tree (qual_wfl);
          if (decl == error_mark_node)
@@ -6187,7 +6284,7 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found)
        case ARRAY_REF:
          /* If the access to the function call is a non static field,
             build the code to access it. */
-         if (DECL_P (decl) && !FIELD_STATIC (decl))
+         if (JDECL_P (decl) && !FIELD_STATIC (decl))
            {
              decl = maybe_access_field (decl, *where_found, type);
              if (decl == error_mark_node)
@@ -6292,7 +6389,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;
@@ -6348,15 +6445,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
@@ -6381,7 +6481,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))));
@@ -6583,6 +6683,7 @@ patch_method_invocation (patch, primary, where, is_static, ret_decl)
   tree list;
   int is_static_flag = 0;
   int is_super_init = 0;
+  tree this_arg = NULL_TREE;
   
   /* Should be overriden if everything goes well. Otherwise, if
      something fails, it should keep this value. It stop the
@@ -6680,7 +6781,8 @@ patch_method_invocation (patch, primary, where, is_static, ret_decl)
                                       identifier, args);
 
          /* 4- Add the field as an argument */
-         args = tree_cons (NULL_TREE, field, nreverse (args));
+         args = nreverse (args);
+         this_arg = field;
        }
 
       /* IDENTIFIER_WFL will be used to report any problem further */
@@ -6775,8 +6877,8 @@ patch_method_invocation (patch, primary, where, is_static, ret_decl)
         returned by the object allocator. If method is resolved as a
         primary, use the primary otherwise use the current THIS. */
       args = nreverse (args);
-      if (!METHOD_STATIC (list) && TREE_CODE (patch) != NEW_CLASS_EXPR)
-       args = tree_cons (NULL_TREE, primary ? primary : current_this, args);
+      if (TREE_CODE (patch) != NEW_CLASS_EXPR)
+       this_arg = primary ? primary : current_this;
     }
 
   /* Merge point of all resolution schemes. If we have nothing, this
@@ -6801,6 +6903,8 @@ patch_method_invocation (patch, primary, where, is_static, ret_decl)
   check_deprecation (wfl, list);
 
   is_static_flag = METHOD_STATIC (list);
+  if (! METHOD_STATIC (list) && this_arg != NULL_TREE)
+    args = tree_cons (NULL_TREE, this_arg, args);
 
   /* In the context of an explicit constructor invocation, we can't
      invoke any method relying on `this'. Exceptions are: we're
@@ -6996,13 +7100,9 @@ lookup_method_invoke (lc, cl, class, name, arg_list)
   /* Fix the arguments */
   for (node = arg_list; node; node = TREE_CHAIN (node))
     {
-      tree current_arg = TREE_VALUE (node);
-      /* Integer constant 0 passed as itself, not as a type */
-      if (current_arg != integer_zero_node)
-       current_arg = TREE_TYPE (TREE_VALUE (node));
+      tree current_arg = TREE_TYPE (TREE_VALUE (node));
       /* Non primitive type may have to be resolved */
-      if (current_arg != integer_zero_node 
-         && !JPRIMITIVE_TYPE_P (current_arg))
+      if (!JPRIMITIVE_TYPE_P (current_arg))
        resolve_and_layout (current_arg, NULL_TREE);
       /* And promoted */
       if (TREE_CODE (current_arg) == RECORD_TYPE)
@@ -7042,9 +7142,6 @@ lookup_method_invoke (lc, cl, class, name, arg_list)
       candidates = obstack_finish (&temporary_obstack);
     }
   /* Issue the error message */
-  for (node = atl; node; node = TREE_CHAIN (node))
-    if (TREE_VALUE (node) == integer_zero_node)
-      TREE_VALUE (node) = long_type_node;
   method = make_node (FUNCTION_TYPE);
   TYPE_ARG_TYPES (method) = atl;
   signature = build_java_argument_signature (method);
@@ -7209,7 +7306,7 @@ qualify_ambiguous_name (id)
      tree id;
 {
   tree qual, qual_wfl, name, decl, ptr_type, saved_current_class;
-  int again, super_found = 0, this_found = 0;
+  int again, super_found = 0, this_found = 0, new_array_found = 0;
 
   /* We first qualify the first element, then derive qualification of
      others based on the first one. If the first element is qualified
@@ -7237,6 +7334,10 @@ qualify_ambiguous_name (id)
            qual_wfl = QUAL_WFL (qual);
          }
        break;
+      case NEW_ARRAY_EXPR:
+       qual = TREE_CHAIN (qual);
+       new_array_found = again = 1;
+       continue;
       case NEW_CLASS_EXPR:
       case CONVERT_EXPR:
        qual_wfl = TREE_OPERAND (qual_wfl, 0);
@@ -7279,9 +7380,11 @@ qualify_ambiguous_name (id)
        /* Do one more interation to set things up */
        super_found = again = 1;
       }
-    /* Loop one more time if we're dealing with ?: or a string constant */
+    /* Loop one more time if we're dealing with ?: or a string
+       constant, or a convert expression */
     if (TREE_CODE (qual_wfl) == CONDITIONAL_EXPR
-       || TREE_CODE (qual_wfl) == STRING_CST)
+       || TREE_CODE (qual_wfl) == STRING_CST
+       || TREE_CODE (qual_wfl) == CONVERT_EXPR)
       {
        qual = TREE_CHAIN (qual);
        qual_wfl = QUAL_WFL (qual);
@@ -7293,7 +7396,6 @@ qualify_ambiguous_name (id)
      declaration or parameter declaration, then it is an expression
      name. We don't carry this test out if we're in the context of the
      use of SUPER or THIS */
-
   if (!this_found && !super_found && (decl = IDENTIFIER_LOCAL_VALUE (name)))
     {
       RESOLVE_EXPRESSION_NAME_P (qual_wfl) = 1;
@@ -7302,11 +7404,13 @@ qualify_ambiguous_name (id)
 
   /* If within the class/interface NAME was found to be used there
      exists a (possibly inherited) field named NAME, then this is an
-     expression name. */
-  else if ((decl = lookup_field_wrapper (ptr_type, name)))
+     expression name. If we saw a NEW_ARRAY_EXPR before and want to
+     address length, it is OK. */
+  else if ((decl = lookup_field_wrapper (ptr_type, name))
+          || (new_array_found && name == length_identifier_node))
     {
       RESOLVE_EXPRESSION_NAME_P (qual_wfl) = 1;
-      QUAL_RESOLUTION (qual) = decl;
+      QUAL_RESOLUTION (qual) = (new_array_found ? NULL_TREE : decl);
     }
 
   /* We reclassify NAME as a type name if:
@@ -7408,6 +7512,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) = build1 (SAVE_EXPR, TREE_TYPE (op0), 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. */
@@ -7439,7 +7559,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;
@@ -7470,7 +7589,8 @@ 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);
@@ -7490,8 +7610,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;
@@ -7524,16 +7643,27 @@ java_complete_lhs (node)
     case TRY_EXPR:
       return patch_try_statement (node);
 
+    case TRY_FINALLY_EXPR:
+      COMPLETE_CHECK_OP_0 (node);
+      COMPLETE_CHECK_OP_1 (node);
+      CAN_COMPLETE_NORMALLY (node)
+       = (CAN_COMPLETE_NORMALLY (TREE_OPERAND (node, 0))
+          && CAN_COMPLETE_NORMALLY (TREE_OPERAND (node, 1)));
+      TREE_TYPE (node) = TREE_TYPE (TREE_OPERAND (node, 0));
+      return 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;
 
@@ -7672,18 +7802,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
-         && TREE_OPERAND (node, 1) != empty_stmt_node)
+      if (wfl_op2 == empty_stmt_node)
+       CAN_COMPLETE_NORMALLY (node) = CAN_COMPLETE_NORMALLY (nn);
+      else
        {
-         SET_WFL_OPERATOR (wfl_operator, node, wfl_op2);
-         parse_error_context (wfl_operator, "Unreachable statement");
+         if (! CAN_COMPLETE_NORMALLY (nn) && TREE_CODE (nn) != ERROR_MARK)
+           {
+             /* 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:
@@ -7695,6 +7837,8 @@ java_complete_lhs (node)
          || TREE_CODE (EXPR_WFL_NODE (node)) == IDENTIFIER_NODE)
        {
          node = resolve_expression_name (node, NULL);
+         if (node == error_mark_node)
+           return node;
          CAN_COMPLETE_NORMALLY (node) = 1;
        }
       else
@@ -7705,9 +7849,9 @@ 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 == error_mark_node)
            {
              /* Its important for the evaluation of assignment that
                 this mark on the TREE_TYPE is propagated. */
@@ -7769,7 +7913,7 @@ 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:
@@ -7782,43 +7926,33 @@ java_complete_lhs (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));
+
+         /* 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 = 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 (DECL_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
@@ -7867,18 +8001,24 @@ 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);
@@ -8254,7 +8394,7 @@ static int
 check_final_assignment (lvalue, wfl)
      tree lvalue, wfl;
 {
-  if (DECL_P (lvalue) && FIELD_FINAL (lvalue) &&
+  if (JDECL_P (lvalue) && FIELD_FINAL (lvalue) &&
       DECL_NAME (current_function_decl) != clinit_identifier_node)
     {
       parse_error_context 
@@ -8311,9 +8451,8 @@ patch_assignment (node, wfl_op1, wfl_op2)
   EXPR_WFL_LINECOL (wfl_operator) = EXPR_WFL_LINECOL (node);
 
   /* Lhs can be a named variable */
-  if (DECL_P (lvalue))
+  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 +
@@ -8528,24 +8667,17 @@ static int
 valid_builtin_assignconv_identity_widening_p (lhs_type, rhs_type)
      tree lhs_type, rhs_type;
 {
-  int all_primitive;
-
+  /* 5.1.1: This is the identity conversion part. */
   if (lhs_type == rhs_type)
     return 1;
 
-  /* Sometimes, instead of passing a type, we pass integer_zero_node
-     so we know that an integral type can accomodate it */
-  if (JINTEGRAL_TYPE_P (lhs_type) && (rhs_type == integer_zero_node))
-    return 1;
-
-  all_primitive = 
-    JPRIMITIVE_TYPE_P (lhs_type) && JPRIMITIVE_TYPE_P (rhs_type);
-
-  if (!all_primitive)
+  /* Reject non primitive types */
+  if (!JPRIMITIVE_TYPE_P (lhs_type) || !JPRIMITIVE_TYPE_P (rhs_type))
     return 0;
 
-  /* byte, even if it's smaller than a char can't be converted into a
-     char. Short can't too, but the < test below takes care of that */
+  /* 5.1.2: widening primitive conversion. byte, even if it's smaller
+     than a char can't be converted into a char. Short can't too, but
+     the < test below takes care of that */
   if (lhs_type == char_type_node && rhs_type == byte_type_node)
     return 0;
 
@@ -8559,13 +8691,13 @@ valid_builtin_assignconv_identity_widening_p (lhs_type, rhs_type)
          || rhs_type == promoted_boolean_type_node))
     return 1;
 
-  if (JINTEGRAL_TYPE_P (rhs_type)
-      && ((TYPE_PRECISION (rhs_type) < TYPE_PRECISION (lhs_type))
-         || (JFLOAT_TYPE_P (lhs_type) &&
-             TYPE_PRECISION (rhs_type) == TYPE_PRECISION (lhs_type))))
-    return 1;
-  else if (JFLOAT_TYPE_P (rhs_type)
-          && (TYPE_PRECISION (rhs_type) < TYPE_PRECISION (lhs_type)))
+  /* From here, an integral is widened if its precision is smaller
+     than the precision of the LHS or if the LHS is a floating point
+     type, or the RHS is a float and the RHS a double. */
+  if ((JINTEGRAL_TYPE_P (rhs_type) && JINTEGRAL_TYPE_P (lhs_type) 
+       && (TYPE_PRECISION (rhs_type) < TYPE_PRECISION (lhs_type)))
+      || (JINTEGRAL_TYPE_P (rhs_type) && JFLOAT_TYPE_P (lhs_type))
+      || (rhs_type == float_type_node && lhs_type == double_type_node))
     return 1;
 
   return 0;
@@ -8583,6 +8715,9 @@ valid_ref_assignconv_cast_p (source, dest, cast)
      tree dest;
      int cast;
 {
+  /* SOURCE or DEST might be null if not from a declared entity. */
+  if (!source || !dest)
+    return 0;
   if (JNULLP_TYPE_P (source))
     return 1;
   if (TREE_CODE (source) == POINTER_TYPE)
@@ -8660,8 +8795,10 @@ valid_ref_assignconv_cast_p (source, dest, cast)
     {
       if (TYPE_CLASS_P (dest))
        return dest == object_type_node;
+      /* Can't cast an array to an interface unless the interface is
+        java.lang.Cloneable */
       if (TYPE_INTERFACE_P (dest))
-       return 0;               /* Install test on Clonable. FIXME */
+       return (DECL_NAME (TYPE_NAME (dest)) == java_lang_cloneable ? 1 : 0);
       else                     /* Arrays */
        {
          tree source_element_type = TYPE_ARRAY_ELEMENT (source);
@@ -8714,16 +8851,17 @@ do_unary_numeric_promotion (arg)
   return arg;
 }
 
+/* Return a non zero value if SOURCE can be converted into DEST using
+   the method invocation conversion rule (5.3).  */
 static int
 valid_method_invocation_conversion_p (dest, source)
      tree dest, source;
 {
-  return (((JPRIMITIVE_TYPE_P (source) || (source == integer_zero_node))
-           && JPRIMITIVE_TYPE_P (dest)
-           && valid_builtin_assignconv_identity_widening_p (dest, source))
-          || ((JREFERENCE_TYPE_P (source) || JNULLP_TYPE_P (source))
-              && (JREFERENCE_TYPE_P (dest) || JNULLP_TYPE_P (dest))
-              && valid_ref_assignconv_cast_p (source, dest, 0)));
+  return ((JPRIMITIVE_TYPE_P (source) && JPRIMITIVE_TYPE_P (dest)
+          && valid_builtin_assignconv_identity_widening_p (dest, source))
+         || ((JREFERENCE_TYPE_P (source) || JNULLP_TYPE_P (source))
+             && (JREFERENCE_TYPE_P (dest) || JNULLP_TYPE_P (dest))
+             && valid_ref_assignconv_cast_p (source, dest, 0)));
 }
 
 /* Build an incomplete binop expression. */
@@ -8841,10 +8979,18 @@ patch_binop (node, wfl_op1, wfl_op2)
       /* Change the division operator if necessary */
       if (code == RDIV_EXPR && TREE_CODE (prom_type) == INTEGER_TYPE)
        TREE_SET_CODE (node, TRUNC_DIV_EXPR);
-      /* This one is more complicated. FLOATs are processed by a function
-        call to soft_fmod. */
+
+      /* This one is more complicated. FLOATs are processed by a
+        function call to soft_fmod. Duplicate the value of the
+        COMPOUND_ASSIGN_P flag. */
       if (code == TRUNC_MOD_EXPR)
-       return build_java_binop (TRUNC_MOD_EXPR, prom_type, op1, 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;
 
     /* 15.17 Additive Operators */
@@ -8919,8 +9065,19 @@ patch_binop (node, wfl_op1, wfl_op2)
       /* The >>> operator is a >> operating on unsigned quantities */
       if (code == URSHIFT_EXPR && ! flag_emit_class_files)
        {
-         op1 = convert (unsigned_type (prom_type), op1);
+         tree to_return;
+          tree utype = unsigned_type (prom_type);
+          op1 = convert (utype, op1);
          TREE_SET_CODE (node, RSHIFT_EXPR);
+          TREE_OPERAND (node, 0) = op1;
+          TREE_OPERAND (node, 1) = op2;
+          TREE_TYPE (node) = utype;
+         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;
 
@@ -8954,6 +9111,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 */
@@ -8967,7 +9125,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;
            }
        }
@@ -9104,6 +9262,8 @@ patch_binop (node, wfl_op1, wfl_op2)
   TREE_OPERAND (node, 0) = op1;
   TREE_OPERAND (node, 1) = op2;
   TREE_TYPE (node) = prom_type;
+  TREE_SIDE_EFFECTS (node) = TREE_SIDE_EFFECTS (op1) | TREE_SIDE_EFFECTS (op2);
+  
   return fold (node);
 }
 
@@ -9223,25 +9383,40 @@ build_string_concatenation (op1, op2)
      tree op1, op2;
 {
   tree result;
+  int side_effects = TREE_SIDE_EFFECTS (op1) | TREE_SIDE_EFFECTS (op2);
+
   
   /* Try to do some static optimization */
   if ((result = string_constant_concatenation (op1, op2)))
     return result;
 
-  /* If operands are string constant, turn then into object references */
+  /* 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) == 0)
+    op2 = NULL_TREE;
 
+  /* If operands are string constant, turn then into object references */
   if (TREE_CODE (op1) == STRING_CST)
     op1 = patch_string_cst (op1);
-  if (TREE_CODE (op2) == STRING_CST)
+  if (op2 && TREE_CODE (op2) == STRING_CST)
     op2 = patch_string_cst (op2);
 
+  /* If either one of the constant is null and the other non null
+     operand is a String object, return it. */
+  if (JSTRING_TYPE_P (TREE_TYPE (op1)) && !op2)
+    return op1;
+
   /* If OP1 isn't already a StringBuffer, create and
      initialize a new one */
   if (!IS_CRAFTED_STRING_BUFFER_P (op1))
     {
       /* Two solutions here: 
         1) OP1 is a string reference, we call new StringBuffer(OP1)
-        2) Op2 is something else, we call new StringBuffer().append(OP1). */
+        2) OP1 is something else, we call new StringBuffer().append(OP1). */
       if (JSTRING_TYPE_P (TREE_TYPE (op1)))
        op1 = BUILD_STRING_BUFFER (op1);
       else
@@ -9251,13 +9426,19 @@ build_string_concatenation (op1, op2)
        }
     }
 
-  /* No longer the last node holding a crafted StringBuffer */
-  IS_CRAFTED_STRING_BUFFER_P (op1) = 0;
-  /* Create a node for `{new...,xxx}.append (op2)' */
-  op1 = make_qualified_primary (op1, BUILD_APPEND (op2), 0);
+  if (op2)
+    {
+      /* OP1 is no longer the last node holding a crafted StringBuffer */
+      IS_CRAFTED_STRING_BUFFER_P (op1) = 0;
+      /* Create a node for `{new...,xxx}.append (op2)' */
+      if (op2)
+       op1 = make_qualified_primary (op1, BUILD_APPEND (op2), 0);
+    }
+
   /* Mark the last node holding a crafted StringBuffer */
   IS_CRAFTED_STRING_BUFFER_P (op1) = 1;
-  
+
+  TREE_SIDE_EFFECTS (op1) = side_effects;
   return op1;
 }
 
@@ -9383,7 +9564,7 @@ patch_unaryop (node, wfl_op)
 {
   tree op = TREE_OPERAND (node, 0);
   tree op_type = TREE_TYPE (op);
-  tree prom_type, value;
+  tree prom_type, value, decl;
   int code = TREE_CODE (node);
   int error_found = 0;
 
@@ -9399,9 +9580,11 @@ patch_unaryop (node, wfl_op)
     case PREINCREMENT_EXPR:
       /* 15.14.2 Prefix Decrement Operator -- */
     case PREDECREMENT_EXPR:
-      if (!DECL_P (op) && !((TREE_CODE (op) == INDIRECT_REF 
-                            || TREE_CODE (op) == COMPONENT_REF) 
-                           && JPRIMITIVE_TYPE_P (TREE_TYPE (op))))
+      decl = strip_out_static_field_access_decl (op);
+      if (!JDECL_P (decl) 
+         && !((TREE_CODE (decl) == INDIRECT_REF 
+               || TREE_CODE (decl) == COMPONENT_REF) 
+              && JPRIMITIVE_TYPE_P (TREE_TYPE (decl))))
        {
          tree lvalue;
          /* Before screaming, check that we're not in fact trying to
@@ -9505,7 +9688,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;
     }
   
@@ -9517,6 +9704,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);
 }
 
@@ -9571,12 +9759,21 @@ patch_cast (node, wfl_operator)
       if (cast_type == op_type)
        return node;
 
+      /* float and double type are converted to the original type main
+        variant and then to the target type. */
+      if (JFLOAT_TYPE_P (op_type) && TREE_CODE (cast_type) == CHAR_TYPE)
+       op = convert (integer_type_node, op);
+
       /* Try widening/narowwing convertion. Potentially, things need
         to be worked out in gcc so we implement the extreme cases
         correctly. fold_convert() needs to be fixed. */
       return convert (cast_type, op);
     }
 
+  /* It's also valid to cast a boolean into a boolean */
+  if (op_type == boolean_type_node && cast_type == boolean_type_node)
+    return node;
+
   /* null can be casted to references */
   if (op == null_pointer_node && JREFERENCE_TYPE_P (cast_type))
     return build_null_of_type (cast_type);
@@ -9584,7 +9781,7 @@ patch_cast (node, wfl_operator)
   /* The remaining legal casts involve conversion between reference
      types. Check for their compile time correctness. */
   if (JREFERENCE_TYPE_P (op_type) && JREFERENCE_TYPE_P (cast_type) 
-      && valid_ref_assignconv_cast_p (cast_type, op_type, 1))
+      && valid_ref_assignconv_cast_p (op_type, cast_type, 1))
     {
       TREE_TYPE (node) = promote_type (cast_type);
       /* Now, the case can be determined correct at compile time if
@@ -9696,7 +9893,16 @@ patch_array_ref (node)
       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;
 }
@@ -9840,7 +10046,7 @@ build_new_array_init (location, values)
 {
   tree constructor = build (CONSTRUCTOR, NULL_TREE, NULL_TREE, values);
   tree to_return = build1 (NEW_ARRAY_INIT, NULL_TREE, constructor);
-  EXPR_WFL_LINECOL (to_return) = EXPR_WFL_LINECOL (constructor) = location;
+  EXPR_WFL_LINECOL (to_return) = location;
   return to_return;
 }
 
@@ -9877,7 +10083,10 @@ patch_new_array_init (type, node)
       if (elt == NULL_TREE || TREE_CODE (elt) != NEW_ARRAY_INIT)
        {
          error_seen |= array_constructor_check_entry (element_type, current);
-         if (! TREE_CONSTANT (TREE_VALUE (current)))
+         elt = TREE_VALUE (current);
+         /* When compiling to native code, STRING_CST is converted to
+            INDIRECT_REF, but still with a TREE_CONSTANT flag. */
+         if (! TREE_CONSTANT (elt) || TREE_CODE (elt) == INDIRECT_REF)
            all_constant = 0;
        }
       else
@@ -10199,7 +10408,7 @@ build_new_loop (loop_body)
        COMPOUND_EXPR           (loop main body)
          EXIT_EXPR             (this order is for while/for loops.
          LABELED_BLOCK_EXPR      the order is reversed for do loops)
-           LABEL_DECL           (continue occurding here branche at the 
+           LABEL_DECL           (a continue occuring here branches at the 
            BODY                         end of this labeled block)
        INCREMENT               (if any)
 
@@ -10390,6 +10599,16 @@ patch_bc_statement (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))
     {
@@ -10398,7 +10617,7 @@ patch_bc_statement (node)
          while/do/for/switch */
       if (is_unlabeled &&
          !(TREE_CODE (target_stmt) == LOOP_EXPR        /* do/while/for */
-           || TREE_CODE (target_stmt) == SWITCH_EXPR)) /* switch FIXME */
+           || TREE_CODE (target_stmt) == SWITCH_EXPR)) /* switch */
        {
          parse_error_context (wfl_operator, 
                               "`break' must be in loop or switch");
@@ -10409,18 +10628,21 @@ patch_bc_statement (node)
        EXIT_BLOCK_LABELED_BLOCK (node) = bc_label;
     }
   /* 14.14 The continue Statement */
-  /* The continue statement must always target a loop */
+  /* The continue statement must always target a loop, unnamed or not. */
   else 
-    {
+    { 
       if (TREE_CODE (target_stmt) != LOOP_EXPR) /* do/while/for */
        {
          parse_error_context (wfl_operator, "`continue' must be in loop");
          return error_mark_node;
        }
       /* Everything looks good. We can fix the `continue' jump to go
-         at the place in the loop were the continue is. The continue
-        is the current labeled block, by construction. */
-      EXIT_BLOCK_LABELED_BLOCK (node) = bc_label = ctxp->current_labeled_block;
+        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;
     }
 
   CAN_COMPLETE_NORMALLY (bc_label) = 1;
@@ -10515,123 +10737,24 @@ 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;
+build_try_statement (location, try_block, catches)
+     int location;
+     tree try_block, catches;
 {
-  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;
+  tree node = build (TRY_EXPR, NULL_TREE, try_block, catches);
+  EXPR_WFL_LINECOL (node) = location;
+  return node;
 }
 
 static tree
-build_try_statement (location, try_block, catches, finally)
+build_try_finally_statement (location, try_block, finally)
      int location;
-     tree try_block, catches, finally;
-{
-  tree node, rff;
-
-  if (finally && ! flag_emit_class_files)
-    {
-      /* This block defines a scope for the entire try[-catch]-finally
-        sequence. It hold a local variable used to return from the
-        finally using a computed goto. We call it
-        return_from_finally (RFF). */
-      rff = build_decl (VAR_DECL, generate_name (), return_address_type_node);
-
-      /* Modification of the try block. */
-      try_block = build_jump_to_finally (try_block, rff, 
-                                        FINALLY_EXPR_LABEL (finally), 
-                                        NULL_TREE);
-
-      /* To the finally block: add the computed goto */
-      add_stmt_to_block (FINALLY_EXPR_BLOCK (finally), NULL_TREE,
-                        build (GOTO_EXPR, void_type_node, rff));
-
-      /* Modification of each catch blocks, if any */
-      if (catches)
-       {
-         tree catch, catch_decl, catch_block, stmt;
-
-         for (catch = catches; catch; catch = TREE_CHAIN (catch))
-           TREE_OPERAND (catch, 0) = 
-             build_jump_to_finally (TREE_OPERAND (catch, 0), rff,
-                                    FINALLY_EXPR_LABEL (finally),
-                                    NULL_TREE);
-
-         /* Plus, at the end of the list, we add the catch clause that
-            will catch an uncaught exception, call finally and rethrow it:
-              BLOCK
-                void *exception_parameter; (catch_decl)
-                LABELED_BLOCK
-                  BLOCK
-                    exception_parameter = _Jv_exception_info ();
-                    RFF = &LABEL_DECL;
-                    goto finally;
-                LABEL_DECL;
-                CALL_EXPR
-                  Jv_ReThrow
-                  exception_parameter */
-         catch_decl = build_decl (VAR_DECL, generate_name (), ptr_type_node);
-         BUILD_ASSIGN_EXCEPTION_INFO (stmt, catch_decl);
-         catch_block = build_expr_block (stmt, NULL_TREE);
-         catch_block = build_jump_to_finally (catch_block, rff, 
-                                              FINALLY_EXPR_LABEL (finally), 
-                                              void_type_node);
-         BUILD_THROW (stmt, catch_decl);
-         catch_block = build_expr_block (catch_block, catch_decl);
-         add_stmt_to_block (catch_block, void_type_node, stmt);
-
-         /* Link the new handler to the existing list as the first
-            entry. It will be the last one to be generated. */
-         catch = build1 (CATCH_EXPR, void_type_node, catch_block);
-         TREE_CHAIN (catch) = catches;
-         catches = catch;
-       }
-    }
-
-  node = build (TRY_EXPR, NULL_TREE, try_block, catches, finally);
-  EXPR_WFL_LINECOL (node) = location;
-  
-  /* If we have a finally, surround this whole thing by a block where
-     the RFF local variable is defined. */
-
-  return (finally && ! flag_emit_class_files ? build_expr_block (node, rff)
-         : node);
-}
-
-/* Get the catch clause block from an element of the catch clause
-   list. If depends on whether a finally clause exists or node (in
-   which case the original catch clause was surrounded by a
-   LABELED_BLOCK_EXPR. */
-
-tree
-java_get_catch_block (node, finally_present_p)
-     tree node;
-     int finally_present_p;
+     tree try_block, finally;
 {
-  return (CATCH_EXPR_GET_EXPR (TREE_OPERAND (node, 0), finally_present_p));
+  tree node = build (TRY_FINALLY_EXPR, NULL_TREE, try_block, finally);
+  EXPR_WFL_LINECOL (node) = location;
+  return node;
 }
 
 static tree
@@ -10642,8 +10765,6 @@ patch_try_statement (node)
   tree try = TREE_OPERAND (node, 0);
   /* Exception handlers are considered in left to right order */
   tree catch = nreverse (TREE_OPERAND (node, 1));
-  tree finally = TREE_OPERAND (node, 2);
-  int finally_p = (finally ? 1 : 0);
   tree current, caught_type_list = NULL_TREE;
 
   /* Check catch clauses, if any. Every time we find an error, we try
@@ -10656,29 +10777,14 @@ patch_try_statement (node)
       tree sub_current, catch_block, catch_clause;
       int unreachable;
 
-      /* Always detect the last catch clause if a finally is
-         present. This is the catch-all handler and it just needs to
-         be walked. */
-      if (!TREE_CHAIN (current) && finally)
-       {
-         TREE_OPERAND (current, 0) = 
-           java_complete_tree (TREE_OPERAND (current, 0));
-         continue;
-       }
-
       /* At this point, the structure of the catch clause is
-         LABELED_BLOCK_EXPR    (if we have a finally)
           CATCH_EXPR           (catch node)
             BLOCK              (with the decl of the parameter)
                COMPOUND_EXPR
                  MODIFY_EXPR   (assignment of the catch parameter)
                 BLOCK          (catch clause block)
-           LABEL_DECL          (where to return after finally (if any))
-
-        Since the structure of the catch clause depends on the
-        presence of a finally, we use a function call to get to the
-        cath clause */
-      catch_clause = java_get_catch_block (current, finally_p);
+       */
+      catch_clause = TREE_OPERAND (current, 0);
       carg_decl = BLOCK_EXPR_DECLS (catch_clause);
       carg_type = TREE_TYPE (TREE_TYPE (carg_decl));
 
@@ -10712,7 +10818,7 @@ patch_try_statement (node)
           sub_current != current; sub_current = TREE_CHAIN (sub_current))
        {
          tree sub_catch_clause, decl;
-         sub_catch_clause = java_get_catch_block (sub_current, finally_p);
+         sub_catch_clause = TREE_OPERAND (sub_current, 0);
          decl = BLOCK_EXPR_DECLS (sub_catch_clause);
 
          if (inherits_from_p (carg_type, TREE_TYPE (TREE_TYPE (decl))))
@@ -10752,24 +10858,12 @@ patch_try_statement (node)
     CAN_COMPLETE_NORMALLY (node) = 1;
   POP_EXCEPTIONS ();
 
-  /* Process finally */
-  if (finally)
-    {
-      current = java_complete_tree (FINALLY_EXPR_BLOCK (finally));
-      FINALLY_EXPR_BLOCK (finally) = current;
-      if (current == error_mark_node)
-       error_found = 1;
-      if (! CAN_COMPLETE_NORMALLY (current))
-       CAN_COMPLETE_NORMALLY (node) = 0;
-    }
-
   /* Verification ends here */
   if (error_found) 
     return error_mark_node;
 
   TREE_OPERAND (node, 0) = try;
   TREE_OPERAND (node, 1) = catch;
-  TREE_OPERAND (node, 2) = finally;
   TREE_TYPE (node) = void_type_node;
   return node;
 }
@@ -10783,7 +10877,7 @@ patch_synchronized_statement (node, wfl_op1)
   tree expr = java_complete_tree (TREE_OPERAND (node, 0));
   tree block = TREE_OPERAND (node, 1);
 
-  tree enter, exit, finally, expr_decl;
+  tree enter, exit, expr_decl, assignment;
 
   if (expr == error_mark_node)
     {
@@ -10823,13 +10917,13 @@ patch_synchronized_statement (node, wfl_op1)
   BUILD_MONITOR_EXIT (exit, expr_decl);
   CAN_COMPLETE_NORMALLY (enter) = 1;
   CAN_COMPLETE_NORMALLY (exit) = 1;
+  assignment = build (MODIFY_EXPR, NULL_TREE, expr_decl, expr);
+  TREE_SIDE_EFFECTS (assignment) = 1;
   node = build1 (CLEANUP_POINT_EXPR, NULL_TREE,
                 build (COMPOUND_EXPR, NULL_TREE,
                        build (WITH_CLEANUP_EXPR, NULL_TREE,
                               build (COMPOUND_EXPR, NULL_TREE,
-                                     build (MODIFY_EXPR, NULL_TREE,
-                                            expr_decl, expr),
-                                     enter),
+                                     assignment, enter),
                               NULL_TREE, exit),
                        block));
   node = build_expr_block (node, expr_decl);
This page took 0.089903 seconds and 5 git commands to generate.