[PATCH] Java: fixing PR #172, 173, 174, 176 and 178. Other improvements.

Alexandre Petit-Bianco apbianco@cygnus.com
Wed Mar 22 22:56:00 GMT 2000


I'm checking in this patch. It fixed the following PRs:

  http://sourceware.cygnus.com/ml/java-prs/2000-q1/msg00169.html
  http://sourceware.cygnus.com/ml/java-prs/2000-q1/msg00170.html
  http://sourceware.cygnus.com/ml/java-prs/2000-q1/msg00171.html
  http://sourceware.cygnus.com/ml/java-prs/2000-q1/msg00180.html
  http://sourceware.cygnus.com/ml/java-prs/2000-q1/msg00190.html

It also fixes the way the compiler choses the most specific method and
generates the synthetic method `class$' to implement the `<type>.class'
1.1 extension.

./A

Index: ChangeLog
===================================================================
RCS file: /cvs/gcc/egcs/gcc/java/ChangeLog,v
retrieving revision 1.392
diff -u -p -r1.392 ChangeLog
--- ChangeLog	2000/03/22 22:48:04	1.392
+++ ChangeLog	2000/03/23 06:39:17
@@ -1,3 +1,18 @@
+2000-03-22  Alexandre Petit-Bianco  <apbianco@cygnus.com>
+
+	* parse.y (check_abstract_method_definitions): New local
+	`end_type_reached'. Make sure we also consider `end_type'.
+	(java_check_abstract_method_definitions): Make sure we also
+	eventually consider `java.lang.Object'.
+	(maybe_use_access_method): Don't use access method if not a pure
+	inner class or if the method's context is right.
+	(find_applicable_accessible_methods_list): New static
+	`object_done'. Don't search abstract classes as interfaces. Fixed
+	indentation. Fixed the `java.lang.Object' only search. Search class'
+	interface(s) first, fully search enclosing contexts. 
+	(find_most_specific_methods_list): Pick closest candidates when
+	they're all abstract.
+
 Mon Mar 20 08:58:51 2000  Alexandre Petit-Bianco  <apbianco@cygnus.com>
 
 	* jcf-write.c (generate_bytecode_insns): TRY_FINALLY_EXPR:
@@ -8,6 +23,31 @@ Mon Mar 20 08:58:51 2000  Alexandre Peti
 
 	* except.c (emit_handlers): Clear catch_clauses_last.
 
+2000-03-17  Alexandre Petit-Bianco  <apbianco@cygnus.com>
+
+	* parse.y (check_method_types_complete): New function.
+	(create_class): Reset anonymous class counter only when seeing an
+	non inner classe.
+	(java_complete_class): JDEP_METHOD: Don't recompute signature
+	if incomplete.
+
+2000-03-17  Alexandre Petit-Bianco  <apbianco@cygnus.com>
+
+	* class.c (build_static_ref): Fixed indentation in comment.
+	* java-tree.def (TRY_EXPR): Fixed typo in name.
+	(CLASS_LITERAL): Likewise.
+	* java-tree.h: (TYPE_DOT_CLASS): New macro.
+	(struct lang_type): New field `dot_class'.
+	* jcf-write.c (generate_bytecode_insns): Fixed error message.
+	(generate_classfile): Method `class$' is synthetic.
+	* parse.y (build_do_class_method): New function.
+	(build_dot_class_method_invocation): Likewise.
+	(java_complete_expand_methods): Expand TYPE_DOT_CLASS if necessary.
+	(resolve_qualified_expression_name): Handle CLASS_LITERAL.
+	(qualify_ambiguous_name): Likewise.
+	(patch_incomplete_class_ref): Invoke synthetic method if necessary.
+	(build_try_statement): Fixed leading comment.
+
 Fri Mar 17 08:09:14 2000  Richard Kenner  <kenner@vlsi1.ultra.nyu.edu>
 
 	* class.c (make_field_value): Properly handle sizes.
@@ -34,6 +74,26 @@ Fri Mar 17 08:09:14 2000  Richard Kenner
 2000-03-16  Tom Tromey  <tromey@cygnus.com>
 
 	* lang.c (lang_decode_option): Enable -Wunused when -Wall given.
+
+2000-03-15  Alexandre Petit-Bianco  <apbianco@cygnus.com>
+
+	* parse.h (INNER_ENCLOSING_SCOPE_CHECK): Disregard anonymous
+	classes.
+	* parse.y (patch_method_invocation): Handle anonymous classes
+	creation in static context.
+
+2000-03-15  Alexandre Petit-Bianco  <apbianco@cygnus.com>
+
+	* parse.h (INNER_ENCLOSING_SCOPE_CHECK): New macro.
+	* parse.y (resolve_qualified_expression_name): Use it.
+	(patch_method_invocation): Likewise.
+
+2000-03-15  Alexandre Petit-Bianco  <apbianco@cygnus.com>
+
+	* parse.y (register_incomplete_type): JDEP_ENCLOSING set
+	depending on the type of dependency which dictates what the
+	current class is.
+	(unresolved_type_p): Resolved types limited to the current class.
 
 2000-03-15  Tom Tromey  <tromey@cygnus.com>
 
Index: class.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/java/class.c,v
retrieving revision 1.60
diff -u -p -r1.60 class.c
--- class.c	2000/03/17 17:31:57	1.60
+++ class.c	2000/03/23 06:39:21
@@ -967,8 +967,7 @@ build_static_field_ref (fdecl)
   else
     {
       /* Compile as:
-       * *(FTYPE*)build_class_ref(FCLASS)->fields[INDEX].info.addr
-       */
+       * *(FTYPE*)build_class_ref(FCLASS)->fields[INDEX].info.addr */
       static tree fields_ident = NULL_TREE;
       static tree info_ident = NULL_TREE;
       tree ref = build_class_ref (fclass);
Index: java-tree.def
===================================================================
RCS file: /cvs/gcc/egcs/gcc/java/java-tree.def,v
retrieving revision 1.12
diff -u -p -r1.12 java-tree.def
--- java-tree.def	2000/03/14 05:01:04	1.12
+++ java-tree.def	2000/03/23 06:39:22
@@ -50,7 +50,7 @@ DEFTREECODE (DEFAULT_EXPR, "default", 'x
 /* Try expression
    Operand 0 is the tried block,
    Operand 1 contains chained catch nodes. */
-DEFTREECODE (TRY_EXPR, "try-catch-finally", 'e', 2)
+DEFTREECODE (TRY_EXPR, "try-catch", 'e', 2)
 
 /* Catch clause.
    Operand 0 is the catch clause block, which contains the declaration of
@@ -86,7 +86,7 @@ DEFTREECODE (NEW_ARRAY_INIT, "new_array_
 /* Class literal.
    Operand 0 is the name of the class we're trying to build a
    reference from.  */
-DEFTREECODE (CLASS_LITERAL, "class_litteral", '1', 1)
+DEFTREECODE (CLASS_LITERAL, "class_literal", '1', 1)
 
 /* Instance initializer.
    Operand 0 contains the intance initializer statement. This tree node
Index: java-tree.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/java/java-tree.h,v
retrieving revision 1.61
diff -u -p -r1.61 java-tree.h
--- java-tree.h	2000/03/16 18:32:45	1.61
+++ java-tree.h	2000/03/23 06:39:25
@@ -547,6 +547,9 @@ struct lang_decl_var
 #define TYPE_FINIT_STMT_LIST(T)  (TYPE_LANG_SPECIFIC(T)->finit_stmt_list)
 #define TYPE_CLINIT_STMT_LIST(T) (TYPE_LANG_SPECIFIC(T)->clinit_stmt_list)
 #define TYPE_II_STMT_LIST(T)     (TYPE_LANG_SPECIFIC(T)->ii_block)
+/* The decl of the synthetic method `class$' used to handle `.class'
+   for non primitive types when compiling to bytecode. */
+#define TYPE_DOT_CLASS(T)        (TYPE_LANG_SPECIFIC(T)->dot_class)
 
 struct lang_type
 {
@@ -557,6 +560,10 @@ struct lang_type
   tree finit_stmt_list;		/* List of statements $finit$ will use */
   tree clinit_stmt_list;	/* List of statements <clinit> will use  */
   tree ii_block;		/* Instance initializer block */
+  tree dot_class;		/* The decl of the `class$' function that
+				   needs to be invoked and generated when
+				   compiling to bytecode to implement
+				   <non_primitive_type>.class */
 };
 
 #ifdef JAVA_USE_HANDLES
Index: jcf-write.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/java/jcf-write.c,v
retrieving revision 1.51
diff -u -p -r1.51 jcf-write.c
--- jcf-write.c	2000/03/22 22:48:04	1.51
+++ jcf-write.c	2000/03/23 06:39:32
@@ -2569,7 +2569,7 @@ generate_bytecode_insns (exp, target, st
       /* fall through */
     notimpl:
     default:
-      error("internal error - tree code not implemented: %s",
+      error("internal error in generate_bytecode_insn - tree code not implemented: %s",
 	    tree_code_name [(int) TREE_CODE (exp)]);
     }
 }
@@ -2911,7 +2911,8 @@ generate_classfile (clas, state)
 
       /* Make room for the Synthetic attribute (of zero length.)  */
       if (DECL_FINIT_P (part) 
-	  || OUTER_FIELD_ACCESS_IDENTIFIER_P (DECL_NAME (part)))
+	  || OUTER_FIELD_ACCESS_IDENTIFIER_P (DECL_NAME (part))
+	  || TYPE_DOT_CLASS (clas) == part)
 	{
 	  i++;
 	  synthetic_p = 1;
Index: parse.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/java/parse.h,v
retrieving revision 1.47
diff -u -p -r1.47 parse.h
--- parse.h	2000/03/14 05:01:05	1.47
+++ parse.h	2000/03/23 06:40:27
@@ -823,6 +823,17 @@ struct parser_ctxt {
                                      TREE_VALUE (GET_ENCLOSING_CPC ()) :      \
 				     NULL_TREE)
 
+/* Make sure that innerclass T sits in an appropriate enclosing
+   context.  */
+#define INNER_ENCLOSING_SCOPE_CHECK(T)					\
+  (INNER_CLASS_TYPE_P ((T)) && !ANONYMOUS_CLASS_P ((T))			\
+   /* We have a this and it's not the right one */			\
+   && ((current_this							\
+	&& (DECL_CONTEXT (TYPE_NAME ((T)))				\
+	    != TYPE_NAME (TREE_TYPE (TREE_TYPE (current_this)))))	\
+       /* We don't have a this. */					\
+       || !current_this))
+
 /* Push macro. First argument to PUSH_CPC is a DECL_TYPE, second
    argument is the unqualified currently parsed class name.  */
 #define PUSH_CPC(C,R) { 					\
Index: parse.y
===================================================================
RCS file: /cvs/gcc/egcs/gcc/java/parse.y,v
retrieving revision 1.145
diff -u -p -r1.145 parse.y
--- parse.y	2000/03/15 09:30:39	1.145
+++ parse.y	2000/03/23 06:41:01
@@ -238,6 +238,7 @@ static void start_artificial_method_body
 static void end_artificial_method_body PARAMS ((tree));
 static int check_method_redefinition PARAMS ((tree, tree));
 static int reset_method_name PARAMS ((tree));
+static int check_method_types_complete PARAMS ((tree));
 static void java_check_regular_methods PARAMS ((tree));
 static void java_check_abstract_methods PARAMS ((tree));
 static tree maybe_build_primttype_type_ref PARAMS ((tree, tree));
@@ -314,6 +315,9 @@ static tree create_anonymous_class PARAM
 static void patch_anonymous_class PARAMS ((tree, tree, tree));
 static void add_inner_class_fields PARAMS ((tree, tree));
 
+static tree build_dot_class_method PARAMS ((tree));
+static tree build_dot_class_method_invocation PARAMS ((tree));
+
 /* Number of error found so far. */
 int java_error_count; 
 /* Number of warning found so far. */
@@ -3832,8 +3836,8 @@ create_class (flags, id, super, interfac
   /* Eventually sets the @deprecated tag flag */
   CHECK_DEPRECATED (decl);
 
-  /* Reset the anonymous class counter when declaring a toplevel class */
-  if (TOPLEVEL_CLASS_DECL_P (decl))
+  /* Reset the anonymous class counter when declaring non inner classes */
+  if (!INNER_CLASS_DECL_P (decl))
     anonymous_class_counter = 1;
 
   return decl;
@@ -4702,9 +4706,16 @@ unresolved_type_p (wfl, returned)
 {
   if (TREE_CODE (wfl) == EXPR_WITH_FILE_LOCATION)
     {
-      tree decl = IDENTIFIER_CLASS_VALUE (EXPR_WFL_NODE (wfl));
       if (returned)
-	*returned = (decl ? TREE_TYPE (decl) : NULL_TREE);
+	{
+	  tree decl = IDENTIFIER_CLASS_VALUE (EXPR_WFL_NODE (wfl));
+	  if (decl && current_class && (decl == TYPE_NAME (current_class)))
+	    *returned = TREE_TYPE (decl);
+	  else if (GET_CPC_UN () == EXPR_WFL_NODE (wfl))
+	    *returned = TREE_TYPE (GET_CPC ());
+	  else
+	    *returned = NULL_TREE;
+	}
       return 1;
     }
   if (returned)
@@ -4883,7 +4894,10 @@ register_incomplete_type (kind, wfl, dec
   JDEP_WFL (new) = wfl;
   JDEP_CHAIN (new) = NULL;
   JDEP_MISC (new) = NULL_TREE;
-  if(!(JDEP_ENCLOSING (new) = GET_ENCLOSING_CPC_CONTEXT ()))
+  if ((kind == JDEP_SUPER || kind == JDEP_INTERFACE)
+      && GET_ENCLOSING_CPC ())
+    JDEP_ENCLOSING (new) = TREE_VALUE (GET_ENCLOSING_CPC ());
+  else
     JDEP_ENCLOSING (new) = GET_CPC ();
   JDEP_GET_PATCH (new) = (tree *)NULL;
 
@@ -5228,9 +5242,14 @@ java_complete_class ()
 		{
 		  tree mdecl = JDEP_DECL (dep), signature;
 		  push_obstacks (&permanent_obstack, &permanent_obstack);
-		  /* Recompute and reset the signature */
-		  signature = build_java_signature (TREE_TYPE (mdecl));
-		  set_java_signature (TREE_TYPE (mdecl), signature);
+		  /* Recompute and reset the signature, check first that
+		     all types are now defined. If they're not,
+		     dont build the signature. */
+		  if (check_method_types_complete (mdecl))
+		    {
+		      signature = build_java_signature (TREE_TYPE (mdecl));
+		      set_java_signature (TREE_TYPE (mdecl), signature);
+		    }
 		  pop_obstacks ();
 		}
 	      else
@@ -5698,6 +5717,7 @@ check_abstract_method_definitions (do_in
     {
       tree other_super, other_method, method_sig, method_name;
       int found = 0;
+      int end_type_reached = 0;
       
       if (!METHOD_ABSTRACT (method) || METHOD_FINAL (method))
 	continue;
@@ -5711,27 +5731,31 @@ check_abstract_method_definitions (do_in
       if (TREE_CODE (method_name) == EXPR_WITH_FILE_LOCATION)
 	method_name = EXPR_WFL_NODE (method_name);
 
-      for (other_super = class; other_super != end_type; 
-	   other_super = CLASSTYPE_SUPER (other_super))
-	{
-	  for (other_method = TYPE_METHODS (other_super); other_method;
-	       other_method = TREE_CHAIN (other_method))
-	    {
-	      tree s = build_java_signature (TREE_TYPE (other_method));
-	      tree other_name = DECL_NAME (other_method);
-
-	      if (TREE_CODE (other_name) == EXPR_WITH_FILE_LOCATION)
-		other_name = EXPR_WFL_NODE (other_name);
-	      if (!DECL_CLINIT_P (other_method)
-		  && !DECL_CONSTRUCTOR_P (other_method)
-		  && method_name == other_name && method_sig == s)
-		{
-		  found = 1;
-		  break;
-		}
-	    }
-	}
-      
+      other_super = class;
+      do {
+	if (other_super == end_type)
+	  end_type_reached = 1;
+	
+	/* Method search */
+	for (other_method = TYPE_METHODS (other_super); other_method;
+            other_method = TREE_CHAIN (other_method))
+	  {
+	    tree s = build_java_signature (TREE_TYPE (other_method));
+	    tree other_name = DECL_NAME (other_method);
+	    
+	    if (TREE_CODE (other_name) == EXPR_WITH_FILE_LOCATION)
+	      other_name = EXPR_WFL_NODE (other_name);
+	    if (!DECL_CLINIT_P (other_method)
+		&& !DECL_CONSTRUCTOR_P (other_method)
+		&& method_name == other_name && method_sig == s)
+             {
+               found = 1;
+               break;
+             }
+	  }
+	other_super = CLASSTYPE_SUPER (other_super);
+      } while (!end_type_reached);
+ 
       /* Report that abstract METHOD didn't find an implementation
 	 that CLASS can use. */
       if (!found)
@@ -5781,14 +5805,11 @@ java_check_abstract_method_definitions (
     return;
 
   /* Check for inherited types */
-  for (super = CLASSTYPE_SUPER (class); super != object_type_node; 
-       super = CLASSTYPE_SUPER (super))
-    {
-      if (!CLASS_ABSTRACT (TYPE_NAME (super)))
-	continue;
-
-      check_abstract_method_definitions (0, class_decl, super);
-    }
+  super = class;
+  do {
+    super = CLASSTYPE_SUPER (super);
+    check_abstract_method_definitions (0, class_decl, super);
+  } while (super != object_type_node);
 
   /* Check for implemented interfaces. */
   vector = TYPE_BINFO_BASETYPES (class);
@@ -5799,6 +5820,30 @@ java_check_abstract_method_definitions (
     }
 }
 
+/* Check all the types method DECL uses and return 1 if all of them
+   are now complete, 0 otherwise. This is used to check whether its
+   safe to build a method signature or not.  */
+
+static int
+check_method_types_complete (decl)
+     tree decl;
+{
+  tree type = TREE_TYPE (decl);
+  tree args;
+
+  if (!INCOMPLETE_TYPE_P (TREE_TYPE (type)))
+    return 0;
+  
+  args = TYPE_ARG_TYPES (type);
+  if (TREE_CODE (type) == METHOD_TYPE)
+    args = TREE_CHAIN (args);
+  for (; args != end_params_node; args = TREE_CHAIN (args))
+    if (INCOMPLETE_TYPE_P (TREE_VALUE (args)))
+      return 0;
+
+  return 1;
+}
+
 /* Check all the methods of CLASS_DECL. Methods are first completed
    then checked according to regular method existance rules.  If no
    constructor for CLASS_DECL were encountered, then build its
@@ -7227,6 +7272,10 @@ java_complete_expand_methods (class_decl
       ctxp->explicit_constructor_p = 0;
     }
   
+  /* We might have generated a class$ that we now want to expand */
+  if (TYPE_DOT_CLASS (current_class))
+    java_complete_expand_method (TYPE_DOT_CLASS (current_class));
+
   /* Now verify constructor circularity (stop after the first one we
      prove wrong.) */
   if (!CLASS_INTERFACE (class_decl))
@@ -7893,6 +7942,129 @@ build_thisn_assign ()
 }
 
 
+/* Building the synthetic `class$' used to implement the `.class' 1.1
+   extension for non primitive types. This method looks like:
+
+    static Class class$(String type) throws NoClassDefFoundError
+    {
+      try {return (java.lang.Class.forName (String));}
+      catch (ClassNotFoundException e) {
+        throw new NoClassDefFoundError(e.getMessage());}
+    } */
+
+static tree
+build_dot_class_method (class)
+     tree class;
+{
+#define BWF(S) build_wfl_node (get_identifier ((S)))
+#define MQN(X,Y) make_qualified_name ((X), (Y), 0)
+  tree args, tmp, saved_current_function_decl, mdecl;
+  tree stmt, throw_stmt, catch, catch_block, try_block;
+  tree catch_clause_param;
+  tree class_not_found_exception, no_class_def_found_error;
+
+  static tree get_message_wfl, type_parm_wfl;
+
+  if (!get_message_wfl)
+    {
+      get_message_wfl = build_wfl_node (get_identifier ("getMessage"));
+      type_parm_wfl = build_wfl_node (get_identifier ("type$"));
+    }
+
+  /* Build the arguments */
+  args = build_tree_list (get_identifier ("type$"),
+			  build_pointer_type (string_type_node));
+  TREE_CHAIN (args) = end_params_node;
+
+  /* Build the qualified name java.lang.Class.forName */
+  tmp = MQN (MQN (MQN (BWF ("java"), 
+		       BWF ("lang")), BWF ("Class")), BWF ("forName"));
+
+  /* For things we have to catch and throw */
+  class_not_found_exception = 
+    lookup_class (get_identifier ("java.lang.ClassNotFoundException"));
+  no_class_def_found_error = 
+    lookup_class (get_identifier ("java.lang.NoClassDefFoundError"));
+  load_class (class_not_found_exception, 1);
+  load_class (no_class_def_found_error, 1);
+
+  /* Create the "class$" function */
+  mdecl = create_artificial_method (class, ACC_STATIC, 
+				    build_pointer_type (class_type_node),
+				    get_identifier ("class$"), args);
+  DECL_FUNCTION_THROWS (mdecl) = build_tree_list (NULL_TREE,
+						  no_class_def_found_error);
+  
+  /* We start by building the try block. We need to build:
+       return (java.lang.Class.forName (type)); */
+  stmt = build_method_invocation (tmp, 
+				  build_tree_list (NULL_TREE, type_parm_wfl));
+  stmt = build_return (0, stmt);
+  /* Put it in a block. That's the try block */
+  try_block = build_expr_block (stmt, NULL_TREE);
+
+  /* Now onto the catch block. We start by building the expression
+     throwing a new exception: 
+       throw new NoClassDefFoundError (_.getMessage); */
+  throw_stmt = make_qualified_name (build_wfl_node (wpv_id), 
+				    get_message_wfl, 0);
+  throw_stmt = build_method_invocation (throw_stmt, NULL_TREE);
+  
+  /* Build new NoClassDefFoundError (_.getMessage) */
+  throw_stmt = build_new_invocation 
+    (build_wfl_node (get_identifier ("NoClassDefFoundError")),
+     build_tree_list (build_pointer_type (string_type_node), throw_stmt));
+
+  /* Build the throw, (it's too early to use BUILD_THROW) */
+  throw_stmt = build1 (THROW_EXPR, NULL_TREE, throw_stmt);
+
+  /* Build the catch block to encapsulate all this. We begin by
+     building an decl for the catch clause parameter and link it to
+     newly created block, the catch block. */
+  catch_clause_param = 
+    build_decl (VAR_DECL, wpv_id, 
+		build_pointer_type (class_not_found_exception));
+  catch_block = build_expr_block (NULL_TREE, catch_clause_param);
+  
+  /* We initialize the variable with the exception handler. */
+  catch = build (MODIFY_EXPR, NULL_TREE, catch_clause_param,
+		 soft_exceptioninfo_call_node);
+  add_stmt_to_block (catch_block, NULL_TREE, catch);
+
+  /* We add the statement throwing the new exception */
+  add_stmt_to_block (catch_block, NULL_TREE, throw_stmt);
+
+  /* Build a catch expression for all this */
+  catch_block = build1 (CATCH_EXPR, NULL_TREE, catch_block);
+
+  /* Build the try/catch sequence */
+  stmt = build_try_statement (0, try_block, catch_block);
+
+  fix_method_argument_names (args, mdecl);
+  layout_class_method (class, NULL_TREE, mdecl, NULL_TREE);
+  saved_current_function_decl = current_function_decl;
+  start_artificial_method_body (mdecl);
+  java_method_add_stmt (mdecl, stmt);
+  end_artificial_method_body (mdecl);
+  current_function_decl = saved_current_function_decl;
+  TYPE_DOT_CLASS (class) = mdecl;
+
+  return mdecl;
+}
+
+static tree
+build_dot_class_method_invocation (name)
+     tree name;
+{
+  tree s = make_node (STRING_CST);
+  TREE_STRING_LENGTH (s) = IDENTIFIER_LENGTH (name);
+  TREE_STRING_POINTER (s) = obstack_alloc (expression_obstack,
+					   TREE_STRING_LENGTH (s)+1);
+  strcpy (TREE_STRING_POINTER (s), IDENTIFIER_POINTER (name));
+  return build_method_invocation (build_wfl_node (get_identifier ("class$")),
+				  build_tree_list (NULL_TREE, s));
+}
+
 /* This section of the code deals with constructor.  */
 
 /* Craft a body for default constructor. Patch existing constructor
@@ -8503,13 +8675,13 @@ resolve_qualified_expression_name (wfl, 
 	  /* If we're creating an inner class instance, check for that
 	     an enclosing instance is in scope */
 	  if (TREE_CODE (qual_wfl) == NEW_CLASS_EXPR
-	      && INNER_CLASS_TYPE_P (type) && current_this
-	      && (DECL_CONTEXT (TYPE_NAME (type)) 
-		  != TYPE_NAME (TREE_TYPE (TREE_TYPE (current_this)))))
+	      && INNER_ENCLOSING_SCOPE_CHECK (type))
 	    {
 	      parse_error_context 
-		(qual_wfl, "No enclosing instance for inner class `%s' is in scope; an explicit one must be provided when creating this inner class", 
-		 lang_printable_name (type, 0));
+		(qual_wfl, "No enclosing instance for inner class `%s' is in scope%s",
+		 lang_printable_name (type, 0),
+		 (!current_this ? "" :
+		  "; an explicit one must be provided when creating this inner class"));
 	      RESTORE_THIS_AND_CURRENT_CLASS;
 	      return 1;
 	    }
@@ -8590,6 +8762,13 @@ resolve_qualified_expression_name (wfl, 
 	  *type_found = type = TREE_TYPE (decl);
 	  break;
 
+	case CLASS_LITERAL:
+	  if ((decl = java_complete_tree (qual_wfl)) == error_mark_node)
+	    return 1;
+	  *where_found = QUAL_RESOLUTION (q) = decl;
+	  *type_found = type = TREE_TYPE (decl);
+	  break;
+
 	default:
 	  /* Fix for -Wall Just go to the next statement. Don't
              continue */
@@ -9206,6 +9385,19 @@ patch_method_invocation (patch, primary,
 					     class_to_search, primary))
 	PATCH_METHOD_RETURN_ERROR ();
 
+      /* Check for inner classes creation from illegal contexts */
+      if (lc && (INNER_CLASS_TYPE_P (class_to_search)
+		 && !CLASS_STATIC (TYPE_NAME (class_to_search)))
+	  && INNER_ENCLOSING_SCOPE_CHECK (class_to_search))
+	{
+	  parse_error_context 
+	    (wfl, "No enclosing instance for inner class `%s' is in scope%s",
+	     lang_printable_name (class_to_search, 0),
+	     (!current_this ? "" :
+	      "; an explicit one must be provided when creating this inner class"));
+	  PATCH_METHOD_RETURN_ERROR ();
+	}
+
       /* Non static methods are called with the current object extra
 	 argument. If patch a `new TYPE()', the argument is the value
 	 returned by the object allocator. If method is resolved as a
@@ -9281,7 +9473,10 @@ patch_method_invocation (patch, primary,
 	args = nreverse (args);
       
       /* Secretely pass the current_this/primary as a second argument */
-      args = tree_cons (NULL_TREE, (primary ? primary : current_this), args);
+      if (primary || current_this)
+	args = tree_cons (NULL_TREE, (primary ? primary : current_this), args);
+      else
+	args = tree_cons (NULL_TREE, integer_zero_node, args);
     }
 
   is_static_flag = METHOD_STATIC (list);
@@ -9367,7 +9562,9 @@ maybe_use_access_method (is_super_init, 
   int non_static_context = !METHOD_STATIC (md);
 
   if (is_super_init 
-      || !INNER_CLASS_TYPE_P (current_class) || DECL_FINIT_P (md))
+      || DECL_CONTEXT (md) == current_class
+      || !PURE_INNER_CLASS_TYPE_P (current_class) 
+      || DECL_FINIT_P (md))
     return 0;
   
   /* If we're calling a method found in an enclosing class, generate
@@ -9629,6 +9826,7 @@ find_applicable_accessible_methods_list 
      int lc;
      tree class, name, arglist;
 {
+  static int object_done = 0;
   tree list = NULL_TREE, all_list = NULL_TREE;
 
   if (!CLASS_LOADED_P (class) && !CLASS_FROM_SOURCE_P (class))
@@ -9638,15 +9836,15 @@ find_applicable_accessible_methods_list 
     }
 
   /* Search interfaces */
-  if (CLASS_INTERFACE (TYPE_NAME (class))
-      || CLASS_ABSTRACT (TYPE_NAME (class)))
+  if (CLASS_INTERFACE (TYPE_NAME (class)))
     {
       static tree searched_interfaces = NULL_TREE;
       static int search_not_done = 0;
       int i, n;
       tree basetype_vec = TYPE_BINFO_BASETYPES (class);
 
-      /* Have we searched this interface already? */
+      /* Have we searched this interface already? We shoud use a hash
+         table, FIXME */
       if (searched_interfaces)
 	{  
 	  tree current;  
@@ -9657,23 +9855,18 @@ find_applicable_accessible_methods_list 
 	}
       searched_interfaces = tree_cons (NULL_TREE, class, searched_interfaces);
 
-      search_applicable_methods_list 
-	(lc, TYPE_METHODS (class), name, arglist, &list, &all_list);
-
+      search_applicable_methods_list (lc, TYPE_METHODS (class), 
+				      name, arglist, &list, &all_list);
       n = TREE_VEC_LENGTH (basetype_vec);
-      for (i = 0; i < n; i++)
+      for (i = 1; i < n; i++)
 	{
 	  tree t = BINFO_TYPE (TREE_VEC_ELT (basetype_vec, i));
 	  tree rlist;
 
-	  /* Skip java.lang.Object (we'll search it once later.) */
-	  if (t == object_type_node)
-	    continue;
-	  
 	  search_not_done++;
 	  rlist = find_applicable_accessible_methods_list (lc,  t, name, 
 							   arglist);
-	  all_list = chainon (rlist, (list ? list : all_list)); 
+	  list = chainon (rlist, list);
 	  search_not_done--;
 	}
 
@@ -9681,32 +9874,61 @@ find_applicable_accessible_methods_list 
          java.lang.Object */
       if (!search_not_done)
 	{  
+	  if (!object_done)
+	    search_applicable_methods_list (lc, 
+					    TYPE_METHODS (object_type_node),
+					    name, arglist, &list, &all_list);
 	  searched_interfaces = NULL_TREE;  
-	  search_applicable_methods_list (lc, TYPE_METHODS (object_type_node),
-					  name, arglist, &list, &all_list);
 	}
     }
   /* Search classes */
   else
     {
-      tree saved_class = class;
+      tree sc = class;
+      int seen_inner_class = 0;
       search_applicable_methods_list (lc, TYPE_METHODS (class), 
 				      name, arglist, &list, &all_list);
 
+      /* We must search all interfaces of this class */
+      if (!lc)
+      {
+	tree basetype_vec = TYPE_BINFO_BASETYPES (sc);
+	int n = TREE_VEC_LENGTH (basetype_vec), i;
+	object_done = 1;
+	for (i = 1; i < n; i++)
+	  {
+	    tree t = BINFO_TYPE (TREE_VEC_ELT (basetype_vec, i));
+	    tree rlist;
+	    if (t != object_type_node)
+	      rlist = find_applicable_accessible_methods_list (lc, t,
+							       name, arglist);
+	    list = chainon (rlist, list);
+	  }
+	object_done = 0;
+      }
+
       /* 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)));
-	  search_applicable_methods_list (lc, TYPE_METHODS (class),
-					  name, arglist, &list, &all_list);
+	  rlist = find_applicable_accessible_methods_list (lc, class, 
+							   name, arglist);
+	  list = chainon (rlist, list);
 	}
-      
-      for (class = saved_class, class = (lc ? NULL_TREE : 
-					 CLASSTYPE_SUPER (class)); class;
-	   class = CLASSTYPE_SUPER (class))
-	search_applicable_methods_list 
-	  (lc, TYPE_METHODS (class), name, arglist, &list, &all_list);
+
+      if (!lc && seen_inner_class 
+	  && TREE_TYPE (DECL_CONTEXT (TYPE_NAME (sc))) == CLASSTYPE_SUPER (sc))
+	class = CLASSTYPE_SUPER (sc);
+      else
+	class = sc;
+
+      for (class = (lc ? NULL_TREE : CLASSTYPE_SUPER (class)); 
+        class; class = CLASSTYPE_SUPER (class))
+       search_applicable_methods_list (lc, TYPE_METHODS (class), 
+                                       name, arglist, &list, &all_list);
     }
 
   /* Either return the list obtained or all selected (but
@@ -9782,16 +10004,31 @@ find_most_specific_methods_list (list)
     if (DECL_SPECIFIC_COUNT (TREE_VALUE (current)) == max)
       new_list = tree_cons (NULL_TREE, TREE_VALUE (current), new_list);
 
+  /* If we have several and they're all abstract, just pick the
+     closest one. */
+
+  if (new_list && TREE_CHAIN (new_list))
+    {
+      tree c;
+      for (c = new_list; c && METHOD_ABSTRACT (TREE_VALUE (c)); 
+	   c = TREE_CHAIN (c))
+        ;
+      if (!c)
+	{
+	  new_list = nreverse (new_list);
+	  TREE_CHAIN (new_list) = NULL_TREE;
+	}
+    }
+
   /* If we can't find one, lower expectations and try to gather multiple
      maximally specific methods */
-  while (!new_list)
+  while (!new_list && max)
     {
       while (--max > 0)
 	{
 	  if (DECL_SPECIFIC_COUNT (TREE_VALUE (current)) == max)
 	    new_list = tree_cons (NULL_TREE, TREE_VALUE (current), new_list);
 	}
-      return new_list;
     }
 
   return new_list;
@@ -9898,6 +10135,10 @@ qualify_ambiguous_name (id)
 	qual = TREE_CHAIN (qual);
 	qual_wfl = QUAL_WFL (qual);
 	break;
+      case CLASS_LITERAL:
+	qual = TREE_CHAIN (qual);
+	qual_wfl = QUAL_WFL (qual);
+      break;
       default:
 	/* Fix for -Wall. Just break doing nothing */
 	break;
@@ -11067,7 +11308,6 @@ build_this_super_qualified_invocation (u
      int use_this;
      tree name, args;
      int lloc, rloc;
-
 {
   tree invok;
   tree wfl = 
@@ -12477,8 +12717,18 @@ patch_incomplete_class_ref (node)
 
   if (!(ref_type = resolve_type_during_patch (type)))
     return error_mark_node;
+
+  if (!flag_emit_class_files || JPRIMITIVE_TYPE_P (ref_type))
+    return build_class_ref (ref_type);
 
-  return build_class_ref (ref_type);
+  /* If we're emitting class files and we have to deal with non
+     primitive types, we invoke (and consider generating) the
+     synthetic static method `class$'. */
+  if (!TYPE_DOT_CLASS (current_class))
+      build_dot_class_method (current_class);
+  ref_type = 
+    build_dot_class_method_invocation (DECL_NAME (TYPE_NAME (ref_type)));
+  return java_complete_tree (ref_type);
 }
 
 /* 15.14 Unary operators. We return error_mark_node in case of error,
@@ -13722,7 +13972,7 @@ patch_switch_statement (node)
   return node;
 }
 
-/* 14.18 The try statement */
+/* 14.18 The try/catch statements */
 
 static tree
 build_try_statement (location, try_block, catches)


More information about the Gcc-patches mailing list