summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/java/ChangeLog25
-rw-r--r--gcc/java/class.c2
-rw-r--r--gcc/java/expr.c4
-rw-r--r--gcc/java/jcf-parse.c2
-rw-r--r--gcc/java/parse.h1
-rw-r--r--gcc/java/parse.y156
-rw-r--r--gcc/java/typeck.c9
7 files changed, 137 insertions, 62 deletions
diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog
index e0238576790..f27b2bcdbc4 100644
--- a/gcc/java/ChangeLog
+++ b/gcc/java/ChangeLog
@@ -1,3 +1,28 @@
+1999-12-14 Alexandre Petit-Bianco <apbianco@cygnus.com>
+
+ * class.c (class_depth): Return -1 if the class doesn't load
+ properly.
+ * expr.c (can_widen_reference_to): Check for errors during depth
+ computation and return 0 accordingly.
+ * jcf-parse.c (parse_source_file): Call java_fix_constructors to
+ create default constructors and add an other error check.
+ * parse.h (java_fix_constructors): Prototyped.
+ * parse.y (java_pre_expand_clinit): Likewise.
+ (build_super_invocation): Re-prototyped to feature one argument.
+ (java_check_circular_reference): Directly use `current'.
+ (java_fix_constructors): New function.
+ (java_check_regular_methods): Don't create default constructors
+ here, but abort if none were found.
+ (java_complete_expand_methods): Pre-process <clinit> calling
+ java_pre_expand_clinit.
+ (java_pre_expand_clinit): New function.
+ (fix_constructors): build_super_invocation invoked with the
+ current method declaration as an argument.
+ (build_super_invocation): Use the context of the processed method
+ decl argument instead of current_class.
+ * typeck.c (lookup_java_method): Take WFLs in method names into
+ account.
+
1999-12-17 Tom Tromey <tromey@cygnus.com>
* gjavah.c (decode_signature_piece): Print "::" in JArray<>. This
diff --git a/gcc/java/class.c b/gcc/java/class.c
index 66941bd4967..e042c131931 100644
--- a/gcc/java/class.c
+++ b/gcc/java/class.c
@@ -403,6 +403,8 @@ class_depth (clas)
int depth = 0;
if (! CLASS_LOADED_P (clas))
load_class (clas, 1);
+ if (TYPE_SIZE (clas) == error_mark_node)
+ return -1;
while (clas != object_type_node)
{
depth++;
diff --git a/gcc/java/expr.c b/gcc/java/expr.c
index c7332a52b07..d789efb6292 100644
--- a/gcc/java/expr.c
+++ b/gcc/java/expr.c
@@ -386,6 +386,10 @@ can_widen_reference_to (source_type, target_type)
int source_depth = class_depth (source_type);
int target_depth = class_depth (target_type);
+ /* class_depth can return a negative depth if an error occurred */
+ if (source_depth < 0 || target_depth < 0)
+ return 0;
+
if (CLASS_INTERFACE (TYPE_NAME (target_type)))
{
/* target_type is OK if source_type or source_type ancestors
diff --git a/gcc/java/jcf-parse.c b/gcc/java/jcf-parse.c
index 2f7cc090aea..c1827893911 100644
--- a/gcc/java/jcf-parse.c
+++ b/gcc/java/jcf-parse.c
@@ -756,6 +756,8 @@ parse_source_file (file)
java_parse_abort_on_error ();
java_check_circular_reference (); /* Check on circular references */
java_parse_abort_on_error ();
+ java_fix_constructors (); /* Fix the constructors */
+ java_parse_abort_on_error ();
}
static int
diff --git a/gcc/java/parse.h b/gcc/java/parse.h
index 4d3b9ee98e3..2cfbedaf602 100644
--- a/gcc/java/parse.h
+++ b/gcc/java/parse.h
@@ -662,6 +662,7 @@ struct parser_ctxt {
void safe_layout_class PROTO ((tree));
void java_complete_class PROTO ((void));
void java_check_circular_reference PROTO ((void));
+void java_fix_constructors PROTO ((void));
void java_check_final PROTO ((void));
void java_layout_classes PROTO ((void));
tree java_method_add_stmt PROTO ((tree, tree));
diff --git a/gcc/java/parse.y b/gcc/java/parse.y
index cb1c43de45f..e5853a7061a 100644
--- a/gcc/java/parse.y
+++ b/gcc/java/parse.y
@@ -134,6 +134,7 @@ static tree register_incomplete_type PROTO ((int, tree, tree, tree));
static tree obtain_incomplete_type PROTO ((tree));
static tree java_complete_lhs PROTO ((tree));
static tree java_complete_tree PROTO ((tree));
+static int java_pre_expand_clinit PROTO ((tree));
static void java_complete_expand_method PROTO ((tree));
static int unresolved_type_p PROTO ((tree, tree *));
static void create_jdep_list PROTO ((struct parser_ctxt *));
@@ -216,7 +217,7 @@ static int check_thrown_exceptions_do PROTO ((tree));
static void purge_unchecked_exceptions PROTO ((tree));
static void check_throws_clauses PROTO ((tree, tree, tree));
static void finish_method_declaration PROTO ((tree));
-static tree build_super_invocation PROTO ((void));
+static tree build_super_invocation PROTO ((tree));
static int verify_constructor_circularity PROTO ((tree, tree));
static char *constructor_circularity_msg PROTO ((tree, tree));
static tree build_this_super_qualified_invocation PROTO ((int, tree, tree,
@@ -3985,7 +3986,7 @@ java_check_circular_reference ()
for (current = ctxp->class_list; current; current = TREE_CHAIN (current))
{
tree type = TREE_TYPE (current);
- if (CLASS_INTERFACE (TYPE_NAME (type)))
+ if (CLASS_INTERFACE (current))
{
/* Check all interfaces this class extends */
tree basetype_vec = TYPE_BINFO_BASETYPES (type);
@@ -4010,6 +4011,44 @@ java_check_circular_reference ()
}
}
+/* Fix the constructors. This will be called right after circular
+ references have been checked. It is necessary to fix constructors
+ early even if no code generation will take place for that class:
+ some generated constructor might be required by the class whose
+ compilation triggered this one to be simply loaded. */
+
+void
+java_fix_constructors ()
+{
+ tree current;
+
+ for (current = ctxp->class_list; current; current = TREE_CHAIN (current))
+ {
+ tree decl;
+ tree class_type = TREE_TYPE (current);
+ int saw_ctor = 0;
+
+ for (decl = TYPE_METHODS (class_type); decl; decl = TREE_CHAIN (decl))
+ {
+ if (DECL_CONSTRUCTOR_P (decl))
+ {
+ fix_constructors (decl);
+ saw_ctor = 1;
+ }
+ }
+
+ if (!saw_ctor)
+ {
+ int flags = (get_access_flags_from_decl (current) & ACC_PUBLIC ?
+ ACC_PUBLIC : 0);
+ decl = create_artificial_method (class_type, flags, void_type_node,
+ init_identifier_node,
+ end_params_node);
+ DECL_CONSTRUCTOR_P (decl) = 1;
+ }
+ }
+}
+
/* safe_layout_class just makes sure that we can load a class without
disrupting the current_class, input_file, lineno, etc, information
about the class processed currently. */
@@ -4916,24 +4955,7 @@ java_check_regular_methods (class_decl)
java_check_abstract_method_definitions (class_decl);
if (!saw_constructor)
- {
- /* No constructor seen, we craft one, at line 0. Since this
- operation takes place after we laid methods out
- (layout_class_methods), we prepare the its DECL
- appropriately. */
- int flags;
- tree decl;
-
- /* If the class is declared PUBLIC, the default constructor is
- PUBLIC otherwise it has default access implied by no access
- modifiers. */
- flags = (get_access_flags_from_decl (class_decl) & ACC_PUBLIC ?
- ACC_PUBLIC : 0);
- decl = create_artificial_method (class, flags, void_type_node,
- init_identifier_node, end_params_node);
- DECL_CONSTRUCTOR_P (decl) = 1;
- layout_class_method (TREE_TYPE (class_decl), NULL_TREE, decl, NULL_TREE);
- }
+ fatal ("No constructor found");
}
/* Return a non zero value if the `throws' clause of METHOD (if any)
@@ -5999,7 +6021,7 @@ java_complete_expand_methods ()
{
int is_interface;
tree class_type = CLASS_TO_HANDLE_TYPE (TREE_TYPE (current));
- tree decl;
+ tree decl, prev_decl;
current_class = TREE_TYPE (current);
is_interface = CLASS_INTERFACE (TYPE_NAME (current_class));
@@ -6008,42 +6030,21 @@ java_complete_expand_methods ()
init_outgoing_cpool ();
/* We want <clinit> (if any) to be processed first. */
- decl = tree_last (TYPE_METHODS (class_type));
- if (IS_CLINIT (decl))
- {
- tree fbody = DECL_FUNCTION_BODY (decl);
- tree list;
- if (fbody != NULL_TREE)
- {
- /* First check if we can ignore empty <clinit> */
- tree block_body = BLOCK_EXPR_BODY (fbody);
-
- current_this = NULL_TREE;
- current_function_decl = decl;
- if (block_body != NULL_TREE)
- {
- /* Prevent the use of `this' inside <clinit> */
- ctxp->explicit_constructor_p = 1;
+ for (prev_decl = NULL_TREE, decl = TYPE_METHODS (class_type);
+ decl; prev_decl= decl, decl = TREE_CHAIN (decl))
+ if (IS_CLINIT (decl))
+ {
+ if (!java_pre_expand_clinit (decl))
+ {
+ if (prev_decl)
+ TREE_CHAIN (prev_decl) = TREE_CHAIN (decl);
+ else
+ TYPE_METHODS (class_type) = TREE_CHAIN (decl);
+ }
+ break;
+ }
- block_body = java_complete_tree (block_body);
- ctxp->explicit_constructor_p = 0;
- BLOCK_EXPR_BODY (fbody) = block_body;
- if (block_body != NULL_TREE
- && TREE_CODE (block_body) == BLOCK
- && BLOCK_EXPR_BODY (block_body) == empty_stmt_node)
- decl = NULL_TREE;
- }
- }
- list = nreverse (TREE_CHAIN (nreverse (TYPE_METHODS (class_type))));
- if (decl != NULL_TREE)
- {
- TREE_CHAIN (decl) = list;
- TYPE_METHODS (class_type) = decl;
- }
- else
- TYPE_METHODS (class_type) = list;
- }
-
+ /* Now go on for regular business. */
for (decl = TYPE_METHODS (class_type); decl; decl = TREE_CHAIN (decl))
{
current_function_decl = decl;
@@ -6092,6 +6093,40 @@ java_complete_expand_methods ()
the list of the catch clauses of the currently analysed try block. */
static tree currently_caught_type_list;
+/* Complete and expand <clinit>. Return a non zero value if <clinit>
+ is worth keeping. */
+
+static int
+java_pre_expand_clinit (decl)
+ tree decl;
+{
+ tree fbody = DECL_FUNCTION_BODY (decl);
+ tree list;
+ int to_return = 1;
+
+ if (fbody != NULL_TREE)
+ {
+ /* First check if we can ignore empty <clinit> */
+ tree block_body = BLOCK_EXPR_BODY (fbody);
+
+ current_this = NULL_TREE;
+ current_function_decl = decl;
+ if (block_body != NULL_TREE)
+ {
+ /* Prevent the use of `this' inside <clinit> */
+ ctxp->explicit_constructor_p = 1;
+ block_body = java_complete_tree (block_body);
+ ctxp->explicit_constructor_p = 0;
+
+ BLOCK_EXPR_BODY (fbody) = block_body;
+ if (block_body != NULL_TREE && TREE_CODE (block_body) == BLOCK
+ && BLOCK_EXPR_BODY (block_body) == empty_stmt_node)
+ to_return = 0;
+ }
+ }
+ return to_return;
+}
+
/* Complete and expand a method. */
static void
@@ -6197,7 +6232,7 @@ fix_constructors (mdecl)
/* We don't generate a super constructor invocation if we're
compiling java.lang.Object. build_super_invocation takes care
of that. */
- compound = java_method_add_stmt (mdecl, build_super_invocation ());
+ compound = java_method_add_stmt (mdecl, build_super_invocation (mdecl));
end_artificial_method_body (mdecl);
}
@@ -6229,7 +6264,7 @@ fix_constructors (mdecl)
/* The constructor is missing an invocation of super() */
if (!found)
compound = add_stmt_to_compound (compound, NULL_TREE,
- build_super_invocation ());
+ build_super_invocation (mdecl));
/* Fix the constructor main block if we're adding extra stmts */
if (compound)
@@ -8923,9 +8958,10 @@ maybe_absorb_scoping_blocks ()
we're currently dealing with the class java.lang.Object. */
static tree
-build_super_invocation ()
+build_super_invocation (mdecl)
+ tree mdecl;
{
- if (current_class == object_type_node)
+ if (DECL_CONTEXT (mdecl) == object_type_node)
return empty_stmt_node;
else
{
diff --git a/gcc/java/typeck.c b/gcc/java/typeck.c
index 331de1c9fb6..213a3899fbc 100644
--- a/gcc/java/typeck.c
+++ b/gcc/java/typeck.c
@@ -755,7 +755,10 @@ lookup_java_method (searched_class, method_name, method_signature)
method != NULL_TREE; method = TREE_CHAIN (method))
{
tree method_sig = build_java_signature (TREE_TYPE (method));
- if (DECL_NAME (method) == method_name
+ tree name = DECL_NAME (method);
+
+ if ((TREE_CODE (name) == EXPR_WITH_FILE_LOCATION ?
+ EXPR_WFL_NODE (name) : name) == method_name
&& method_sig == method_signature)
return method;
}
@@ -788,8 +791,10 @@ lookup_java_method (searched_class, method_name, method_signature)
method != NULL_TREE; method = TREE_CHAIN (method))
{
tree method_sig = build_java_signature (TREE_TYPE (method));
+ tree name = DECL_NAME (method);
- if (DECL_NAME (method) == method_name
+ if ((TREE_CODE (name) == EXPR_WITH_FILE_LOCATION ?
+ EXPR_WFL_NODE (name) : name) == method_name
&& method_sig == method_signature)
return method;
}