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]

PATH: More xref framework work and static initializers implementation


I just checked in a patch which does some more work for the xref
framework and also implements the Java static initializer blocks.

The xref work mainly consists in keeping line/column information for
decls when the flag_emit_xref is seen set.

The work around the Java static initializer blocks allows the blocks
to be linked to the body of <clinit> and also ensures that the rules
around static initializers are respected (textual order execution,
preventing `this' and `return' from being used, preventing checked
exception from being thrown without being caught in the same static
initializer block.)

	* parse.h (EXPR_WFL_GET_LINECOL): Set a line and column count
 	using a WFL compound value.
	* parse.y (xref.h): Include.
	(maybe_create_class_interface_decl): Set DECL_SOURCE_LINE to the
 	WFL compound value.
	(register_fields): Set WFL compound value to lineno if doing
 	xrefs.
	(java_complete_expand_method): Call expand_xref if flag_emit_xref
 	is set.
	* xref.c (system.h, jcf.h, parse.h, obstack.h): Include.
	* xref.h (expand_xref): Prototype renamed from xref_generate.

	* parse.h (BLOCK_CHAIN_DECL): New use GET_CURRENT_BLOCK.
	(GET_CURRENT_BLOCK): New macro.
	* parse.y (current_static_block): New global variable.
	(method_body:): Define action.
	(complete_method_declaration): Set current_function_decl to NULL
 	when work on the current method is done.
	(declare_local_variables): Use GET_CURRENT_BLOCK.
	(java_method_add_stmt): Likewise.
	(java_complete_expand_method): Disable the use of `this' when
 	expanding <clinit>.
	(enter_a_block): If no current method exist, use
 	current_static_block to link static initializer blocks.
	(exit_block): Rewritten to use current_static_block when no current
 	method decl exists.
	(lookup_name_in_blocks): Use GET_CURRENT_BLOCK.
	(patch_return): Forbid the use of `return' in static initializers.
	(patch_throw_statement): Fixed indentation. Issue specific error
 	for uncaught thrown checked exception in static initializer
 	blocks. Removed FIXME.

Index: parse.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/java/parse.h,v
retrieving revision 1.28
diff -u -p -r1.28 parse.h
--- parse.h	1999/03/21 06:09:22	1.28
+++ parse.h	1999/03/28 00:16:03
@@ -456,10 +456,15 @@ typedef struct _jdeplist {
 #define BLOCK_CHAIN_DECL(NODE)						    \
   {		 							    \
     TREE_CHAIN ((NODE)) = 						    \
-      BLOCK_EXPR_DECLS (DECL_FUNCTION_BODY (current_function_decl));	    \
-    BLOCK_EXPR_DECLS (DECL_FUNCTION_BODY (current_function_decl)) = (NODE); \
+      BLOCK_EXPR_DECLS (GET_CURRENT_BLOCK (current_function_decl));         \
+    BLOCK_EXPR_DECLS (GET_CURRENT_BLOCK (current_function_decl)) = (NODE);  \
   }
 
+/* Return the current block, either found in the body of the currently
+   declared function or in the current static block being defined. */
+#define GET_CURRENT_BLOCK(F) ((F) ? DECL_FUNCTION_BODY ((F)) :	\
+			     current_static_block)
+
 /* For an artificial BLOCK (created to house a local variable declaration not
    at the start of an existing block), the parent block;  otherwise NULL. */
 #define BLOCK_EXPR_ORIGIN(NODE) BLOCK_ABSTRACT_ORIGIN(NODE)
@@ -471,6 +476,13 @@ typedef struct _jdeplist {
 /* Retrieve those two info separately. */
 #define DECL_SOURCE_LINE_FIRST(DECL)    (DECL_SOURCE_LINE(DECL) & 0x0000ffff)
 #define DECL_SOURCE_LINE_LAST(DECL)     (DECL_SOURCE_LINE(DECL) >> 16)
+
+/* Retrieve line/column from a WFL. */
+#define EXPR_WFL_GET_LINECOL(V,LINE,COL)	\
+  {						\
+     (LINE) = (V) >> 12;			\
+     (COL) = (V) & 0xfff;			\
+   }
 
 /* Build a WFL for expression nodes */
 #define BUILD_EXPR_WFL(NODE, WFL)					\
Index: parse.y
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/java/parse.y,v
retrieving revision 1.67
diff -u -p -r1.67 parse.y
--- parse.y	1999/03/27 16:05:23	1.67
+++ parse.y	1999/03/28 00:16:04
@@ -61,6 +61,7 @@ definitions and other extensions.  */
 #include "zipfile.h"
 #include "convert.h"
 #include "buffer.h"
+#include "xref.h"
 
 #ifndef DIR_SEPARATOR
 #define DIR_SEPARATOR '/'
@@ -290,6 +291,10 @@ static tree java_lang_id = NULL_TREE;
 
 /* The "java.lang.Cloneable" qualified name.  */
 static tree java_lang_cloneable = NULL_TREE;
+
+/* Context and flag for static blocks */
+static tree current_static_block = NULL_TREE;
+
 %}
 
 %union {
@@ -931,11 +936,13 @@ method_body:
 static_initializer:
 	static block
 		{
-		  RULE ("STATIC_INITIALIZER");
+		  TREE_CHAIN ($2) = ctxp->static_initialized;
+		  ctxp->static_initialized = $2;
 		}
 |	static block SC_TK	/* Shouldn't be here. FIXME */
 		{
-		  RULE ("STATIC_INITIALIZER");
+		  TREE_CHAIN ($2) = ctxp->static_initialized;
+		  ctxp->static_initialized = $2;
 		}
 ;
 
@@ -2850,7 +2857,11 @@ maybe_create_class_interface_decl (decl,
   
   /* Take care of the file and line business */
   DECL_SOURCE_FILE (decl) = EXPR_WFL_FILENAME (cl);
-  DECL_SOURCE_LINE (decl) = EXPR_WFL_LINENO (cl);
+  /* If we're emiting xrefs, store the line/col number information */
+  if (flag_emit_xref)
+    DECL_SOURCE_LINE (decl) = EXPR_WFL_LINECOL (cl);
+  else
+    DECL_SOURCE_LINE (decl) = EXPR_WFL_LINENO (cl);
   CLASS_FROM_SOURCE_P (TREE_TYPE (decl)) = 1;
   CLASS_FROM_CURRENTLY_COMPILED_SOURCE_P (TREE_TYPE (decl)) =
     IS_A_COMMAND_LINE_FILENAME_P (EXPR_WFL_FILENAME_NODE (cl));
@@ -3142,7 +3153,10 @@ register_fields (flags, type, variable_l
 
       /* Set lineno to the line the field was found and create a
          declaration for it. Eventually sets the @deprecated tag flag. */
-      lineno = EXPR_WFL_LINENO (cl);
+      if (flag_emit_xref)
+	lineno = EXPR_WFL_LINECOL (cl);
+      else
+	lineno = EXPR_WFL_LINENO (cl);
       field_decl = add_field (class_type, current_name, real_type, flags);
       CHECK_DEPRECATED (field_decl);
       
@@ -3470,6 +3484,9 @@ finish_method_declaration (method_body)
   /* Merge last line of the function with first line, directly in the
      function decl. It will be used to emit correct debug info. */
   DECL_SOURCE_LINE_MERGE (current_function_decl, ctxp->last_ccb_indent1);
+  /* So we don't have an irrelevant function declaration context for
+     the next static block we'll see. */
+  current_function_decl = NULL_TREE;
 }
 
 /* Build a an error message for constructor circularity errors.  */
@@ -5237,11 +5254,11 @@ declare_local_variables (modifier, type,
 
   /* Push a new block if statements were seen between the last time we
      pushed a block and now. Keep a cound of block to close */
-  if (BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (current_function_decl)))
+  if (BLOCK_EXPR_BODY (GET_CURRENT_BLOCK (current_function_decl)))
     {
-      tree body = DECL_FUNCTION_BODY (current_function_decl);
+      tree body = GET_CURRENT_BLOCK (current_function_decl);
       tree b = enter_block ();
-      BLOCK_EXPR_ORIGIN(b) = body;
+      BLOCK_EXPR_ORIGIN (b) = body;
     }
 
   if (modifier)
@@ -5498,7 +5515,7 @@ tree
 java_method_add_stmt (fndecl, expr)
      tree fndecl, expr;
 {
-  return add_stmt_to_block (DECL_FUNCTION_BODY (fndecl), NULL_TREE, expr);
+  return add_stmt_to_block (GET_CURRENT_BLOCK (fndecl), NULL_TREE, expr);
 }
 
 static tree
@@ -5689,6 +5706,8 @@ java_complete_expand_methods ()
 	{
 	  if (flag_emit_class_files)
 	    write_classfile (current_class);
+	  if (flag_emit_xref)
+	    expand_xref (current_class);
 	  else if (! flag_syntax_only)
 	    finish_class (current_class);
 	}
@@ -5729,8 +5748,13 @@ java_complete_expand_method (mdecl)
 
       if (block_body != NULL_TREE)
 	{
+	  /* Prevent the use of `this' inside <clinit> */
+	  if (DECL_NAME (current_function_decl) == clinit_identifier_node)
+	    ctxp->explicit_constructor_p = 1;
+
 	  block_body = java_complete_tree (block_body);
 	  check_for_initialization (block_body);
+	  ctxp->explicit_constructor_p = 0;
 	}
       BLOCK_EXPR_BODY (fbody) = block_body;
 
@@ -8269,8 +8293,13 @@ enter_a_block (b)
      tree b;
 {
   tree fndecl = current_function_decl; 
+
+  if (!fndecl) {
+    BLOCK_SUPERCONTEXT (b) = current_static_block;
+    current_static_block = b;
+  }
 
-  if (!DECL_FUNCTION_BODY (fndecl))
+  else if (!DECL_FUNCTION_BODY (fndecl))
     {
       BLOCK_SUPERCONTEXT (b) = fndecl;
       DECL_FUNCTION_BODY (fndecl) = b;
@@ -8290,11 +8319,20 @@ enter_a_block (b)
 static tree
 exit_block ()
 {
-  tree b = DECL_FUNCTION_BODY (current_function_decl);
-
-  if (BLOCK_SUPERCONTEXT (b) != current_function_decl)
-    DECL_FUNCTION_BODY (current_function_decl) = BLOCK_SUPERCONTEXT (b);
+  tree b;
+  if (current_function_decl)
+    {
+      b = DECL_FUNCTION_BODY (current_function_decl);
+      if (BLOCK_SUPERCONTEXT (b) != current_function_decl)
+	DECL_FUNCTION_BODY (current_function_decl) = BLOCK_SUPERCONTEXT (b);
+    }
+  else
+    {
+      b = current_static_block;
 
+      if (BLOCK_SUPERCONTEXT (b))
+	current_static_block = BLOCK_SUPERCONTEXT (b);
+    }
   return b;
 }
 
@@ -8306,7 +8344,7 @@ static tree
 lookup_name_in_blocks (name)
      tree name;
 {
-  tree b = DECL_FUNCTION_BODY (current_function_decl);
+  tree b = GET_CURRENT_BLOCK (current_function_decl);
 
   while (b != current_function_decl)
     {
@@ -8328,7 +8366,7 @@ lookup_name_in_blocks (name)
 static void
 maybe_absorb_scoping_blocks ()
 {
-  while (BLOCK_EXPR_ORIGIN (DECL_FUNCTION_BODY (current_function_decl)))
+  while (BLOCK_EXPR_ORIGIN (GET_CURRENT_BLOCK (current_function_decl)))
     {
       tree b = exit_block ();
       java_method_add_stmt (current_function_decl, b);
@@ -10273,6 +10311,10 @@ patch_return (node)
   if (return_exp && (mtype == void_type_node || DECL_CONSTRUCTOR_P (meth)))
     error_found = 1;
 
+  /* It's invalid to use a return statement in a static block */
+  if (DECL_NAME (current_function_decl) == clinit_identifier_node)
+    error_found = 1;
+
   /* It's invalid to have a no return value within a function that
      isn't declared with the keyword `void' */
   if (!return_exp && (mtype != void_type_node && !DECL_CONSTRUCTOR_P (meth)))
@@ -10280,7 +10322,11 @@ patch_return (node)
 
   if (error_found)
     {
-      if (!DECL_CONSTRUCTOR_P (meth))
+      if (DECL_NAME (current_function_decl) == clinit_identifier_node)
+	parse_error_context (wfl_operator,
+			     "`return' inside static initializer.");
+
+      else if (!DECL_CONSTRUCTOR_P (meth))
 	{
 	  char *t = strdup (lang_printable_name (mtype, 0));
 	  parse_error_context (wfl_operator, 
@@ -10983,8 +11029,7 @@ patch_throw_statement (node, wfl_op1)
      throws clause the declaration. */
   SET_WFL_OPERATOR (wfl_operator, node, wfl_op1);
   if (!unchecked_ok)
-    tryblock_throws_ok = 
-      check_thrown_exceptions_do (TREE_TYPE (expr));
+    tryblock_throws_ok = check_thrown_exceptions_do (TREE_TYPE (expr));
   if (!(unchecked_ok || tryblock_throws_ok))
     {
       /* If there is a surrounding try block that has no matching
@@ -10998,11 +11043,22 @@ patch_throw_statement (node, wfl_op1)
 			     lang_printable_name (type, 0));
       /* If we have no surrounding try statement and the method doesn't have
 	 any throws, report it now. FIXME */
+
+      /* We report that the exception can't be throw from a try block
+         in all circumstances but when the `throw' is inside a static
+         block. */
       else if (!EXCEPTIONS_P (currently_caught_type_list) 
 	       && !tryblock_throws_ok)
-	parse_error_context (wfl_operator, "Checked exception `%s' isn't "
-			     "thrown from a `try' block", 
-			     lang_printable_name (type, 0));
+	{
+	  if (DECL_NAME (current_function_decl) == clinit_identifier_node)
+	    parse_error_context (wfl_operator, "Checked exception `%s' can't "
+				 "be thrown in initializer",
+				 lang_printable_name (type, 0));
+	  else
+	    parse_error_context (wfl_operator, "Checked exception `%s' isn't "
+				 "thrown from a `try' block", 
+				 lang_printable_name (type, 0));
+	}
       /* Otherwise, the current method doesn't have the appropriate
          throws declaration */
       else
@@ -11013,11 +11069,6 @@ patch_throw_statement (node, wfl_op1)
       return error_mark_node;
     }
 
-  /* If a throw statement is contained in a static initializer, then a
-     compile-time check ensures that either its value is always an
-     unchecked exception or its value is always caught by some try
-     statement that contains it. FIXME, static initializer. */
-  
   if (! flag_emit_class_files)
     BUILD_THROW (node, expr);
   return node;
Index: xref.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/java/xref.c,v
retrieving revision 1.1
diff -u -p -r1.1 xref.c
--- xref.c	1999/03/22 19:57:37	1.1
+++ xref.c	1999/03/28 00:16:04
@@ -26,9 +26,13 @@ The Free Software Foundation is independ
 
 #include <stdio.h>
 #include "config.h"
+#include "system.h"
 #include "tree.h"
 #include "java-tree.h"
 #include "xref.h"
+#include "jcf.h"
+#include "parse.h"
+#include "obstack.h"
 
 
 static xref_flag_table xref_table [] = {
Index: xref.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/java/xref.h,v
retrieving revision 1.1
diff -u -p -r1.1 xref.h
--- xref.h	1999/03/22 19:57:37	1.1
+++ xref.h	1999/03/28 00:16:04
@@ -25,7 +25,7 @@ The Free Software Foundation is independ
 
 /* Exported functions. */
 int xref_flag_value PROTO ((char *));
-void xref_generate PROTO ((tree));
+void expand_xref PROTO ((tree));
 
 /* flag_emit_xref range of possible values. */
 
.--- Alex (www.cygnus.com/~apbianco, {apbianco-page,apbianco}@cygnus.com)
| Cygnus Java Team.


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