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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Patch] Java: PR 13948


Hi,

  The following is my proposed patch for PR java/13948. It fixes
the ICE there by making sure that a class is loaded before we try
to lay out its methods. I also cleaned up the dead code in
java_layout_seen_methods().

This change however triggered the infamous "./Foo.java: Class `Foo'
has already been defined in file `Foo.java'" error in GCJ.

My first reaction was to use canonical filenames throughout
using libiberty's lrealpath(). However this had two problems:

  a. Handling files like "ConcreteProcess.java" in libgcj that
  are actually symbolic links to "PosixProcess.java" (on Linux),
  but contain class "ConcreteProcess".

  b. "gcj Snafu.java" would give diagnostics with
  /full/path/to/Snafu.java rather than what the user actually gave on
  the command line.

My solution is to distinguish between the "real file" (the full
canonical path) and the "given file" (the name as given by the user)
for parsing - the former is used to keep track of whether a file
has been parsed or not, while the latter is used for everything
else.

The solution is slightly sub-optimal in that lrealpath() mallocs
fresh memory on every invocation and *could be* a bit expensive
not only for that reason, but also when constructed filenames
represent symbolic links or have lots of "./" or "/../" (say).

However, I felt that doing this right away would have unnecessarily
complicated as well as delayed my patch. This can always be
taken up later and I didn't have any numbers to back it anyway.

Finally, I note that this patch also fixes the original ICE
in PR 11117 but changes it to another ICE that I shall soon
look into.

Tested on i686-pc-linux-gnu with no libjava testsuite regressions,
including Jacks.

Ok for mainline?

(This should perhaps also go into 3.4...)

Ranjit.

Index: ChangeLog
from  Ranjit Mathew  <rmathew@hotmail.com>

	Fixes PR java/13948
	* parse.y (java_layout_seen_class_methods): Ensure class is loaded
	before trying to lay out its methods. Remove redundant and dead
	code.
	* jcf-parse.c (read_class): Track parsed files using canonical paths
	obtained via lrealpath from libiberty.
	(java_parse_file): Likewise.
	(parse_source_file_1): Rename formal parameter to reflect its
	modified purpose. Minor formatting fix.

Index: parse.y
===================================================================
*** parse.y	Wed Jun  9 20:00:49 2004
--- parse.y	Mon Jun 14 21:44:11 2004
*************** add_stmt_to_block (tree b, tree type, tr
*** 7574,7599 ****
    return c;
  }

! void java_layout_seen_class_methods (void)
  {
-   tree previous_list = all_class_list;
-   tree end = NULL_TREE;
    tree current;

!   while (1)
!     {
!       for (current = previous_list;
! 	   current != end; current = TREE_CHAIN (current))
! 	layout_class_methods (TREE_TYPE (TREE_VALUE (current)));

!       if (previous_list != all_class_list)
! 	{
! 	  end = previous_list;
! 	  previous_list = all_class_list;
! 	}
!       else
! 	break;
!     }
  }

  static GTY(()) tree stop_reordering;
--- 7574,7597 ----
    return c;
  }

! /* Lays out the methods for the classes seen so far.  */
!
! void
! java_layout_seen_class_methods (void)
  {
    tree current;

!   for (current = all_class_list;
!        current != NULL_TREE;
!        current = TREE_CHAIN (current))
!   {
!     tree cls = TREE_TYPE (TREE_VALUE (current));

!     if (! CLASS_LOADED_P (cls))
!       load_class (cls, 0);
!
!     layout_class_methods (cls);
!   }
  }

  static GTY(()) tree stop_reordering;
Index: jcf-parse.c
===================================================================
--- jcf-parse.c	2004-06-14 20:42:29.000000000 +0530
+++ jcf-parse.c	2004-06-14 21:49:34.000000000 +0530
@@ -494,27 +494,33 @@ read_class (tree name)
   if (current_jcf->java_source)
     {
       const char *filename = current_jcf->filename;
-      tree file;
+      tree given_file, real_file;
       FILE *finput;
       int generate;

       java_parser_context_save_global ();
       java_push_parser_context ();
-      BUILD_FILENAME_IDENTIFIER_NODE (file, filename);
-      generate = IS_A_COMMAND_LINE_FILENAME_P (file);
+
+      BUILD_FILENAME_IDENTIFIER_NODE (given_file, filename);
+      real_file = get_identifier (lrealpath (filename));
+
+      generate = IS_A_COMMAND_LINE_FILENAME_P (given_file);
       if (wfl_operator == NULL_TREE)
 	wfl_operator = build_expr_wfl (NULL_TREE, NULL, 0, 0);
-      EXPR_WFL_FILENAME_NODE (wfl_operator) = file;
+      EXPR_WFL_FILENAME_NODE (wfl_operator) = given_file;
       input_filename = ggc_strdup (filename);
       output_class = current_class = NULL_TREE;
       current_function_decl = NULL_TREE;
-      if (!HAS_BEEN_ALREADY_PARSED_P (file))
+
+      if (! HAS_BEEN_ALREADY_PARSED_P (real_file))
 	{
-	  if (!(finput = fopen (input_filename, "r")))
+	  if (! (finput = fopen (input_filename, "r")))
 	    fatal_error ("can't reopen %s: %m", input_filename);
-	  parse_source_file_1 (file, finput);
+
+	  parse_source_file_1 (real_file, finput);
 	  parse_source_file_2 ();
 	  parse_source_file_3 ();
+
 	  if (fclose (finput))
 	    fatal_error ("can't close %s: %m", input_filename);
 	}
@@ -798,11 +804,12 @@ parse_class_file (void)
 /* Parse a source file, as pointed by the current value of INPUT_FILENAME. */

 static void
-parse_source_file_1 (tree file, FILE *finput)
+parse_source_file_1 (tree real_file, FILE *finput)
 {
   int save_error_count = java_error_count;
-  /* Mark the file as parsed */
-  HAS_BEEN_ALREADY_PARSED_P (file) = 1;
+
+  /* Mark the file as parsed.  */
+  HAS_BEEN_ALREADY_PARSED_P (real_file) = 1;

   jcf_dependency_add_file (input_filename, 0);

@@ -1015,9 +1022,11 @@ java_parse_file (int set_yydebug ATTRIBU
       unsigned char magic_string[4];
       uint32 magic = 0;
       tree name = TREE_VALUE (node);
+      tree real_file;

       /* Skip already parsed files */
-      if (HAS_BEEN_ALREADY_PARSED_P (name))
+      real_file = get_identifier (lrealpath (IDENTIFIER_POINTER (name)));
+      if (HAS_BEEN_ALREADY_PARSED_P (real_file))
 	continue;

       /* Close previous descriptor, if any */
@@ -1075,7 +1084,8 @@ java_parse_file (int set_yydebug ATTRIBU
 	  JAVA_FILE_P (node) = 1;
 	  java_push_parser_context ();
 	  java_parser_context_save_global ();
-	  parse_source_file_1 (name, finput);
+
+	  parse_source_file_1 (real_file, finput);
 	  java_parser_context_restore_global ();
 	  java_pop_parser_context (1);
 	}


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