Commit e920ebc9 by Alexandre Petit-Bianco Committed by Alexandre Petit-Bianco

class.c (class_depth): Return -1 if the class doesn't load properly.

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.

From-SVN: r31144
parent f0353e33
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> 1999-12-17 Tom Tromey <tromey@cygnus.com>
* gjavah.c (decode_signature_piece): Print "::" in JArray<>. This * gjavah.c (decode_signature_piece): Print "::" in JArray<>. This
......
...@@ -403,6 +403,8 @@ class_depth (clas) ...@@ -403,6 +403,8 @@ class_depth (clas)
int depth = 0; int depth = 0;
if (! CLASS_LOADED_P (clas)) if (! CLASS_LOADED_P (clas))
load_class (clas, 1); load_class (clas, 1);
if (TYPE_SIZE (clas) == error_mark_node)
return -1;
while (clas != object_type_node) while (clas != object_type_node)
{ {
depth++; depth++;
......
...@@ -386,6 +386,10 @@ can_widen_reference_to (source_type, target_type) ...@@ -386,6 +386,10 @@ can_widen_reference_to (source_type, target_type)
int source_depth = class_depth (source_type); int source_depth = class_depth (source_type);
int target_depth = class_depth (target_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))) if (CLASS_INTERFACE (TYPE_NAME (target_type)))
{ {
/* target_type is OK if source_type or source_type ancestors /* target_type is OK if source_type or source_type ancestors
......
...@@ -756,6 +756,8 @@ parse_source_file (file) ...@@ -756,6 +756,8 @@ parse_source_file (file)
java_parse_abort_on_error (); java_parse_abort_on_error ();
java_check_circular_reference (); /* Check on circular references */ java_check_circular_reference (); /* Check on circular references */
java_parse_abort_on_error (); java_parse_abort_on_error ();
java_fix_constructors (); /* Fix the constructors */
java_parse_abort_on_error ();
} }
static int static int
......
...@@ -662,6 +662,7 @@ struct parser_ctxt { ...@@ -662,6 +662,7 @@ struct parser_ctxt {
void safe_layout_class PROTO ((tree)); void safe_layout_class PROTO ((tree));
void java_complete_class PROTO ((void)); void java_complete_class PROTO ((void));
void java_check_circular_reference PROTO ((void)); void java_check_circular_reference PROTO ((void));
void java_fix_constructors PROTO ((void));
void java_check_final PROTO ((void)); void java_check_final PROTO ((void));
void java_layout_classes PROTO ((void)); void java_layout_classes PROTO ((void));
tree java_method_add_stmt PROTO ((tree, tree)); tree java_method_add_stmt PROTO ((tree, tree));
......
...@@ -134,6 +134,7 @@ static tree register_incomplete_type PROTO ((int, tree, tree, tree)); ...@@ -134,6 +134,7 @@ static tree register_incomplete_type PROTO ((int, tree, tree, tree));
static tree obtain_incomplete_type PROTO ((tree)); static tree obtain_incomplete_type PROTO ((tree));
static tree java_complete_lhs PROTO ((tree)); static tree java_complete_lhs PROTO ((tree));
static tree java_complete_tree 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 void java_complete_expand_method PROTO ((tree));
static int unresolved_type_p PROTO ((tree, tree *)); static int unresolved_type_p PROTO ((tree, tree *));
static void create_jdep_list PROTO ((struct parser_ctxt *)); static void create_jdep_list PROTO ((struct parser_ctxt *));
...@@ -216,7 +217,7 @@ static int check_thrown_exceptions_do PROTO ((tree)); ...@@ -216,7 +217,7 @@ static int check_thrown_exceptions_do PROTO ((tree));
static void purge_unchecked_exceptions PROTO ((tree)); static void purge_unchecked_exceptions PROTO ((tree));
static void check_throws_clauses PROTO ((tree, tree, tree)); static void check_throws_clauses PROTO ((tree, tree, tree));
static void finish_method_declaration PROTO ((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 int verify_constructor_circularity PROTO ((tree, tree));
static char *constructor_circularity_msg PROTO ((tree, tree)); static char *constructor_circularity_msg PROTO ((tree, tree));
static tree build_this_super_qualified_invocation PROTO ((int, tree, tree, static tree build_this_super_qualified_invocation PROTO ((int, tree, tree,
...@@ -3985,7 +3986,7 @@ java_check_circular_reference () ...@@ -3985,7 +3986,7 @@ java_check_circular_reference ()
for (current = ctxp->class_list; current; current = TREE_CHAIN (current)) for (current = ctxp->class_list; current; current = TREE_CHAIN (current))
{ {
tree type = TREE_TYPE (current); tree type = TREE_TYPE (current);
if (CLASS_INTERFACE (TYPE_NAME (type))) if (CLASS_INTERFACE (current))
{ {
/* Check all interfaces this class extends */ /* Check all interfaces this class extends */
tree basetype_vec = TYPE_BINFO_BASETYPES (type); tree basetype_vec = TYPE_BINFO_BASETYPES (type);
...@@ -4010,6 +4011,44 @@ java_check_circular_reference () ...@@ -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 /* safe_layout_class just makes sure that we can load a class without
disrupting the current_class, input_file, lineno, etc, information disrupting the current_class, input_file, lineno, etc, information
about the class processed currently. */ about the class processed currently. */
...@@ -4916,24 +4955,7 @@ java_check_regular_methods (class_decl) ...@@ -4916,24 +4955,7 @@ java_check_regular_methods (class_decl)
java_check_abstract_method_definitions (class_decl); java_check_abstract_method_definitions (class_decl);
if (!saw_constructor) if (!saw_constructor)
{ fatal ("No constructor found");
/* 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);
}
} }
/* Return a non zero value if the `throws' clause of METHOD (if any) /* Return a non zero value if the `throws' clause of METHOD (if any)
...@@ -5999,7 +6021,7 @@ java_complete_expand_methods () ...@@ -5999,7 +6021,7 @@ java_complete_expand_methods ()
{ {
int is_interface; int is_interface;
tree class_type = CLASS_TO_HANDLE_TYPE (TREE_TYPE (current)); tree class_type = CLASS_TO_HANDLE_TYPE (TREE_TYPE (current));
tree decl; tree decl, prev_decl;
current_class = TREE_TYPE (current); current_class = TREE_TYPE (current);
is_interface = CLASS_INTERFACE (TYPE_NAME (current_class)); is_interface = CLASS_INTERFACE (TYPE_NAME (current_class));
...@@ -6008,42 +6030,21 @@ java_complete_expand_methods () ...@@ -6008,42 +6030,21 @@ java_complete_expand_methods ()
init_outgoing_cpool (); init_outgoing_cpool ();
/* We want <clinit> (if any) to be processed first. */ /* We want <clinit> (if any) to be processed first. */
decl = tree_last (TYPE_METHODS (class_type)); for (prev_decl = NULL_TREE, decl = TYPE_METHODS (class_type);
if (IS_CLINIT (decl)) decl; prev_decl= decl, decl = TREE_CHAIN (decl))
{ if (IS_CLINIT (decl))
tree fbody = DECL_FUNCTION_BODY (decl); {
tree list; if (!java_pre_expand_clinit (decl))
if (fbody != NULL_TREE) {
{ if (prev_decl)
/* First check if we can ignore empty <clinit> */ TREE_CHAIN (prev_decl) = TREE_CHAIN (decl);
tree block_body = BLOCK_EXPR_BODY (fbody); else
TYPE_METHODS (class_type) = TREE_CHAIN (decl);
current_this = NULL_TREE; }
current_function_decl = decl; break;
if (block_body != NULL_TREE) }
{
/* Prevent the use of `this' inside <clinit> */
ctxp->explicit_constructor_p = 1;
block_body = java_complete_tree (block_body); /* Now go on for regular business. */
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;
}
for (decl = TYPE_METHODS (class_type); decl; decl = TREE_CHAIN (decl)) for (decl = TYPE_METHODS (class_type); decl; decl = TREE_CHAIN (decl))
{ {
current_function_decl = decl; current_function_decl = decl;
...@@ -6092,6 +6093,40 @@ java_complete_expand_methods () ...@@ -6092,6 +6093,40 @@ java_complete_expand_methods ()
the list of the catch clauses of the currently analysed try block. */ the list of the catch clauses of the currently analysed try block. */
static tree currently_caught_type_list; 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. */ /* Complete and expand a method. */
static void static void
...@@ -6197,7 +6232,7 @@ fix_constructors (mdecl) ...@@ -6197,7 +6232,7 @@ fix_constructors (mdecl)
/* We don't generate a super constructor invocation if we're /* We don't generate a super constructor invocation if we're
compiling java.lang.Object. build_super_invocation takes care compiling java.lang.Object. build_super_invocation takes care
of that. */ 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); end_artificial_method_body (mdecl);
} }
...@@ -6229,7 +6264,7 @@ fix_constructors (mdecl) ...@@ -6229,7 +6264,7 @@ fix_constructors (mdecl)
/* The constructor is missing an invocation of super() */ /* The constructor is missing an invocation of super() */
if (!found) if (!found)
compound = add_stmt_to_compound (compound, NULL_TREE, 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 */ /* Fix the constructor main block if we're adding extra stmts */
if (compound) if (compound)
...@@ -8923,9 +8958,10 @@ maybe_absorb_scoping_blocks () ...@@ -8923,9 +8958,10 @@ maybe_absorb_scoping_blocks ()
we're currently dealing with the class java.lang.Object. */ we're currently dealing with the class java.lang.Object. */
static tree 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; return empty_stmt_node;
else else
{ {
......
...@@ -755,7 +755,10 @@ lookup_java_method (searched_class, method_name, method_signature) ...@@ -755,7 +755,10 @@ lookup_java_method (searched_class, method_name, method_signature)
method != NULL_TREE; method = TREE_CHAIN (method)) method != NULL_TREE; method = TREE_CHAIN (method))
{ {
tree method_sig = build_java_signature (TREE_TYPE (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) && method_sig == method_signature)
return method; return method;
} }
...@@ -788,8 +791,10 @@ lookup_java_method (searched_class, method_name, method_signature) ...@@ -788,8 +791,10 @@ lookup_java_method (searched_class, method_name, method_signature)
method != NULL_TREE; method = TREE_CHAIN (method)) method != NULL_TREE; method = TREE_CHAIN (method))
{ {
tree method_sig = build_java_signature (TREE_TYPE (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) && method_sig == method_signature)
return method; return method;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment