This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

[PATCH] Java: fix to java/4007 and other misc. fixes.



This patch fixes different things:

  http://gcc.gnu.org/ml/java/2001-08/msg00027.html
  http://gcc.gnu.org/ml/java-prs/2001-q3/msg00067.html
  http://gcc.gnu.org/ml/gcc/2001-08/msg00528.html

It's been fairly thoroughly tested, I'm checking this in.

./A

2001-08-16  Alexandre Petit-Bianco  <apbianco@redhat.com>

	* jcf-parse.c (load_class): New locals saved and class_loaded. If
	loading a class_or_name fails, try considering an innerclass name
	and load the enclosing context.
	* parse.y (resolve_inner_class): New function.
	(find_as_inner_class): Added leading comment.
	(register_incomplete_type): Keep the current context as enclosing
	context for JDEP_FIELD dependencies.
	(do_resolve_class): Locals new_class_decl and super initialized to
	NULL. Call resolve_inner_class, explore the enclosing context
	superclass if necessary.
	Fixes PR java/4007

2001-08-12  Alexandre Petit-Bianco  <apbianco@redhat.com>

	* decl.c (init_decl_processing): exception_type_node,
	class_not_found_type_node, and no_class_def_found_type_node
	initialized. predef_filenames augmented accordingly.
	instinit_identifier_node initialized.
	* java-tree.def (INSTANCE_INITIALIZERS_EXPR): Entry removed.
	* java-tree.h (enum java_tree_index): New entries
	JTI_EXCEPTION_TYPE_NODE, JTI_CLASS_NOT_FOUND_TYPE_NODE,
	JTI_NO_CLASS_DEF_FOUND_TYPE_NODE, JTI_INSTINIT_IDENTIFIER_NODE.
	(exception_type_node): New macro.
	(class_not_found_type_node): Likewise.
	(no_class_def_found_type_node): Likewise.
	(instinit_identifier_node): Likewise.
	(PREDEF_FILENAMES_SIZE): Adjusted.
	(TYPE_HAS_FINAL_VARIABLE): Fixed typo.
	(struct lang_type): Fixed typo in bitfield name.
	(DECL_INSTINIT_P): New macro.
	(ID_INSTINIT_P): Likewise.
	* jcf-write.h (generate_classfile): instinit$ bears the Synthetic
	attribute.
	* parse.y (encapsulate_with_try_catch): New function.
	(generate_instinit): Likewise.
	(build_instinit_invocation): Likewise.
	(ctors_unchecked_throws_clause_p): Likewise.
	(add_instance_initializer): Deleted.
	(build_instance_initializer): Likewise.
	(in_instance_initializer): Likewise.
	(check_method_redefinition): instinit$ not to be verified.
	(java_complete_expand_methods): Generate instinit$, simplified code.
	(build_dot_class_method): Eliminated unnecessary locals. Use
	encapsulate_with_try_catch, removed unnecessary code.
	(fix_constructors): New local iii. Use build_instinit_invocation.
	(patch_method_invocation): Added comment.
	(maybe_use_access_method): Don't consider instinit$.
	(find_applicable_accessible_methods_list): Shorten the search for
	instinit$ too.
	(java_complete_lhs): case INSTANCE_INITIALIZERS_EXPR removed.
	(patch_return): Use DECL_INSTINIT_P instead of in_instance_initializer.
	(patch_throw_statement): Likewise. Fixed typo.

2001-08-09  Alexandre Petit-Bianco  <apbianco@redhat.com>

	* expr.c (java_lang_expand_expr): Call `expand_end_bindings' and
	`poplevel' in the right order.

Index: decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/decl.c,v
retrieving revision 1.106
diff -u -p -r1.106 decl.c
--- decl.c	2001/08/13 15:52:38	1.106
+++ decl.c	2001/08/17 20:35:56
@@ -541,10 +541,16 @@ init_decl_processing ()
   string_ptr_type_node = promote_type (string_type_node);
   class_type_node = lookup_class (get_identifier ("java.lang.Class"));
   throwable_type_node = lookup_class (get_identifier ("java.lang.Throwable"));
+  exception_type_node = lookup_class (get_identifier ("java.lang.Exception"));
   runtime_exception_type_node = 
     lookup_class (get_identifier ("java.lang.RuntimeException"));
   error_exception_type_node = 
     lookup_class (get_identifier ("java.lang.Error"));
+  class_not_found_type_node = 
+    lookup_class (get_identifier ("java.lang.ClassNotFoundException"));
+  no_class_def_found_type_node = 
+    lookup_class (get_identifier ("java.lang.NoClassDefFoundError"));
+
   rawdata_ptr_type_node
     = promote_type (lookup_class (get_identifier ("gnu.gcj.RawData")));
 
@@ -557,6 +563,9 @@ init_decl_processing ()
   predef_filenames [4] = get_identifier ("java/lang/String.java");
   predef_filenames [5] = get_identifier ("java/lang/Throwable.java");
   predef_filenames [6] = get_identifier ("gnu/gcj/RawData.java");
+  predef_filenames [7] = get_identifier ("java/lang/Exception");
+  predef_filenames [8] = get_identifier ("java/lang/ClassNotFoundException");
+  predef_filenames [9] = get_identifier ("java/lang/NoClassDefFoundError");
 
   methodtable_type = make_node (RECORD_TYPE);
   layout_type (methodtable_type);
@@ -572,6 +581,7 @@ init_decl_processing ()
   /* The new `finit$' special method identifier. This one is now
      generated in place of `$finit$'.  */
   finit_identifier_node = get_identifier ("finit$");
+  instinit_identifier_node = get_identifier ("instinit$");
   void_signature_node = get_identifier ("()V");
   length_identifier_node = get_identifier ("length");
   this_identifier_node = get_identifier ("this");
Index: expr.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/expr.c,v
retrieving revision 1.114
diff -u -p -r1.114 expr.c
--- expr.c	2001/08/09 04:19:12	1.114
+++ expr.c	2001/08/17 20:35:58
@@ -2505,8 +2505,8 @@ java_lang_expand_expr (exp, target, tmod
 	    }
 	  expand_expr (body, const0_rtx, VOIDmode, 0);
 	  emit_queue ();
-	  poplevel (1, 1, 0);
 	  expand_end_bindings (getdecls (), 1, 0);
+	  poplevel (1, 1, 0);
 	  return const0_rtx;
 	}
       return const0_rtx;
Index: java-tree.def
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/java-tree.def,v
retrieving revision 1.16
diff -u -p -r1.16 java-tree.def
--- java-tree.def	2001/05/13 04:59:32	1.16
+++ java-tree.def	2001/08/17 20:35:58
@@ -88,12 +88,6 @@ DEFTREECODE (NEW_ARRAY_INIT, "new_array_
    reference from.  */
 DEFTREECODE (CLASS_LITERAL, "class_literal", '1', 1)
 
-/* Instance initializer.
-   Operand 0 contains the intance initializer statement. This tree node
-   is used for context detection, so that special rules can be
-   enforced. */
-DEFTREECODE (INSTANCE_INITIALIZERS_EXPR, "instance_initializers_expr", '1', 1)
-
 /* The Java object within the exception object from the runtime.  */
 DEFTREECODE (JAVA_EXC_OBJ_EXPR, "java_exc_obj_expr", 'e', 0)
 
Index: java-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/java-tree.h,v
retrieving revision 1.118
diff -u -p -r1.118 java-tree.h
--- java-tree.h	2001/08/09 04:19:12	1.118
+++ java-tree.h	2001/08/17 20:35:59
@@ -251,9 +251,12 @@ enum java_tree_index
   JTI_STRING_TYPE_NODE,
   JTI_STRING_PTR_TYPE_NODE,
   JTI_THROWABLE_TYPE_NODE,
+  JTI_EXCEPTION_TYPE_NODE,
   JTI_RUNTIME_EXCEPTION_TYPE_NODE,
   JTI_ERROR_EXCEPTION_TYPE_NODE,
   JTI_RAWDATA_PTR_TYPE_NODE,
+  JTI_CLASS_NOT_FOUND_TYPE_NODE,
+  JTI_NO_CLASS_DEF_FOUND_TYPE_NODE,
 
   JTI_BYTE_ARRAY_TYPE_NODE,
   JTI_SHORT_ARRAY_TYPE_NODE,
@@ -278,6 +281,7 @@ enum java_tree_index
   JTI_INIT_IDENTIFIER_NODE,      
   JTI_CLINIT_IDENTIFIER_NODE,      
   JTI_FINIT_IDENTIFIER_NODE,      
+  JTI_INSTINIT_IDENTIFIER_NODE,
   JTI_FINIT_LEG_IDENTIFIER_NODE,  
   JTI_VOID_SIGNATURE_NODE,       
   JTI_LENGTH_IDENTIFIER_NODE,  
@@ -408,12 +412,18 @@ extern tree java_global_trees[JTI_MAX];
   java_global_trees[JTI_STRING_PTR_TYPE_NODE]
 #define throwable_type_node \
   java_global_trees[JTI_THROWABLE_TYPE_NODE]
+#define exception_type_node \
+  java_global_trees[JTI_EXCEPTION_TYPE_NODE]
 #define runtime_exception_type_node \
   java_global_trees[JTI_RUNTIME_EXCEPTION_TYPE_NODE]
 #define error_exception_type_node \
   java_global_trees[JTI_ERROR_EXCEPTION_TYPE_NODE]
 #define rawdata_ptr_type_node \
   java_global_trees[JTI_RAWDATA_PTR_TYPE_NODE]
+#define class_not_found_type_node \
+  java_global_trees[JTI_CLASS_NOT_FOUND_TYPE_NODE]
+#define no_class_def_found_type_node \
+  java_global_trees[JTI_NO_CLASS_DEF_FOUND_TYPE_NODE]
 
 #define byte_array_type_node \
   java_global_trees[JTI_BYTE_ARRAY_TYPE_NODE]
@@ -463,6 +473,8 @@ extern tree java_global_trees[JTI_MAX];
   java_global_trees[JTI_FINIT_IDENTIFIER_NODE]      /* "finit$" */
 #define finit_leg_identifier_node \
   java_global_trees[JTI_FINIT_LEG_IDENTIFIER_NODE]  /* "$finit$" */
+#define instinit_identifier_node \
+  java_global_trees[JTI_INSTINIT_IDENTIFIER_NODE]  /* "instinit$" */
 #define void_signature_node \
   java_global_trees[JTI_VOID_SIGNATURE_NODE]       /* "()V" */
 #define length_identifier_node \
@@ -598,7 +610,7 @@ extern tree java_global_trees[JTI_MAX];
 #define nativecode_ptr_array_type_node \
   java_global_trees[JTI_NATIVECODE_PTR_ARRAY_TYPE_NODE]
 
-#define PREDEF_FILENAMES_SIZE 7
+#define PREDEF_FILENAMES_SIZE 10
 extern tree predef_filenames[PREDEF_FILENAMES_SIZE];
 
 #define nativecode_ptr_type_node ptr_type_node
@@ -937,7 +949,7 @@ struct lang_decl_var
 #define TYPE_PACKAGE_LIST(T)     (TYPE_LANG_SPECIFIC(T)->package_list)
 #define TYPE_PRIVATE_INNER_CLASS(T) (TYPE_LANG_SPECIFIC(T)->pic)
 #define TYPE_PROTECTED_INNER_CLASS(T) (TYPE_LANG_SPECIFIC(T)->poic)
-#define TYPE_HAS_FINAL_VARIABLE(T) (TYPE_LANG_SPECIFIC(T)->afv)
+#define TYPE_HAS_FINAL_VARIABLE(T) (TYPE_LANG_SPECIFIC(T)->hfv)
 
 struct lang_type
 {
@@ -955,7 +967,7 @@ struct lang_type
   tree package_list;		/* List of package names, progressive */
   unsigned pic:1;		/* Private Inner Class. */
   unsigned poic:1;		/* Protected Inner Class. */
-  unsigned afv:1;		/* Has final variables */
+  unsigned hfv:1;		/* Has final variables */
 };
 
 #ifdef JAVA_USE_HANDLES
@@ -1197,6 +1209,7 @@ struct rtx_def * java_lang_expand_expr P
 #define DECL_INIT_P(DECL)   (ID_INIT_P (DECL_NAME (DECL)))
 #define DECL_FINIT_P(DECL)  (ID_FINIT_P (DECL_NAME (DECL)))
 #define DECL_CLINIT_P(DECL) (ID_CLINIT_P (DECL_NAME (DECL)))
+#define DECL_INSTINIT_P(DECL) (ID_INSTINIT_P (DECL_NAME (DECL)))
 
 /* Predicates on method identifiers. Kept close to other macros using
    them  */
@@ -1209,6 +1222,7 @@ struct rtx_def * java_lang_expand_expr P
 			 || (ID) == finit_leg_identifier_node)
 #define ID_CLINIT_P(ID) ((ID) == clinit_identifier_node)
 #define ID_CLASSDOLLAR_P(ID) ((ID) == classdollar_identifier_node)
+#define ID_INSTINIT_P(ID) ((ID) == instinit_identifier_node)
 
 /* Access flags etc for a variable/field (a FIELD_DECL): */
 
Index: jcf-parse.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/jcf-parse.c,v
retrieving revision 1.89
diff -u -p -r1.89 jcf-parse.c
--- jcf-parse.c	2001/07/11 20:51:46	1.89
+++ jcf-parse.c	2001/08/17 20:36:00
@@ -650,7 +650,8 @@ load_class (class_or_name, verbose)
      tree class_or_name;
      int verbose;
 {
-  tree name;
+  tree name, saved;
+  int class_loaded;
 
   /* class_or_name can be the name of the class we want to load */
   if (TREE_CODE (class_or_name) == IDENTIFIER_NODE)
@@ -663,8 +664,31 @@ load_class (class_or_name, verbose)
   else
     name = DECL_NAME (TYPE_NAME (class_or_name));
 
-  if (read_class (name) == 0 && verbose)
-    error ("Cannot find file for class %s.", IDENTIFIER_POINTER (name));
+  saved = name;
+  while (1)
+    {
+      char *dollar;
+
+      if ((class_loaded = read_class (name)))
+	break;
+
+      /* We failed loading name. Now consider that we might be looking
+	 for a inner class but it's only available in source for in
+	 its enclosing context. */
+      if ((dollar = strrchr (IDENTIFIER_POINTER (name), '$')))
+	{
+	  int c = *dollar;
+	  *dollar = '\0';
+	  name = get_identifier (IDENTIFIER_POINTER (name));
+	  *dollar = c;
+	}
+      /* Otherwise, we failed, we bail. */
+      else
+	break;
+    }
+
+  if (!class_loaded && verbose)
+    error ("Cannot find file for class %s.", IDENTIFIER_POINTER (saved));
 }
 
 /* Parse the .class file JCF. */
Index: jcf-write.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/jcf-write.c,v
retrieving revision 1.82
diff -u -p -r1.82 jcf-write.c
--- jcf-write.c	2001/08/01 02:28:42	1.82
+++ jcf-write.c	2001/08/17 20:36:01
@@ -2935,7 +2935,8 @@ generate_classfile (clas, state)
       i = (body != NULL_TREE) + (DECL_FUNCTION_THROWS (part) != NULL_TREE);
 
       /* Make room for the Synthetic attribute (of zero length.)  */
-      if (DECL_FINIT_P (part) 
+      if (DECL_FINIT_P (part)
+	  || DECL_INSTINIT_P (part)
 	  || OUTER_FIELD_ACCESS_IDENTIFIER_P (DECL_NAME (part))
 	  || TYPE_DOT_CLASS (clas) == part)
 	{
Index: parse.y
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/parse.y,v
retrieving revision 1.299
diff -u -p -r1.299 parse.y
--- parse.y	2001/08/09 04:19:12	1.299
+++ parse.y	2001/08/17 20:36:11
@@ -221,6 +221,7 @@ static tree string_constant_concatenatio
 static tree build_string_concatenation PARAMS ((tree, tree));
 static tree patch_string_cst PARAMS ((tree));
 static tree patch_string PARAMS ((tree));
+static tree encapsulate_with_try_catch PARAMS ((int, tree, tree, tree));
 static tree build_try_statement PARAMS ((int, tree, tree));
 static tree build_try_finally_statement PARAMS ((int, tree, tree));
 static tree patch_try_statement PARAMS ((tree));
@@ -229,6 +230,7 @@ static tree patch_throw_statement PARAMS
 static void check_thrown_exceptions PARAMS ((int, tree));
 static int check_thrown_exceptions_do PARAMS ((tree));
 static void purge_unchecked_exceptions PARAMS ((tree));
+static bool ctors_unchecked_throws_clause_p PARAMS ((tree));
 static void check_throws_clauses PARAMS ((tree, tree, tree));
 static void finish_method_declaration PARAMS ((tree));
 static tree build_super_invocation PARAMS ((tree));
@@ -239,8 +241,8 @@ static tree build_this_super_qualified_i
 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 tree generate_instinit PARAMS ((tree));
+static tree build_instinit_invocation PARAMS ((tree));
 static void fix_constructors PARAMS ((tree));
 static tree build_alias_initializer_parameter_list PARAMS ((int, tree,
 							    tree, int *));
@@ -300,6 +302,8 @@ static tree maybe_make_nested_class_name
 static void make_nested_class_name PARAMS ((tree));
 static void set_nested_class_simple_name_value PARAMS ((tree, int));
 static void link_nested_class_to_enclosing PARAMS ((void));
+static tree resolve_inner_class PARAMS ((struct hash_table *, tree, tree *,
+					 tree *, tree));
 static tree find_as_inner_class PARAMS ((tree, tree, tree));
 static tree find_as_inner_class_do PARAMS ((tree, tree));
 static int check_inner_class_redefinition PARAMS ((tree, tree));
@@ -349,9 +353,6 @@ int do_not_fold;
 /* Cyclic inheritance report, as it can be set by layout_class */
 const char *cyclic_inheritance_report;
  
-/* Tell when we're within an instance initializer */
-static int in_instance_initializer;
-
 /* The current parser context */
 struct parser_ctxt *ctxp;
 
@@ -3528,6 +3529,74 @@ check_inner_class_redefinition (raw_name
   return 0;
 }
 
+/* Tries to find a decl for CLASS_TYPE within ENCLOSING. If we fail,
+   we remember ENCLOSING and SUPER.  */
+
+static tree
+resolve_inner_class (circularity_hash, cl, enclosing, super, class_type)
+     struct hash_table *circularity_hash;
+     tree cl, *enclosing, *super, class_type;
+{
+  tree local_enclosing = *enclosing;
+  tree local_super = NULL_TREE;
+
+  while (local_enclosing)
+    {
+      tree intermediate, decl;
+
+      hash_lookup (circularity_hash, 
+		   (const  hash_table_key) local_enclosing, TRUE, NULL);
+
+      if ((decl = find_as_inner_class (local_enclosing, class_type, cl)))
+	return decl;
+
+      intermediate = local_enclosing;
+      /* Explore enclosing contexts. */
+      while (INNER_CLASS_DECL_P (intermediate))
+	{
+	  intermediate = DECL_CONTEXT (intermediate);
+	  if ((decl = find_as_inner_class (intermediate, class_type, cl)))
+	    return decl;
+	}
+
+      /* Now go to the upper classes, bail out if necessary. We will
+	 analyze the returned SUPER and act accordingly (see
+	 do_resolve_class.) */
+      local_super = CLASSTYPE_SUPER (TREE_TYPE (local_enclosing));
+      if (!local_super || local_super == object_type_node)
+        break;
+
+      if (TREE_CODE (local_super) == POINTER_TYPE)
+        local_super = do_resolve_class (NULL, local_super, NULL, NULL);
+      else
+	local_super = TYPE_NAME (local_super);
+
+      /* We may not have checked for circular inheritance yet, so do so
+         here to prevent an infinite loop. */
+      if (hash_lookup (circularity_hash,
+		       (const hash_table_key) local_super, FALSE, NULL))
+        {
+          if (!cl)
+            cl = lookup_cl (local_enclosing);
+	  
+          parse_error_context
+            (cl, "Cyclic inheritance involving %s",
+	     IDENTIFIER_POINTER (DECL_NAME (local_enclosing)));
+	  local_enclosing = NULL_TREE;
+        }
+      local_enclosing = local_super;
+    }
+
+  /* We failed. Return LOCAL_SUPER and LOCAL_ENCLOSING. */
+  *super = local_super;
+  *enclosing = local_enclosing;
+
+  return NULL_TREE;
+}
+
+/* Within ENCLOSING, find a decl for NAME and return it. NAME can be
+   qualified. */
+
 static tree
 find_as_inner_class (enclosing, name, cl)
      tree enclosing, name, cl;
@@ -4363,29 +4432,71 @@ generate_finit (class_type)
   return mdecl;
 }
 
+/* Generate a function to run the instance initialization code. The
+   private method is called `instinit$'. Unless we're dealing with an
+   anonymous class, we determine whether all ctors of CLASS_TYPE
+   declare a checked exception in their `throws' clause in order to
+   see whether it's necessary to encapsulate the instance initializer
+   statements in a try/catch/rethrow sequence.  */
+
 static tree
-build_instance_initializer (mdecl)
-     tree mdecl;
+generate_instinit (class_type)
+     tree class_type;
 {
-  tree compound = NULL_TREE;
-  tree stmt_list = TYPE_II_STMT_LIST (DECL_CONTEXT (mdecl));
   tree current;
+  tree compound = NULL_TREE;
+  tree parms = tree_cons (this_identifier_node,
+			  build_pointer_type (class_type), end_params_node);
+  tree mdecl = create_artificial_method (class_type, ACC_PRIVATE,
+					 void_type_node,
+					 instinit_identifier_node, parms);
+
+  layout_class_method (class_type, CLASSTYPE_SUPER (class_type),
+		       mdecl, NULL_TREE);
 
-  for (current = stmt_list; current; current = TREE_CHAIN (current))
+  /* Gather all the statements in a compound */
+  for (current = TYPE_II_STMT_LIST (class_type); 
+       current; current = TREE_CHAIN (current))
     compound = add_stmt_to_compound (compound, NULL_TREE, current);
 
-  return compound;
+  /* We need to encapsulate COMPOUND by a try/catch statement to
+     rethrow exceptions that might occur in the instance initializer.
+     We do that only if all ctors of CLASS_TYPE are set to catch a
+     checked exception. This doesn't apply to anonymous classes (since
+     they don't have declared ctors.) */
+  if (!ANONYMOUS_CLASS_P (class_type) && 
+      ctors_unchecked_throws_clause_p (class_type))
+    {
+      compound = encapsulate_with_try_catch (0, exception_type_node, compound, 
+					     build1 (THROW_EXPR, NULL_TREE,
+						     build_wfl_node (wpv_id)));
+      DECL_FUNCTION_THROWS (mdecl) = build_tree_list (NULL_TREE,
+						      exception_type_node);
+    }
+
+  start_artificial_method_body (mdecl);
+  java_method_add_stmt (mdecl, compound);
+  end_artificial_method_body (mdecl);
+
+  return mdecl;
 }
 
-static void
-add_instance_initializer (mdecl)
-     tree mdecl;
+/* FIXME */
+static tree
+build_instinit_invocation (class_type)
+     tree class_type;
 {
-  tree compound = build_instance_initializer (mdecl);
+  tree to_return = NULL_TREE;
 
-  if (compound)
-    java_method_add_stmt (mdecl, build1 (INSTANCE_INITIALIZERS_EXPR,
-					 NULL_TREE, compound));
+  if (TYPE_II_STMT_LIST (class_type))
+    {
+      tree parm = build_tree_list (NULL_TREE,
+				   build_wfl_node (this_identifier_node));
+      to_return =
+	build_method_invocation (build_wfl_node (instinit_identifier_node),
+				 parm);
+    }
+  return to_return;
 }
 
 /* Shared accros method_declarator and method_header to remember the
@@ -5095,7 +5206,7 @@ register_incomplete_type (kind, wfl, dec
   /* For some dependencies, set the enclosing class of the current
      class to be the enclosing context */
   if ((kind == JDEP_SUPER || kind == JDEP_INTERFACE 
-       || kind == JDEP_ANONYMOUS || kind == JDEP_FIELD)
+       || kind == JDEP_ANONYMOUS)
       && GET_ENCLOSING_CPC ())
     JDEP_ENCLOSING (new) = TREE_VALUE (GET_ENCLOSING_CPC ());
   else
@@ -5574,7 +5685,7 @@ tree
 do_resolve_class (enclosing, class_type, decl, cl)
      tree enclosing, class_type, decl, cl;
 {
-  tree new_class_decl, super;
+  tree new_class_decl = NULL_TREE, super = NULL_TREE;
   struct hash_table _ht, *circularity_hash = &_ht;
 
   /* This hash table is used to register the classes we're going
@@ -5590,58 +5701,25 @@ do_resolve_class (enclosing, class_type,
      being loaded from class file. FIXME. */
   while (enclosing)
     {
-      tree intermediate;
-
-      hash_lookup (circularity_hash, 
-		   (const  hash_table_key) enclosing, TRUE, NULL);
-
-      if ((new_class_decl = find_as_inner_class (enclosing, class_type, cl)))
-	{
-	  hash_table_free (circularity_hash);
-	  return new_class_decl;
-	}
-
-      intermediate = enclosing;
-      /* Explore enclosing contexts. */
-      while (INNER_CLASS_DECL_P (intermediate))
-	{
-	  intermediate = DECL_CONTEXT (intermediate);
-	  if ((new_class_decl = find_as_inner_class (intermediate, 
-						     class_type, cl)))
-	    {
-	      hash_table_free (circularity_hash);
-	      return new_class_decl;
-	    }
-	}
-
-      /* Now go to the upper classes, bail out if necessary. */
-      super = CLASSTYPE_SUPER (TREE_TYPE (enclosing));
-      if (!super || super == object_type_node)
-        break;
+      new_class_decl = resolve_inner_class (circularity_hash, cl, &enclosing,
+					    &super, class_type);
+      if (new_class_decl)
+	break;
 
-      if (TREE_CODE (super) == POINTER_TYPE)
-        super = do_resolve_class (NULL, super, NULL, NULL);
+      /* If we haven't found anything because SUPER reached Object and
+	 ENCLOSING happens to be an innerclass, try the enclosing context. */
+      if ((!super || super == object_type_node) && 
+	  enclosing && INNER_CLASS_DECL_P (enclosing))
+	enclosing = DECL_CONTEXT (enclosing);
       else
-	super = TYPE_NAME (super);
-
-      /* We may not have checked for circular inheritance yet, so do so
-         here to prevent an infinite loop. */
-      if (hash_lookup (circularity_hash,
-		       (const hash_table_key) super, FALSE, NULL))
-        {
-          if (!cl)
-            cl = lookup_cl (enclosing);
-	  
-          parse_error_context
-            (cl, "Cyclic inheritance involving %s",
-	     IDENTIFIER_POINTER (DECL_NAME (enclosing)));
-          break;
-        }
-      enclosing = super;
+	enclosing = NULL_TREE;
     }
 
   hash_table_free (circularity_hash);
 
+  if (new_class_decl)
+    return new_class_decl;
+
   /* 1- Check for the type in single imports. This will change
      TYPE_NAME() if something relevant is found */
   find_in_imports (class_type);
@@ -5920,8 +5998,9 @@ check_method_redefinition (class, method
 {
   tree redef, sig;
 
-  /* There's no need to verify <clinit> and finit$ */
-  if (DECL_CLINIT_P (method) || DECL_FINIT_P (method))
+  /* There's no need to verify <clinit> and finit$ and instinit$ */
+  if (DECL_CLINIT_P (method)
+      || DECL_FINIT_P (method) || DECL_INSTINIT_P (method))
     return 0;
 
   sig = TYPE_ARGUMENT_SIGNATURE (TREE_TYPE (method));
@@ -7460,7 +7539,7 @@ static void
 java_complete_expand_methods (class_decl)
      tree class_decl;
 {
-  tree clinit, finit, decl, first_decl;
+  tree clinit, decl, first_decl;
 
   current_class = TREE_TYPE (class_decl);
 
@@ -7482,14 +7561,16 @@ java_complete_expand_methods (class_decl
   first_decl = TYPE_METHODS (current_class);
   clinit = maybe_generate_pre_expand_clinit (current_class);
 
-  /* Then generate finit$ (if we need to) because constructor will
+  /* Then generate finit$ (if we need to) because constructors will
    try to use it.*/
   if (TYPE_FINIT_STMT_LIST (current_class))
-    {
-      finit = generate_finit (current_class);
-      java_complete_expand_method (finit);
-    }
+    java_complete_expand_method (generate_finit (current_class));
 
+  /* Then generate instinit$ (if we need to) because constructors will
+     try to use it. */
+  if (TYPE_II_STMT_LIST (current_class))
+    java_complete_expand_method (generate_instinit (current_class));
+
   /* Now do the constructors */
   for (decl = first_decl ; !java_error_count && decl; decl = TREE_CHAIN (decl))
     {
@@ -8498,9 +8579,7 @@ build_dot_class_method (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;
+  tree stmt, throw_stmt;
 
   static tree get_message_wfl, type_parm_wfl;
 
@@ -8520,33 +8599,24 @@ build_dot_class_method (class)
   /* 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);
-
+  load_class (class_not_found_type_node, 1);
+  load_class (no_class_def_found_type_node, 1);
+  
   /* Create the "class$" function */
   mdecl = create_artificial_method (class, ACC_STATIC, 
 				    build_pointer_type (class_type_node),
 				    classdollar_identifier_node, args);
-  DECL_FUNCTION_THROWS (mdecl) = build_tree_list (NULL_TREE,
-						  no_class_def_found_error);
-  
+  DECL_FUNCTION_THROWS (mdecl) = 
+    build_tree_list (NULL_TREE, no_class_def_found_type_node);
+
   /* 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); */
+     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);
@@ -8559,28 +8629,10 @@ build_dot_class_method (class)
   /* 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,
-		 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 */
-  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);
+  /* Encapsulate STMT in a try block. The catch clause executes THROW_STMT */
+  stmt = encapsulate_with_try_catch (0, class_not_found_type_node,
+				     stmt, throw_stmt);
 
-  /* 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;
@@ -8620,6 +8672,7 @@ static void
 fix_constructors (mdecl)
      tree mdecl;
 {
+  tree iii;			/* Instance Initializer Invocation */
   tree body = DECL_FUNCTION_BODY (mdecl);
   tree thisn_assign, compound = NULL_TREE;
   tree class_type = DECL_CONTEXT (mdecl);
@@ -8661,9 +8714,9 @@ fix_constructors (mdecl)
 	 of that. */
       java_method_add_stmt (mdecl, build_super_invocation (mdecl));
 
-      /* Insert the instance initializer block right here, after the
-         super invocation. */
-      add_instance_initializer (mdecl);
+      /* FIXME */
+      if ((iii = build_instinit_invocation (class_type)))
+	java_method_add_stmt (mdecl, iii);
 
       end_artificial_method_body (mdecl);
     }
@@ -8674,7 +8727,6 @@ fix_constructors (mdecl)
       int invokes_this = 0;
       tree found_call = NULL_TREE;
       tree main_block = BLOCK_EXPR_BODY (body);
-      tree ii;			/* Instance Initializer */
       
       while (body)
 	switch (TREE_CODE (body))
@@ -8717,8 +8769,8 @@ fix_constructors (mdecl)
 	}
       
       /* Insert the instance initializer block right after. */
-      if (!invokes_this && (ii = build_instance_initializer (mdecl)))
-	compound = add_stmt_to_compound (compound, NULL_TREE, ii);
+      if (!invokes_this && (iii = build_instinit_invocation (class_type)))
+	compound = add_stmt_to_compound (compound, NULL_TREE, iii);
 
       /* Fix the constructor main block if we're adding extra stmts */
       if (compound)
@@ -10285,6 +10337,8 @@ patch_method_invocation (patch, primary,
   if (ret_decl)
     *ret_decl = list;
   patch = patch_invoke (patch, list, args);
+
+  /* Now is a good time to insert the call to finit$ */
   if (is_super_init && CLASS_HAS_FINIT_P (current_class))
     {
       tree finit_parms, finit_call;
@@ -10346,7 +10400,8 @@ maybe_use_access_method (is_super_init, 
   if (is_super_init 
       || DECL_CONTEXT (md) == current_class
       || !PURE_INNER_CLASS_TYPE_P (current_class) 
-      || DECL_FINIT_P (md))
+      || DECL_FINIT_P (md)
+      || DECL_INSTINIT_P (md))
     return 0;
   
   /* If we're calling a method found in an enclosing class, generate
@@ -10717,10 +10772,10 @@ find_applicable_accessible_methods_list 
       search_applicable_methods_list (lc, TYPE_METHODS (class), 
 				      name, arglist, &list, &all_list);
 
-      /* When looking finit$ or class$, we turn LC to 1 so that we
-	 only search in class. Note that we should have found
+      /* When looking finit$, class$ or instinit$, we turn LC to 1 so
+	 that we only search in class. Note that we should have found
 	 something at this point. */
-      if (ID_FINIT_P (name) || ID_CLASSDOLLAR_P (name))
+      if (ID_FINIT_P (name) || ID_CLASSDOLLAR_P (name) || ID_INSTINIT_P (name))
 	{
 	  lc = 1;
 	  if (!list)
@@ -12001,16 +12056,6 @@ java_complete_lhs (node)
 	return error_mark_node;
       break;
 
-    case INSTANCE_INITIALIZERS_EXPR:
-      in_instance_initializer++;
-      node = java_complete_tree (TREE_OPERAND (node, 0));
-      in_instance_initializer--;
-      if (node != error_mark_node)
-	TREE_TYPE (node) = void_type_node;
-      else
-	return error_mark_node;
-      break;
-
     default:
       CAN_COMPLETE_NORMALLY (node) = 1;
       /* Ok: may be we have a STRING_CST or a crafted `StringBuffer'
@@ -14709,12 +14754,12 @@ patch_return (node)
   if (!return_exp && (mtype != void_type_node && !DECL_CONSTRUCTOR_P (meth)))
     error_found = 2;
   
-  if (in_instance_initializer)
+  if (DECL_INSTINIT_P (current_function_decl))
     error_found = 1;
 
   if (error_found)
     {
-      if (in_instance_initializer)
+      if (DECL_INSTINIT_P (current_function_decl))
 	parse_error_context (wfl_operator,
 			     "`return' inside instance initializer");
 	
@@ -15234,6 +15279,39 @@ patch_switch_statement (node)
 
 /* 14.18 The try/catch statements */
 
+/* Encapsulate TRY_STMTS' in a try catch sequence. The catch clause
+   catches TYPE and executes CATCH_STMTS.  */
+
+static tree
+encapsulate_with_try_catch (location, type, try_stmts, catch_stmts)
+     int location;
+     tree type, try_stmts, catch_stmts;
+{
+  tree try_block, catch_clause_param, catch_block, catch;
+
+  /* First build a try block */
+  try_block = build_expr_block (try_stmts, NULL_TREE);
+
+  /* Build a catch block: we need a catch clause parameter */
+  catch_clause_param = build_decl (VAR_DECL, 
+				   wpv_id, build_pointer_type (type));
+  /* And a block */
+  catch_block = build_expr_block (NULL_TREE, catch_clause_param);
+  
+  /* Initialize the variable and store in the block */
+  catch = build (MODIFY_EXPR, NULL_TREE, catch_clause_param,
+		 build (JAVA_EXC_OBJ_EXPR, ptr_type_node));
+  add_stmt_to_block (catch_block, NULL_TREE, catch);
+
+  /* Add the catch statements */
+  add_stmt_to_block (catch_block, NULL_TREE, catch_stmts);
+
+  /* Now we can build a CATCH_EXPR */
+  catch_block = build1 (CATCH_EXPR, NULL_TREE, catch_block);
+
+  return build_try_statement (location, try_block, catch_block);
+}
+
 static tree
 build_try_statement (location, try_block, catches)
      int location;
@@ -15468,12 +15546,13 @@ patch_throw_statement (node, wfl_op1)
   unchecked_ok = IS_UNCHECKED_EXCEPTION_P (TREE_TYPE (type));
 
   SET_WFL_OPERATOR (wfl_operator, node, wfl_op1);
-  /* An instance can't throw a checked excetion unless that exception
+  /* An instance can't throw a checked exception unless that exception
      is explicitely declared in the `throws' clause of each
      constructor. This doesn't apply to anonymous classes, since they
      don't have declared constructors. */
   if (!unchecked_ok 
-      && in_instance_initializer && !ANONYMOUS_CLASS_P (current_class))
+      && DECL_INSTINIT_P (current_function_decl)
+      && !ANONYMOUS_CLASS_P (current_class))
     {
       tree current;
       for (current = TYPE_METHODS (current_class); current; 
@@ -15619,6 +15698,38 @@ purge_unchecked_exceptions (mdecl)
     }
   /* List is inverted here, but it doesn't matter */
   DECL_FUNCTION_THROWS (mdecl) = new;
+}
+
+/* This function goes over all of CLASS_TYPE ctors and checks whether
+   each of then features at least one unchecked exception in it
+   `throws' clause. If it's the case, it returns `true', `false'
+   otherwise.  */
+
+static bool
+ctors_unchecked_throws_clause_p (class_type)
+     tree class_type;
+{
+  tree current;
+
+  for (current = TYPE_METHODS (class_type); current;
+       current = TREE_CHAIN (current))
+    {
+      bool ctu = false;	/* Ctor Throws Unchecked */
+      if (DECL_CONSTRUCTOR_P (current))
+	{
+	  tree throws;
+	  for (throws = DECL_FUNCTION_THROWS (current); throws && !ctu;
+	       throws = TREE_CHAIN (throws))
+	    if (inherits_from_p (TREE_VALUE (throws), exception_type_node))
+	      ctu = true;
+	}
+      /* We return false as we found one ctor that is unfit. */
+      if (!ctu && DECL_CONSTRUCTOR_P (current))
+	return false;
+    }
+  /* All ctors feature at least one unchecked exception in their
+     `throws' clause. */
+  return true;
 }
 
 /* 15.24 Conditional Operator ?: */


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]