This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH]: Java front-end improvement patch.
- To: egcs-patches at egcs dot cygnus dot com
- Subject: [PATCH]: Java front-end improvement patch.
- From: Alexandre Petit-Bianco <apbianco at cygnus dot com>
- Date: Thu, 6 Jan 2000 14:08:06 -0800
I just checked in an other front-end improvement patch. This one
does:
- a better job at picking up source/class files during the type
dependencies resolution. The limitation was originally removed with
this patch http://gcc.gnu.org/ml/gcc-patches/1999-12/msg00181.html, but
took some tune up,
- provide better handling of the situation where a source file is
newer than its matching class file. A warning is still issued, but
the source file is parsed instead. I plan on introducing a flag to
force class files to be picked up preferably, since it might help
people in certain situations.
./A
Fri Dec 24 00:25:29 1999 Alexandre Petit-Bianco <apbianco@cygnus.com>
* Makefile.in (LIBDEPS): Added gcc's errors.o
(../jcf-dump$(exeext):): Link with gcc's errors.o
(../gcjh$(exeext):): Likewise.
* expr.c (expand_java_NEW): Layout the entire target type instead of
laying out its methods only.
(lookup_field): Layout the class after having loaded it.
* java-tree.h (java_debug_context): Declared.
* jcf-io.c (toplev.h): Included.
(find_class): Removed assignment to jcf's outofsynch
field. Force source file to be read if newer than its matching
class file. Tweaked debug messages.
* jcf-parse.c (jcf_out_of_synch): Deleted.
(read_class): Call to jcf_out_of_synch removed.
* jcf.h (typedef struct JCF): Field `outofsynch' deleted.
(jcf_out_of_synch): Prototype deleted.
* parse.h (struct parser_ctxt): `minus_seen', `java_error_flag',
`deprecated' and `class_err': integer turned into bit fields.
New bit fields `saved_data_ctx' and `saved_data'. Fixed comments.
* parse.y (package_list): New global.
(package_declaration:): Record newly parsed package name.
(extra_ctxp_pushed_p): Static global deleted.
(java_parser_context_save_global): Create buffer context for the
purpose of saving globals, if necessary.
(java_parser_context_restore_global): Pop context pushed for the
purpose of saving globals, if necessary.
(java_debug_context_do): New prototype and function.
(java_debug_context): Likewise.
(do_resolve_class): Use already parsed package names to qualify
and lookup class candidate.
(java_pre_expand_clinit): Removed unnecessary local variable.
Index: Makefile.in
===================================================================
RCS file: /cvs/gcc/egcs/gcc/java/Makefile.in,v
retrieving revision 1.44
diff -u -p -r1.44 Makefile.in
--- Makefile.in 1999/09/20 16:27:29 1.44
+++ Makefile.in 2000/01/06 21:32:54
@@ -144,7 +144,7 @@ LIBIBERTY = ../../libiberty/libiberty.a
# How to link with both our special library facilities
# and the system's installed libraries.
LIBS = $(LIBIBERTY) $(CLIB)
-LIBDEPS = $(LIBIBERTY)
+LIBDEPS = $(LIBIBERTY) ../errors.o
# Specify the directories to be searched for header files.
# Both . and srcdir are used, in that order,
@@ -184,7 +184,7 @@ compiler: ../jc1$(exeext) ../jv-scan$(ex
../jcf-dump$(exeext): jcf-dump.o jcf-io.o jcf-depend.o jcf-path.o \
zextract.o $(LIBDEPS)
$(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ jcf-dump.o jcf-io.o \
- jcf-depend.o jcf-path.o zextract.o $(LIBS)
+ jcf-depend.o jcf-path.o zextract.o $(LIBS) ../errors.o
# Dependencies here must be kept in sync with dependencies in Make-lang.in.
../jvgenmain$(exeext): jvgenmain.o mangle.o $(LIBDEPS)
@@ -193,7 +193,7 @@ compiler: ../jc1$(exeext) ../jv-scan$(ex
../gcjh$(exeext): gjavah.o jcf-io.o jcf-depend.o jcf-path.o \
zextract.o $(LIBDEPS)
$(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ gjavah.o jcf-io.o \
- jcf-depend.o jcf-path.o zextract.o $(LIBS)
+ jcf-depend.o jcf-path.o zextract.o $(LIBS) ../errors.o
Makefile: $(srcdir)/Makefile.in $(srcdir)/../configure
cd ..; $(SHELL) config.status
Index: expr.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/java/expr.c,v
retrieving revision 1.53
diff -u -p -r1.53 expr.c
--- expr.c 1999/12/31 03:30:22 1.53
+++ expr.c 2000/01/06 21:33:02
@@ -1010,7 +1010,7 @@ expand_java_NEW (type)
{
if (! CLASS_LOADED_P (type))
load_class (type, 1);
- layout_class_methods (type);
+ safe_layout_class (type);
push_value (build (CALL_EXPR, promote_type (type),
build_address_of (alloc_object_node),
tree_cons (NULL_TREE, build_class_ref (type),
@@ -1230,6 +1230,7 @@ lookup_field (typep, name)
if (CLASS_P (*typep) && !CLASS_LOADED_P (*typep))
{
load_class (*typep, 1);
+ safe_layout_class (*typep);
if (!TYPE_SIZE (*typep) || TREE_CODE (TYPE_SIZE (*typep)) == ERROR_MARK)
return error_mark_node;
}
Index: java-tree.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/java/java-tree.h,v
retrieving revision 1.49
diff -u -p -r1.49 java-tree.h
--- java-tree.h 1999/12/10 16:06:23 1.49
+++ java-tree.h 2000/01/06 21:33:07
@@ -637,6 +637,7 @@ extern char* open_class PROTO ((char *,
extern char* open_class PROTO ((char *, struct JCF *, int, const char *));
# endif /* JCF_USE_STDIO */
#endif
+void java_debug_context PROTO ((void));
/* We use ARGS_SIZE_RTX to indicate that gcc/expr.h has been included
to declare `enum expand_modifier'. */
Index: jcf-io.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/java/jcf-io.c,v
retrieving revision 1.19
diff -u -p -r1.19 jcf-io.c
--- jcf-io.c 1999/09/16 15:45:10 1.19
+++ jcf-io.c 2000/01/06 21:33:07
@@ -27,6 +27,7 @@ The Free Software Foundation is independ
#include "jcf.h"
#include "tree.h"
+#include "toplev.h"
#include "java-tree.h"
/* DOS brain-damage */
@@ -286,7 +287,7 @@ DEFUN(find_class, (classname, classname_
java_buffer = (char *) alloca (buflen);
- jcf->java_source = jcf->outofsynch = 0;
+ jcf->java_source = 0;
for (entry = jcf_path_start (); entry != NULL; entry = jcf_path_next (entry))
{
@@ -352,8 +353,24 @@ DEFUN(find_class, (classname, classname_
}
}
+ /* We preferably pick a class file if we have a chance. If the source
+ file is newer than the class file, we issue a warning and parse the
+ source file instead.
+ There should be a flag to allow people have the class file picked
+ up no matter what. FIXME. */
if (! java && ! class && java_buf.st_mtime >= class_buf.st_mtime)
- jcf->outofsynch = 1;
+ {
+ char *stripped_class_name = xstrdup (classname);
+ int i = strlen (stripped_class_name);
+
+ while (stripped_class_name [i] != '.')
+ i--;
+
+ stripped_class_name [i] = '\0';
+ warning ("Source file for class `%s' is newer than its matching class file. Source file used instead", stripped_class_name);
+ free (stripped_class_name);
+ class = -1;
+ }
if (! java)
dep_file = java_buffer;
@@ -382,7 +399,10 @@ DEFUN(find_class, (classname, classname_
#else
if (!class)
{
- SOURCE_FRONTEND_DEBUG (("Trying %s", buffer));
+ SOURCE_FRONTEND_DEBUG ((stderr, "[Class selected: %s]\n",
+ classname+classname_length-
+ (classname_length <= 30 ?
+ classname_length : 30)));
fd = open (buffer, O_RDONLY | O_BINARY);
if (fd >= 0)
goto found;
@@ -391,7 +411,10 @@ DEFUN(find_class, (classname, classname_
if (!java)
{
strcpy (buffer, java_buffer);
- SOURCE_FRONTEND_DEBUG (("Trying %s", buffer));
+ SOURCE_FRONTEND_DEBUG ((stderr, "[Source selected: %s]\n",
+ classname+classname_length-
+ (classname_length <= 30 ?
+ classname_length : 30)));
fd = open (buffer, O_RDONLY);
if (fd >= 0)
{
Index: jcf-parse.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/java/jcf-parse.c,v
retrieving revision 1.39
diff -u -p -r1.39 jcf-parse.c
--- jcf-parse.c 1999/12/31 03:30:22 1.39
+++ jcf-parse.c 2000/01/06 21:33:10
@@ -440,22 +440,6 @@ get_class_constant (JCF *jcf , int i)
return type;
}
-void
-DEFUN(jcf_out_of_synch, (jcf),
- JCF *jcf)
-{
- char *source = xstrdup (jcf->filename);
- int i = strlen (source);
-
- while (source[i] != '.')
- i--;
-
- source [i] = '\0';
- warning ("Class file `%s' out of synch with `%s.java'",
- jcf->filename, source);
- free (source);
-}
-
/* Read a class with the fully qualified-name NAME.
Return 1 iff we read the requested file.
(It is still possible we failed if the file did not
@@ -488,8 +472,6 @@ read_class (name)
{
this_jcf.seen_in_zip = 0;
current_jcf = &this_jcf;
- if (this_jcf.outofsynch)
- jcf_out_of_synch (current_jcf);
}
}
else
Index: jcf.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/java/jcf.h,v
retrieving revision 1.12
diff -u -p -r1.12 jcf.h
--- jcf.h 1999/09/16 15:45:10 1.12
+++ jcf.h 2000/01/06 21:33:11
@@ -92,8 +92,6 @@ typedef struct JCF {
unsigned char *read_end;
int seen_in_zip;
int java_source;
- int outofsynch; /* Found a class file out of synch
- with the matching source file. */
long zip_offset;
jcf_filbuf_t filbuf;
void *read_state;
@@ -226,7 +224,6 @@ typedef struct JCF {
extern const char *find_class PROTO ((const char *, int, JCF*, int));
extern const char *find_classfile PROTO ((char *, JCF*, const char *));
extern int jcf_filbuf_from_stdio PROTO ((JCF *jcf, int count));
-extern void jcf_out_of_synch PROTO((JCF *));
extern int jcf_unexpected_eof PROTO ((JCF*, int)) ATTRIBUTE_NORETURN;
/* Extract a character from a Java-style Utf8 string.
Index: parse.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/java/parse.h,v
retrieving revision 1.41
diff -u -p -r1.41 parse.h
--- parse.h 1999/12/31 03:30:21 1.41
+++ parse.h 2000/01/06 21:33:13
@@ -605,11 +605,25 @@ struct parser_ctxt {
int osb_depth; /* Current depth of [ in an expression */
int osb_limit; /* Limit of this depth */
int *osb_number; /* Keep track of ['s */
- int minus_seen; /* Integral literal overflow */
int lineno; /* Current lineno */
- int java_error_flag; /* Report error when true */
- int deprecated; /* @deprecated tag seen */
+ /* The flags section */
+
+ /* Indicates a context used for saving the parser status. The
+ context must be popped when the status is restored. */
+ unsigned saved_data_ctx:1;
+ /* Indicates that a context already contains saved data and that the
+ next save operation will require a new context to be created. */
+ unsigned saved_data:1;
+ /* Integral literal overflow */
+ unsigned minus_seen:1;
+ /* Report error when true */
+ unsigned java_error_flag:1;
+ /* @deprecated tag seen */
+ unsigned deprecated:1;
+ /* Flag to report certain errors (fix this documentation. FIXME) */
+ unsigned class_err:1;
+
/* This section is defined only if we compile jc1 */
#ifndef JC1_LITE
tree modifier_ctx [11]; /* WFL of modifiers */
@@ -619,7 +633,6 @@ struct parser_ctxt {
struct JCF *current_jcf; /* CU jcf */
int prevent_ese; /* Prevent expression statement error */
- int class_err; /* Flag to report certain errors */
int formal_parameter_number; /* Number of parameters found */
int interface_number; /* # itfs declared to extend an itf def */
@@ -650,7 +663,7 @@ struct parser_ctxt {
int pending_block; /* Pending block to close */
- int explicit_constructor_p; /* True when processing an explicit
+ int explicit_constructor_p; /* >0 when processing an explicit
constructor. This flag is used to trap
illegal argument usage during an
explicit constructor invocation. */
Index: parse.y
===================================================================
RCS file: /cvs/gcc/egcs/gcc/java/parse.y,v
retrieving revision 1.126
diff -u -p -r1.126 parse.y
--- parse.y 1999/12/31 03:30:21 1.126
+++ parse.y 2000/01/06 21:33:57
@@ -266,6 +266,7 @@ static tree search_loop PROTO ((tree));
static int labeled_block_contains_loop_p PROTO ((tree, tree));
static void check_abstract_method_definitions PROTO ((int, tree, tree));
static void java_check_abstract_method_definitions PROTO ((tree));
+static void java_debug_context_do PROTO ((int));
/* Number of error found so far. */
int java_error_count;
@@ -326,6 +327,9 @@ static tree java_lang_cloneable = NULL_T
/* Context and flag for static blocks */
static tree current_static_block = NULL_TREE;
+/* The list of all packages we've seen so far */
+static tree package_list = NULL_TREE;
+
%}
%union {
@@ -591,7 +595,10 @@ type_declarations:
package_declaration:
PACKAGE_TK name SC_TK
- { ctxp->package = EXPR_WFL_NODE ($2); }
+ {
+ ctxp->package = EXPR_WFL_NODE ($2);
+ package_list = tree_cons (ctxp->package, NULL, package_list);
+ }
| PACKAGE_TK error
{yyerror ("Missing name"); RECOVER;}
| PACKAGE_TK name error
@@ -2368,25 +2375,30 @@ java_push_parser_context ()
}
}
-/* If the first file of a file list was a class file, no context
- exists for a source file to be parsed. This boolean remembers that
- java_parser_context_save_global might have created a dummy one, so
- that java_parser_context_restore_global can pop it. */
-static int extra_ctxp_pushed_p = 0;
-
void
java_parser_context_save_global ()
{
if (!ctxp)
{
java_push_parser_context ();
- extra_ctxp_pushed_p = 1;
+ ctxp->saved_data_ctx = 1;
+ }
+ else if (ctxp->saved_data)
+ {
+ struct parser_ctxt *new =
+ (struct parser_ctxt *)xmalloc(sizeof (struct parser_ctxt));
+ bzero ((PTR)new, sizeof (struct parser_ctxt));
+ memcpy ((PTR)new, (PTR)ctxp, sizeof (struct parser_ctxt));
+ new->next = ctxp;
+ ctxp = new;
+ ctxp->saved_data_ctx = 1;
}
ctxp->finput = finput;
ctxp->lineno = lineno;
ctxp->current_class = current_class;
ctxp->filename = input_filename;
ctxp->current_function_decl = current_function_decl;
+ ctxp->saved_data = 1;
}
void
@@ -2396,12 +2408,10 @@ java_parser_context_restore_global ()
lineno = ctxp->lineno;
current_class = ctxp->current_class;
input_filename = ctxp->filename;
+ ctxp->saved_data = 0;
current_function_decl = ctxp->current_function_decl;
- if (!ctxp->next && extra_ctxp_pushed_p)
- {
- java_pop_parser_context (0);
- extra_ctxp_pushed_p = 0;
- }
+ if (ctxp->saved_data_ctx)
+ java_pop_parser_context (0);
}
void
@@ -2444,6 +2454,44 @@ java_pop_parser_context (generate)
free (toFree);
}
+/* Dump the stacked up parser contexts. Intended to be called from a
+ debugger. */
+
+static void
+java_debug_context_do (tab)
+ int tab;
+{
+#define JAVA_TAB_CONTEXT(C) \
+ {int i; for (i = 0; i < (C); i++) fputc (' ', stderr);}
+
+ struct parser_ctxt *copy = ctxp;
+ while (copy)
+ {
+ JAVA_TAB_CONTEXT (tab);
+ fprintf (stderr, "ctxt: 0x%0lX\n", (unsigned long)copy);
+ JAVA_TAB_CONTEXT (tab);
+ fprintf (stderr, "filename: %s\n", copy->filename);
+ JAVA_TAB_CONTEXT (tab);
+ fprintf (stderr, "package: %s\n",
+ (copy->package ?
+ IDENTIFIER_POINTER (copy->package) : "<none>"));
+ JAVA_TAB_CONTEXT (tab);
+ fprintf (stderr, "context for saving: %d\n", copy->saved_data_ctx);
+ JAVA_TAB_CONTEXT (tab);
+ fprintf (stderr, "saved data: %d\n", copy->saved_data);
+ copy = copy->next;
+ tab += 2;
+ }
+#undef JAVA_TAB_CONTEXT
+}
+
+void
+java_debug_context ()
+{
+ java_debug_context_do (0);
+}
+
+
/* Reporting an constructor invocation error. */
static void
parse_ctor_invocation_error ()
@@ -4311,7 +4359,7 @@ do_resolve_class (class_type, decl, cl)
return NULL_TREE;
/* 2- And check for the type in the current compilation unit. If it fails,
- try with a name qualified with the package name if appropriate. */
+ try with a name qualified with the package name we've seen so far */
if ((new_class_decl = IDENTIFIER_CLASS_VALUE (TYPE_NAME (class_type))))
{
if (!CLASS_LOADED_P (TREE_TYPE (new_class_decl)) &&
@@ -4321,40 +4369,29 @@ do_resolve_class (class_type, decl, cl)
}
original_name = TYPE_NAME (class_type);
- if (!QUALIFIED_P (TYPE_NAME (class_type)) && ctxp->package)
- TYPE_NAME (class_type) = merge_qualified_name (ctxp->package,
- TYPE_NAME (class_type));
-#if 1
- if (!(new_class_decl = IDENTIFIER_CLASS_VALUE (TYPE_NAME (class_type))))
- load_class (TYPE_NAME (class_type), 0);
- if ((new_class_decl = IDENTIFIER_CLASS_VALUE (TYPE_NAME (class_type))))
- {
- if (!CLASS_LOADED_P (TREE_TYPE (new_class_decl)) &&
- !CLASS_FROM_SOURCE_P (TREE_TYPE (new_class_decl)))
- load_class (TYPE_NAME (class_type), 0);
- return IDENTIFIER_CLASS_VALUE (TYPE_NAME (class_type));
- }
-#else
- new_name = TYPE_NAME (class_type);
- if ((new_class_decl = IDENTIFIER_CLASS_VALUE (new_name)) != NULL_TREE)
- {
- if (!CLASS_LOADED_P (TREE_TYPE (new_class_decl)) &&
- !CLASS_FROM_SOURCE_P (TREE_TYPE (new_class_decl)))
- load_class (new_name, 0);
- return IDENTIFIER_CLASS_VALUE (new_name);
- }
- else
+ if (!QUALIFIED_P (TYPE_NAME (class_type)))
{
- tree class = read_class (new_name);
- if (class != NULL_TREE)
+ tree package;
+ for (package = package_list; package; package = TREE_CHAIN (package))
{
- tree decl = IDENTIFIER_CLASS_VALUE (new_name);
- if (decl == NULL_TREE)
- decl = push_class (class, new_name);
- return decl;
+ tree new_qualified;
+
+ new_qualified = merge_qualified_name (TREE_PURPOSE (package),
+ original_name);
+ TYPE_NAME (class_type) = new_qualified;
+ new_class_decl = IDENTIFIER_CLASS_VALUE (TYPE_NAME (class_type));
+ if (!new_class_decl)
+ load_class (TYPE_NAME (class_type), 0);
+ new_class_decl = IDENTIFIER_CLASS_VALUE (TYPE_NAME (class_type));
+ if (new_class_decl)
+ {
+ if (!CLASS_LOADED_P (TREE_TYPE (new_class_decl)) &&
+ !CLASS_FROM_SOURCE_P (TREE_TYPE (new_class_decl)))
+ load_class (TYPE_NAME (class_type), 0);
+ return IDENTIFIER_CLASS_VALUE (TYPE_NAME (class_type));
+ }
}
}
-#endif
TYPE_NAME (class_type) = original_name;
/* 3- Check an other compilation unit that bears the name of type */
@@ -6079,7 +6116,6 @@ java_pre_expand_clinit (decl)
tree decl;
{
tree fbody = DECL_FUNCTION_BODY (decl);
- tree list;
int to_return = 1;
if (fbody != NULL_TREE)