OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / gcc / java / parse.y
index 782a653..2ea7af0 100644 (file)
@@ -238,6 +238,7 @@ static const char *get_printable_method_name PARAMS ((tree));
 static tree patch_conditional_expr PARAMS ((tree, tree, tree));
 static tree generate_finit PARAMS ((tree));
 static void add_instance_initializer PARAMS ((tree));
+static tree build_instance_initializer PARAMS ((tree));
 static void fix_constructors PARAMS ((tree));
 static tree build_alias_initializer_parameter_list PARAMS ((int, tree,
                                                            tree, int *));
@@ -329,6 +330,7 @@ static tree build_dot_class_method PARAMS ((tree));
 static tree build_dot_class_method_invocation PARAMS ((tree));
 static void create_new_parser_context PARAMS ((int));
 static void mark_parser_ctxt PARAMS ((void *));
+static tree maybe_build_class_init_for_field PARAMS ((tree, tree));
 
 /* Number of error found so far. */
 int java_error_count; 
@@ -664,7 +666,6 @@ array_type:
                { 
                  int osb = pop_current_osb (ctxp);
                  tree t = build_java_array_type (($1), -1);
-                 CLASS_LOADED_P (t) = 1;
                  while (--osb)
                    t = build_unresolved_array_type (t);
                  $$ = t;
@@ -1885,9 +1886,9 @@ catch_clause_parameter:
                     declared initialized by the appropriate function
                     call */
                  tree ccpb = enter_block ();
-                 tree init = build_assignment (ASSIGN_TK, $2.location, 
-                                               TREE_PURPOSE ($3), 
-                                               soft_exceptioninfo_call_node);
+                 tree init = build_assignment
+                   (ASSIGN_TK, $2.location, TREE_PURPOSE ($3), 
+                    build (JAVA_EXC_OBJ_EXPR, ptr_type_node));
                  declare_local_variables (0, TREE_VALUE ($3),
                                           build_tree_list (TREE_PURPOSE ($3),
                                                            init));
@@ -1953,9 +1954,12 @@ type_literals:
 |      array_type DOT_TK CLASS_TK
                { $$ = build_incomplete_class_ref ($2.location, $1); }
 |      primitive_type DOT_TK CLASS_TK
-               { $$ = build_class_ref ($1); }
+                { $$ = build_incomplete_class_ref ($2.location, $1); }
 |      VOID_TK DOT_TK CLASS_TK
-               { $$ = build_class_ref (void_type_node); }
+                { 
+                   $$ = build_incomplete_class_ref ($2.location,
+                                                   void_type_node);
+                }
 ;
 
 class_instance_creation_expression:
@@ -2670,12 +2674,12 @@ java_pop_parser_context (generate)
   /* Set the single import class file flag to 0 for the current list
      of imported things */
   for (current = ctxp->import_list; current; current = TREE_CHAIN (current))
-    IS_A_SINGLE_IMPORT_CLASSFILE_NAME_P (TREE_PURPOSE (current)) = 0;
+    IS_A_SINGLE_IMPORT_CLASSFILE_NAME_P (TREE_VALUE (current)) = 0;
 
   /* And restore those of the previous context */
   if ((ctxp = next))           /* Assignment is really meant here */
     for (current = ctxp->import_list; current; current = TREE_CHAIN (current))
-      IS_A_SINGLE_IMPORT_CLASSFILE_NAME_P (TREE_PURPOSE (current)) = 1;
+      IS_A_SINGLE_IMPORT_CLASSFILE_NAME_P (TREE_VALUE (current)) = 1;
   
   /* If we pushed a context to parse a class intended to be generated,
      we keep it so we can remember the class. What we could actually
@@ -3253,6 +3257,8 @@ build_array_from_name (type, type_wfl, name, ret_name)
   /* If we have, then craft a new type for this variable */
   if (more_dims)
     {
+      tree save = type;
+
       name = get_identifier (&string [more_dims]);
 
       /* If we have a pointer, use its type */
@@ -3264,14 +3270,20 @@ build_array_from_name (type, type_wfl, name, ret_name)
       if (JPRIMITIVE_TYPE_P (type))
        {
          type = build_java_array_type (type, -1);
-         CLASS_LOADED_P (type) = 1;
          more_dims--;
        }
       /* Otherwise, if we have a WFL for this type, use it (the type
          is already an array on an unresolved type, and we just keep
          on adding dimensions) */
       else if (type_wfl)
-       type = type_wfl;
+       {
+         int i = 0;
+         type = type_wfl;
+         string = IDENTIFIER_POINTER (TYPE_NAME (save));
+         while (string[i]  == '[')
+           ++i;
+         more_dims += i;
+       }
 
       /* Add all the dimensions */
       while (more_dims--)
@@ -3296,23 +3308,26 @@ build_unresolved_array_type (type_or_wfl)
      tree type_or_wfl;
 {
   const char *ptr;
+  tree wfl;
 
   /* TYPE_OR_WFL might be an array on a resolved type. In this case,
      just create a array type */
   if (TREE_CODE (type_or_wfl) == RECORD_TYPE)
-    {
-      tree type = build_java_array_type (type_or_wfl, -1);
-      CLASS_LOADED_P (type) = CLASS_LOADED_P (type_or_wfl);
-      return type;
-    }
+    return build_java_array_type (type_or_wfl, -1);
 
   obstack_1grow (&temporary_obstack, '[');
   obstack_grow0 (&temporary_obstack,
                 IDENTIFIER_POINTER (EXPR_WFL_NODE (type_or_wfl)),
                 IDENTIFIER_LENGTH (EXPR_WFL_NODE (type_or_wfl)));
   ptr = obstack_finish (&temporary_obstack);
-  EXPR_WFL_NODE (type_or_wfl) = get_identifier (ptr);
-  return type_or_wfl;
+  wfl = build_expr_wfl (get_identifier (ptr),
+                       EXPR_WFL_FILENAME (type_or_wfl),
+                       EXPR_WFL_LINENO (type_or_wfl),
+                       EXPR_WFL_COLNO (type_or_wfl));
+  /* Re-install the existing qualifications so that the type can be
+     resolved properly. */
+  EXPR_WFL_QUALIFICATION (wfl) = EXPR_WFL_QUALIFICATION (type_or_wfl);
+  return wfl;
 }
 
 static void
@@ -3521,7 +3536,18 @@ find_as_inner_class (enclosing, name, cl)
          acc = merge_qualified_name (acc, 
                                      EXPR_WFL_NODE (TREE_PURPOSE (qual)));
          BUILD_PTR_FROM_NAME (ptr, acc);
-         decl = do_resolve_class (NULL_TREE, ptr, NULL_TREE, cl);
+
+         /* Don't try to resolve ACC as a class name if it follows
+            the current package name. We don't want to pick something
+            that's accidentally there: for example `a.b.c' in package
+            `a.b' shouldn't trigger loading `a' if it's there by
+            itself. */
+         if (ctxp->package
+             && strstr (IDENTIFIER_POINTER (ctxp->package),
+                        IDENTIFIER_POINTER (acc)))
+           decl = NULL;
+         else
+           decl = do_resolve_class (NULL_TREE, ptr, NULL_TREE, cl);
        }
 
       /* A NULL qual and a decl means that the search ended
@@ -3635,6 +3661,7 @@ maybe_create_class_interface_decl (decl, raw_name, qualified_name, cl)
   else
     DECL_SOURCE_LINE (decl) = EXPR_WFL_LINENO (cl);
   CLASS_FROM_SOURCE_P (TREE_TYPE (decl)) = 1;
+  CLASS_PARSED_P (TREE_TYPE (decl)) = 1;
   CLASS_FROM_CURRENTLY_COMPILED_P (TREE_TYPE (decl)) =
     IS_A_COMMAND_LINE_FILENAME_P (EXPR_WFL_FILENAME_NODE (cl));
 
@@ -4055,7 +4082,7 @@ lookup_field_wrapper (class, name)
   /* Last chance: if we're within the context of an inner class, we
      might be trying to access a local variable defined in an outer
      context. We try to look for it now. */
-  if (INNER_CLASS_TYPE_P (class))
+  if (INNER_CLASS_TYPE_P (class) && TREE_CODE (name) == IDENTIFIER_NODE)
     {
       tree new_name;
       MANGLE_OUTER_LOCAL_VARIABLE_NAME (new_name, name);
@@ -4290,22 +4317,29 @@ generate_finit (class_type)
   return mdecl;
 }
 
-static void
-add_instance_initializer (mdecl)
+static tree
+build_instance_initializer (mdecl)
      tree mdecl;
 {
-  tree current;
-  tree stmt_list = TYPE_II_STMT_LIST (DECL_CONTEXT (mdecl));
   tree compound = NULL_TREE;
+  tree stmt_list = TYPE_II_STMT_LIST (DECL_CONTEXT (mdecl));
+  tree current;
 
-  if (stmt_list)
-    {
-      for (current = stmt_list; current; current = TREE_CHAIN (current))
-       compound = add_stmt_to_compound (compound, NULL_TREE, current);
+  for (current = stmt_list; current; current = TREE_CHAIN (current))
+    compound = add_stmt_to_compound (compound, NULL_TREE, current);
 
-      java_method_add_stmt (mdecl, build1 (INSTANCE_INITIALIZERS_EXPR,
-                                          NULL_TREE, compound));
-    }
+  return compound;
+}
+
+static void
+add_instance_initializer (mdecl)
+     tree mdecl;
+{
+  tree compound = build_instance_initializer (mdecl);
+
+  if (compound)
+    java_method_add_stmt (mdecl, build1 (INSTANCE_INITIALIZERS_EXPR,
+                                        NULL_TREE, compound));
 }
 
 /* Shared accros method_declarator and method_header to remember the
@@ -5221,6 +5255,7 @@ java_fix_constructors ()
       if (CLASS_INTERFACE (TYPE_NAME (class_type)))
        continue;
 
+      current_class = class_type;
       for (decl = TYPE_METHODS (class_type); decl; decl = TREE_CHAIN (decl))
        {
          if (DECL_CONSTRUCTOR_P (decl))
@@ -5253,7 +5288,6 @@ safe_layout_class (class)
   current_class = save_current_class;
   input_filename = save_input_filename;
   lineno = save_lineno;
-  CLASS_LOADED_P (class) = 1;
 }
 
 static tree
@@ -5474,7 +5508,6 @@ resolve_class (enclosing, class_type, decl, cl)
       while (base != name)
        {
          resolved_type = build_java_array_type (resolved_type, -1);
-         CLASS_LOADED_P (resolved_type) = 1;
          name--;
        }
       /* A TYPE_NAME that is a TYPE_DECL was set in
@@ -5492,13 +5525,14 @@ tree
 do_resolve_class (enclosing, class_type, decl, cl)
      tree enclosing, class_type, decl, cl;
 {
-  tree new_class_decl;
+  tree new_class_decl, super, start;
 
   /* Do not try to replace TYPE_NAME (class_type) by a variable, since
      it is changed by find_in_imports{_on_demand} and (but it doesn't
      really matter) qualify_and_find */
 
   /* 0- Search in the current class as an inner class */
+  start = enclosing;
 
   /* Maybe some code here should be added to load the class or
      something, at least if the class isn't an inner class and ended
@@ -5521,14 +5555,28 @@ do_resolve_class (enclosing, class_type, decl, cl)
        }
 
       /* Now go to the upper classes, bail out if necessary. */
-      enclosing = CLASSTYPE_SUPER (TREE_TYPE (enclosing));
-      if (!enclosing || enclosing == object_type_node)
+      super = CLASSTYPE_SUPER (TREE_TYPE (enclosing));
+      if (!super || super == object_type_node)
         break;
 
-      if (TREE_CODE (enclosing) == POINTER_TYPE)
-       enclosing = do_resolve_class (NULL, enclosing, NULL, NULL);
+      if (TREE_CODE (super) == POINTER_TYPE)
+        super = do_resolve_class (NULL, super, NULL, NULL);
       else
-        enclosing = TYPE_NAME (enclosing);
+       super = TYPE_NAME (super);
+      /* We may not have checked for circular inheritance yet, so do so
+         here to prevent an infinite loop. */
+      if (super == start)
+        {
+          if (!cl)
+            cl = lookup_cl (decl);
+         
+          parse_error_context
+            (cl, "Cyclic inheritance involving %s",
+            IDENTIFIER_POINTER (DECL_NAME (enclosing)));
+          break;
+        }
+      enclosing = super;
     }
 
   /* 1- Check for the type in single imports. This will change
@@ -7106,7 +7154,6 @@ static void
 source_end_java_method ()
 {
   tree fndecl = current_function_decl;
-  int flag_asynchronous_exceptions = asynchronous_exceptions;
 
   if (!fndecl)
     return;
@@ -7114,9 +7161,6 @@ source_end_java_method ()
   java_parser_context_save_global ();
   lineno = ctxp->last_ccb_indent1;
 
-  /* 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. */
@@ -7138,24 +7182,14 @@ source_end_java_method ()
   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);
     }
 
   current_function_decl = NULL_TREE;
   java_parser_context_restore_global ();
-  asynchronous_exceptions = flag_asynchronous_exceptions;
 }
 
 /* Record EXPR in the current function block. Complements compound
@@ -7296,9 +7330,6 @@ java_layout_classes ()
       current_class = TREE_TYPE (TREE_VALUE (current));
       layout_class (current_class);
 
-      /* From now on, the class is considered completely loaded */
-      CLASS_LOADED_P (current_class) = 1;
-
       /* Error reported by the caller */
       if (java_error_count)
        return;
@@ -7539,7 +7570,7 @@ maybe_generate_pre_expand_clinit (class_type)
 }
 
 /* Analyzes a method body and look for something that isn't a
-   MODIFY_EXPR. */
+   MODIFY_EXPR with a constant value.  */
 
 static int
 analyze_clinit_body (bbody)
@@ -7563,11 +7594,10 @@ analyze_clinit_body (bbody)
        break;
        
       case MODIFY_EXPR:
-       bbody = NULL_TREE;
-       break;
+       /* Return 0 if the operand is constant, 1 otherwise.  */
+       return ! TREE_CONSTANT (TREE_OPERAND (bbody, 1));
 
       default:
-       bbody = NULL_TREE;
        return 1;
       }
   return 0;
@@ -8403,7 +8433,7 @@ build_dot_class_method (class)
   
   /* We initialize the variable with the exception handler. */
   catch = build (MODIFY_EXPR, NULL_TREE, catch_clause_param,
-                soft_exceptioninfo_call_node);
+                build (JAVA_EXC_OBJ_EXPR, ptr_type_node));
   add_stmt_to_block (catch_block, NULL_TREE, catch);
 
   /* We add the statement throwing the new exception */
@@ -8458,6 +8488,10 @@ fix_constructors (mdecl)
   tree thisn_assign, compound = NULL_TREE;
   tree class_type = DECL_CONTEXT (mdecl);
 
+  if (DECL_FIXED_CONSTRUCTOR_P (mdecl))
+    return;
+  DECL_FIXED_CONSTRUCTOR_P (mdecl) = 1;
+
   if (!body)
     {
       /* It is an error for the compiler to generate a default
@@ -8489,7 +8523,7 @@ fix_constructors (mdecl)
       /* We don't generate a super constructor invocation if we're
         compiling java.lang.Object. build_super_invocation takes care
         of that. */
-      compound = java_method_add_stmt (mdecl, build_super_invocation (mdecl));
+      java_method_add_stmt (mdecl, build_super_invocation (mdecl));
 
       /* Insert the instance initializer block right here, after the
          super invocation. */
@@ -8501,7 +8535,9 @@ fix_constructors (mdecl)
   else 
     {
       int found = 0;
+      tree found_call = NULL_TREE;
       tree main_block = BLOCK_EXPR_BODY (body);
+      tree ii;                 /* Instance Initializer */
       
       while (body)
        switch (TREE_CODE (body))
@@ -8512,27 +8548,38 @@ fix_constructors (mdecl)
            break;
          case COMPOUND_EXPR:
          case EXPR_WITH_FILE_LOCATION:
+           found_call = body;
            body = TREE_OPERAND (body, 0);
            break;
          case BLOCK:
+           found_call = body;
            body = BLOCK_EXPR_BODY (body);
            break;
          default:
            found = 0;
            body = NULL_TREE;
          }
+
+      /* Generate the assignment to this$<n>, if necessary */
+      if ((thisn_assign = build_thisn_assign ()))
+        compound = add_stmt_to_compound (compound, NULL_TREE, thisn_assign);
+
       /* The constructor is missing an invocation of super() */
       if (!found)
        compound = add_stmt_to_compound (compound, NULL_TREE,
                                          build_super_invocation (mdecl));
+      /* Explicit super() invokation should take place before the
+         instance initializer blocks. */
+      else
+       {
+         compound = add_stmt_to_compound (compound, NULL_TREE,
+                                          TREE_OPERAND (found_call, 0));
+         TREE_OPERAND (found_call, 0) = empty_stmt_node;
+       }
       
-      /* Generate the assignment to this$<n>, if necessary */
-      if ((thisn_assign = build_thisn_assign ()))
-        compound = add_stmt_to_compound (compound, NULL_TREE, thisn_assign);
-
-      /* Insert the instance initializer block right here, after the
-         super invocation. */
-      add_instance_initializer (mdecl);
+      /* Insert the instance initializer block right after. */
+      if ((ii = build_instance_initializer (mdecl)))
+       compound = add_stmt_to_compound (compound, NULL_TREE, ii);
 
       /* Fix the constructor main block if we're adding extra stmts */
       if (compound)
@@ -8603,7 +8650,7 @@ void
 java_expand_classes ()
 {
   int save_error_count = 0;
-  static struct parser_ctxt *saved_ctxp = NULL;
+  static struct parser_ctxt *cur_ctxp = NULL;
 
   java_parse_abort_on_error ();
   if (!(ctxp = ctxp_for_generation))
@@ -8611,10 +8658,10 @@ java_expand_classes ()
   java_layout_classes ();
   java_parse_abort_on_error ();
 
-  saved_ctxp = ctxp_for_generation;
-  for (; ctxp_for_generation; ctxp_for_generation = ctxp_for_generation->next)
+  cur_ctxp = ctxp_for_generation;
+  for (; cur_ctxp; cur_ctxp = cur_ctxp->next)
     {
-      ctxp = ctxp_for_generation;
+      ctxp = cur_ctxp;
       input_filename = ctxp->filename;
       lang_init_source (2);           /* Error msgs have method prototypes */
       java_complete_expand_classes (); /* Complete and expand classes */
@@ -8624,11 +8671,10 @@ java_expand_classes ()
 
   /* Find anonymous classes and expand their constructor, now they
      have been fixed. */
-  for (ctxp_for_generation = saved_ctxp;
-       ctxp_for_generation; ctxp_for_generation = ctxp_for_generation->next)
+  for (cur_ctxp = ctxp_for_generation;  cur_ctxp;  cur_ctxp = cur_ctxp->next)
     {
       tree current;
-      ctxp = ctxp_for_generation;
+      ctxp = cur_ctxp;
       for (current = ctxp->class_list; current; current = TREE_CHAIN (current))
        {
          current_class = TREE_TYPE (current);
@@ -8658,11 +8704,10 @@ java_expand_classes ()
     return;
 
   /* Now things are stable, go for generation of the class data. */
-  for (ctxp_for_generation = saved_ctxp;
-       ctxp_for_generation; ctxp_for_generation = ctxp_for_generation->next)
+  for (cur_ctxp = ctxp_for_generation;  cur_ctxp;  cur_ctxp = cur_ctxp->next)
     {
       tree current;
-      ctxp = ctxp_for_generation;
+      ctxp = cur_ctxp;
       for (current = ctxp->class_list; current; current = TREE_CHAIN (current))
        {
          current_class = TREE_TYPE (current);
@@ -8858,8 +8903,8 @@ resolve_expression_name (id, orig)
              /* Otherwise build what it takes to access the field */
              access = build_field_ref ((fs ? NULL_TREE : current_this),
                                        DECL_CONTEXT (decl), name);
-             if (fs && !flag_emit_class_files && !flag_emit_xref)
-               access = build_class_init (DECL_CONTEXT (access), access);
+             if (fs)
+               access = maybe_build_class_init_for_field (decl, access);
              /* We may be asked to save the real field access node */
              if (orig)
                *orig = access;
@@ -8942,29 +8987,16 @@ resolve_field_access (qual_wfl, field_decl, field_type)
     field_ref = decl;
   else if (JDECL_P (decl))
     {
-      int static_final_found = 0;
       if (!type_found)
        type_found = DECL_CONTEXT (decl);
-      is_static = JDECL_P (decl) && FIELD_STATIC (decl);
-      if (CLASS_FINAL_VARIABLE_P (decl)
-         && JPRIMITIVE_TYPE_P (TREE_TYPE (decl))
-         && DECL_INITIAL (decl))
-       {
-         /* When called on a FIELD_DECL of the right (primitive)
-            type, java_complete_tree will try to substitue the decl
-            for it's initial value. */
-         field_ref = java_complete_tree (decl);
-         static_final_found = 1;
-       }
-      else
-       field_ref = build_field_ref ((is_static && !flag_emit_xref? 
-                                     NULL_TREE : where_found), 
-                                    type_found, DECL_NAME (decl));
+      is_static = FIELD_STATIC (decl);
+      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 && !flag_emit_xref)
-       field_ref = build_class_init (DECL_CONTEXT (decl), field_ref);
+      if (is_static)
+       field_ref = maybe_build_class_init_for_field (decl, field_ref);
     }
   else
     field_ref = decl;
@@ -9131,7 +9163,6 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found)
          if (decl == error_mark_node)
            return 1;
          *type_found = type = QUAL_DECL_TYPE (decl);
-         CLASS_LOADED_P (type) = 1;
          continue;
 
        case CONVERT_EXPR:
@@ -9193,7 +9224,8 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found)
       previous_call_static = 0;
 
       /* It can be the keyword THIS */
-      if (EXPR_WFL_NODE (qual_wfl) == this_identifier_node)
+      if (TREE_CODE (qual_wfl) == EXPR_WITH_FILE_LOCATION
+         && EXPR_WFL_NODE (qual_wfl) == this_identifier_node)
        {
          if (!current_this)
            {
@@ -9244,7 +9276,8 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found)
        }
 
       /* 15.10.2 Accessing Superclass Members using SUPER */
-      if (EXPR_WFL_NODE (qual_wfl) == super_identifier_node)
+      if (TREE_CODE (qual_wfl) == EXPR_WITH_FILE_LOCATION
+         && EXPR_WFL_NODE (qual_wfl) == super_identifier_node)
        {
          tree node;
          /* Check on the restricted use of SUPER */
@@ -9444,12 +9477,10 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found)
                  && !CLASS_LOADED_P (field_decl_type)
                  && !TYPE_ARRAY_P (field_decl_type))
                resolve_and_layout (field_decl_type, NULL_TREE);
-             if (TYPE_ARRAY_P (field_decl_type))
-               CLASS_LOADED_P (field_decl_type) = 1;
              
              /* Check on accessibility here */
              if (not_accessible_p (current_class, field_decl,
-                                   TREE_TYPE (decl), from_super))
+                                   DECL_CONTEXT (field_decl), from_super))
                {
                  parse_error_context 
                    (qual_wfl,
@@ -9574,7 +9605,7 @@ not_accessible_p (reference, member, where, from_super)
       /* If where is active, access was made through a
         qualifier. Access is granted if the type of the qualifier is
         or is a sublass of the type the access made from (6.6.2.1.)  */
-      if (where && !inherits_from_p (where, reference))
+      if (where && !inherits_from_p (reference, where))
        return 1;
 
       /* Otherwise, access is granted if occuring from the class where
@@ -9874,7 +9905,29 @@ patch_method_invocation (patch, primary, where, from_super,
          alternate class is specified. */
       else
        {
-         class_to_search = (where ? where : current_class);
+         if (where != NULL_TREE)
+           class_to_search = where;
+         else if (QUALIFIED_P (name))
+           class_to_search = current_class;
+         else
+           {
+             class_to_search = current_class;
+
+             for (;;)
+               {
+                 if (has_method (class_to_search, name))
+                   break;
+                 if (! INNER_CLASS_TYPE_P (class_to_search))
+                   {
+                     parse_error_context (wfl,
+                                          "No method named `%s' in scope",
+                                          IDENTIFIER_POINTER (name));
+                     PATCH_METHOD_RETURN_ERROR ();
+                   }
+                 class_to_search
+                   = TREE_TYPE (DECL_CONTEXT (TYPE_NAME (class_to_search)));
+               }
+           }
          lc = 0;
        }
 
@@ -9966,12 +10019,15 @@ patch_method_invocation (patch, primary, where, from_super,
       /* Calls to clone() on array types are permitted as a special-case. */
       && !is_array_clone_call)
     {
-      char *fct_name = (char *) IDENTIFIER_POINTER (DECL_NAME (list));
-      char *access = java_accstring_lookup (get_access_flags_from_decl (list));
-      char *klass = (char *) IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (DECL_CONTEXT (list))));
-      char *refklass = (char *) IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (current_class)));
-      char *what = (char *) (DECL_CONSTRUCTOR_P (list)
-                            ? "constructor" : "method");
+      const char *fct_name = IDENTIFIER_POINTER (DECL_NAME (list));
+      const char *access =
+       java_accstring_lookup (get_access_flags_from_decl (list));
+      const char *klass =
+       IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (DECL_CONTEXT (list))));
+      const char *refklass =
+       IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (current_class)));
+      const char *what = (DECL_CONSTRUCTOR_P (list)
+                         ? "constructor" : "method");
       /* FIXME: WFL yields the wrong message here but I don't know
         what else to use.  */
       parse_error_context (wfl,
@@ -10079,7 +10135,7 @@ patch_method_invocation (patch, primary, where, from_super,
       /* Prepare to pass hidden parameters to finit$, if any. */
       finit_parms = build_alias_initializer_parameter_list 
        (AIPL_FUNCTION_FINIT_INVOCATION, current_class, NULL_TREE, NULL);
-
+      
       finit_call = 
        build_method_invocation (build_wfl_node (finit_identifier_node),
                                 finit_parms);
@@ -10477,8 +10533,6 @@ find_applicable_accessible_methods_list (lc, class, name, arglist)
   /* Search classes */
   else
     {
-      tree sc = class;
-      int seen_inner_class = 0;
       search_applicable_methods_list (lc, TYPE_METHODS (class), 
                                      name, arglist, &list, &all_list);
 
@@ -10495,7 +10549,7 @@ find_applicable_accessible_methods_list (lc, class, name, arglist)
       /* We must search all interfaces of this class */
       if (!lc)
       {
-       tree basetype_vec = TYPE_BINFO_BASETYPES (sc);
+       tree basetype_vec = TYPE_BINFO_BASETYPES (class);
        int n = TREE_VEC_LENGTH (basetype_vec), i;
        for (i = 1; i < n; i++)
          {
@@ -10510,24 +10564,6 @@ find_applicable_accessible_methods_list (lc, class, name, arglist)
          }
       }
 
-      /* Search enclosing context of inner classes before looking
-         ancestors up. */
-      while (!lc && INNER_CLASS_TYPE_P (class))
-       {
-         tree rlist;
-         seen_inner_class = 1;
-         class = TREE_TYPE (DECL_CONTEXT (TYPE_NAME (class)));
-         rlist = find_applicable_accessible_methods_list (lc, class, 
-                                                          name, arglist);
-         list = chainon (rlist, list);
-       }
-
-      if (!lc && seen_inner_class 
-         && TREE_TYPE (DECL_CONTEXT (TYPE_NAME (sc))) == CLASSTYPE_SUPER (sc))
-       class = CLASSTYPE_SUPER (sc);
-      else
-       class = sc;
-
       /* Search superclass */
       if (!lc && CLASSTYPE_SUPER (class) != NULL_TREE)
        {
@@ -10813,6 +10849,10 @@ qualify_ambiguous_name (id)
     else if (code == INTEGER_CST)
       name = qual_wfl;
     
+    else if (code == CONVERT_EXPR &&
+            TREE_CODE (TREE_OPERAND (qual_wfl, 0)) == EXPR_WITH_FILE_LOCATION)
+      name = TREE_OPERAND (qual_wfl, 0);
+    
     else if ((code == ARRAY_REF || code == CALL_EXPR || code == MODIFY_EXPR) &&
             TREE_CODE (TREE_OPERAND (qual_wfl, 0)) == EXPR_WITH_FILE_LOCATION)
       name = EXPR_WFL_NODE (TREE_OPERAND (qual_wfl, 0));
@@ -10827,7 +10867,7 @@ qualify_ambiguous_name (id)
        qual_wfl = QUAL_WFL (qual);
        again = 1;
       }
-    else 
+    else
       {
        name = EXPR_WFL_NODE (qual_wfl);
        if (!name)
@@ -10855,8 +10895,10 @@ qualify_ambiguous_name (id)
        qual_wfl = QUAL_WFL (qual);
        if (TREE_CODE (qual_wfl) == CALL_EXPR)
          again = 1;
-       else
+       else if (TREE_CODE (qual_wfl) == EXPR_WITH_FILE_LOCATION)
          name = EXPR_WFL_NODE (qual_wfl);
+       else if (TREE_CODE (qual_wfl) == NEW_CLASS_EXPR)
+         name = TREE_OPERAND (qual_wfl, 0);
        this_found = 1;
       }
     /* If we have a SUPER, we set the context accordingly */
@@ -10894,7 +10936,7 @@ qualify_ambiguous_name (id)
      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))
+          || name == length_identifier_node)
     {
       RESOLVE_EXPRESSION_NAME_P (qual_wfl) = 1;
       QUAL_RESOLUTION (qual) = (new_array_found ? NULL_TREE : decl);
@@ -10919,7 +10961,8 @@ qualify_ambiguous_name (id)
   /* Method call, array references and cast are expression name */
   else if (TREE_CODE (QUAL_WFL (qual)) == CALL_EXPR
           || TREE_CODE (QUAL_WFL (qual)) == ARRAY_REF
-          || TREE_CODE (QUAL_WFL (qual)) == CONVERT_EXPR)
+          || TREE_CODE (QUAL_WFL (qual)) == CONVERT_EXPR
+          || TREE_CODE (QUAL_WFL (qual)) == MODIFY_EXPR)
     RESOLVE_EXPRESSION_NAME_P (qual_wfl) = 1;
 
   /* Check here that NAME isn't declared by more than one
@@ -11961,6 +12004,7 @@ maybe_absorb_scoping_blocks ()
    are completing them.  */
 
 /* Wrap a non WFL node around a WFL.  */
+
 static tree
 build_wfl_wrap (node, location)
     tree node;
@@ -11981,7 +12025,6 @@ build_wfl_wrap (node, location)
   return wfl;
 }
 
-
 /* Build a super() constructor invocation. Returns empty_stmt_node if
    we're currently dealing with the class java.lang.Object. */
 
@@ -12376,6 +12419,7 @@ maybe_build_primttype_type_ref (rhs, wfl)
       if (TREE_CODE (n) == VAR_DECL 
          && DECL_NAME (n) == TYPE_identifier_node
          && rhs_type == class_ptr_type
+         && TREE_CODE (wfl) == EXPR_WITH_FILE_LOCATION
          && TREE_CODE (EXPR_WFL_NODE (wfl)) == IDENTIFIER_NODE)
        {
          const char *self_name = IDENTIFIER_POINTER (EXPR_WFL_NODE (wfl));
@@ -12524,12 +12568,15 @@ patch_assignment (node, wfl_op1, wfl_op2)
        base = TREE_OPERAND (lvalue, 0);
       else
        {
-         base = TREE_OPERAND (base, 0);
-         if (flag_bounds_check)
-           base = TREE_OPERAND (base, 1);
-         if (flag_check_references)
-           base = TREE_OPERAND (base, 1);
-         base = TREE_OPERAND (base, 0);        
+          tree op = TREE_OPERAND (base, 0);
+         
+          /* We can have a SAVE_EXPR here when doing String +=.  */
+          if (TREE_CODE (op) == SAVE_EXPR)
+            op = TREE_OPERAND (op, 0);
+          if (flag_bounds_check)
+            base = TREE_OPERAND (TREE_OPERAND (op, 1), 0);
+          else
+            base = TREE_OPERAND (op, 0);
        }
 
       /* Build the invocation of _Jv_CheckArrayStore */
@@ -12555,16 +12602,31 @@ patch_assignment (node, wfl_op1, wfl_op2)
            TREE_OPERAND (lvalue, 1) = build (COMPOUND_EXPR, lhs_type,
                                              check, TREE_OPERAND (lvalue, 1));
        }
-      else 
+      else if (flag_bounds_check)
        {
+          tree hook = lvalue;
+          tree compound = TREE_OPERAND (lvalue, 0);
+          tree bound_check, new_compound;
+
+          if (TREE_CODE (compound) == SAVE_EXPR)
+            {
+              compound = TREE_OPERAND (compound, 0);
+              hook = TREE_OPERAND (hook, 0);
+            }
+
+          /* Find the array bound check, hook the original array access. */
+          bound_check = TREE_OPERAND (compound, 0);
+          TREE_OPERAND (hook, 0) = TREE_OPERAND (compound, 1);
+
          /* 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);
-       }
+          new_compound =
+            build (COMPOUND_EXPR, void_type_node, bound_check, check);
+
+          /* Re-assemble the augmented array access. */
+          lvalue = build (COMPOUND_EXPR, lhs_type, new_compound, lvalue);
+        }
+      else
+        lvalue = build (COMPOUND_EXPR, lhs_type, check, lvalue);
     }
 
   /* Final locals can be used as case values in switch
@@ -12607,7 +12669,7 @@ try_reference_assignconv (lhs_type, rhs)
       else if (valid_ref_assignconv_cast_p (rhs_type, lhs_type, 0))
        new_rhs = rhs;
       /* This is a magic assignment that we process differently */
-      else if (rhs == soft_exceptioninfo_call_node)
+      else if (TREE_CODE (rhs) == JAVA_EXC_OBJ_EXPR)
        new_rhs = rhs;
     }
   return new_rhs;
@@ -13732,8 +13794,11 @@ patch_incomplete_class_ref (node)
 
   if (!flag_emit_class_files || JPRIMITIVE_TYPE_P (ref_type))
     {
+      tree dot = build_class_ref (ref_type);
       /* A class referenced by `foo.class' is initialized.  */
-      return build_class_init (ref_type, build_class_ref (ref_type));
+      if (!flag_emit_class_files)
+       dot = build_class_init (ref_type, dot);
+      return java_complete_tree (dot);
     }
 
   /* If we're emitting class files and we have to deal with non
@@ -13964,11 +14029,7 @@ resolve_type_during_patch (type)
                               IDENTIFIER_POINTER (EXPR_WFL_NODE (type)));
          return NULL_TREE;
        }
-      else
-       {
-         CLASS_LOADED_P (TREE_TYPE (type_decl)) = 1;
-         return TREE_TYPE (type_decl);
-       }
+      return TREE_TYPE (type_decl);
     }
   return type;
 }
@@ -15488,6 +15549,29 @@ patch_conditional_expr (node, wfl_cond, wfl_op1)
   return node;
 }
 
+/* Wrap EXPR with code to initialize DECL's class, if appropriate. */
+
+static tree
+maybe_build_class_init_for_field (decl, expr)
+    tree decl, expr;
+{
+  tree clas = DECL_CONTEXT (decl);
+  if (flag_emit_class_files || flag_emit_xref)
+    return expr;
+
+  if (TREE_CODE (decl) == VAR_DECL && FIELD_STATIC (decl)
+      && FIELD_FINAL (decl))
+    {
+      tree init = DECL_INITIAL (decl);
+      if (init != NULL_TREE)
+       init = fold_constant_for_init (init, decl);
+      if (init != NULL_TREE && CONSTANT_VALUE_P (init))
+       return expr;
+    }
+
+  return build_class_init (clas, expr);
+}
+
 /* Try to constant fold NODE.
    If NODE is not a constant expression, return NULL_EXPR.
    CONTEXT is a static final VAR_DECL whose initializer we are folding. */
@@ -15500,11 +15584,13 @@ fold_constant_for_init (node, context)
   tree op0, op1, val;
   enum tree_code code = TREE_CODE (node);
 
-  if (code == STRING_CST || code == INTEGER_CST || code == REAL_CST)
-    return node;
-
   switch (code)
     {
+    case STRING_CST:
+    case INTEGER_CST:
+    case REAL_CST:
+      return node;
+
     case PLUS_EXPR:
     case MINUS_EXPR:
     case MULT_EXPR: