/* Source code parsing and tree node generation for the GNU compiler
for the Java(TM) language.
- Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
+ Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
Free Software Foundation, Inc.
Contributed by Alexandre Petit-Bianco (apbianco@cygnus.com)
#include "zipfile.h"
#include "convert.h"
#include "buffer.h"
-#include "xref.h"
#include "function.h"
#include "except.h"
#include "ggc.h"
int java_error_count;
/* Number of warning found so far. */
int java_warning_count;
-/* Tell when not to fold, when doing xrefs */
-int do_not_fold;
/* Cyclic inheritance report, as it can be set by layout_class */
const char *cyclic_inheritance_report;
/* List of things that were analyzed for which code will be generated */
struct parser_ctxt *ctxp_for_generation = NULL;
+struct parser_ctxt *ctxp_for_generation_last = NULL;
/* binop_lookup maps token to tree_code. It is used where binary
operations are involved and required by the parser. RDIV_EXPR
class_body:
OCB_TK CCB_TK
{
- /* Store the location of the `}' when doing xrefs */
- if (flag_emit_xref)
- DECL_END_SOURCE_LINE (GET_CPC ()) = $2.location;
$$ = GET_CPC ();
}
| OCB_TK class_body_declarations CCB_TK
{
- /* Store the location of the `}' when doing xrefs */
- if (flag_emit_xref)
- DECL_END_SOURCE_LINE (GET_CPC ()) = $3.location;
$$ = GET_CPC ();
}
;
CCB_TK
{
maybe_absorb_scoping_blocks ();
- /* Store the location of the `}' when doing xrefs */
- if (current_function_decl && flag_emit_xref)
- DECL_END_SOURCE_LINE (current_function_decl) = $1.location;
$$ = exit_block ();
if (!BLOCK_SUBBLOCKS ($$))
BLOCK_SUBBLOCKS ($$) = build_java_empty_stmt ();
do is to just update a list of class names. */
if (generate)
{
- ctxp->next = ctxp_for_generation;
- ctxp_for_generation = ctxp;
+ if (ctxp_for_generation_last == NULL)
+ ctxp_for_generation = ctxp;
+ else
+ ctxp_for_generation_last->next = ctxp;
+ ctxp->next = NULL;
+ ctxp_for_generation_last = ctxp;
}
/* And restore those of the previous context */
code_from_source, strlen (code_from_source));
remainder = obstack_finish (&temporary_obstack);
if (do_warning)
- warning ("%s.\n%s", msgid, remainder);
+ warning (0, "%s.\n%s", msgid, remainder);
else
error ("%s.\n%s", msgid, remainder);
break;
if (TREE_CODE (local_super) == POINTER_TYPE)
- local_super = do_resolve_class (NULL, local_super, NULL, NULL);
+ local_super = do_resolve_class (NULL, NULL, local_super, NULL, NULL);
else
local_super = TYPE_NAME (local_super);
acc = merge_qualified_name (acc,
EXPR_WFL_NODE (TREE_PURPOSE (qual)));
BUILD_PTR_FROM_NAME (ptr, acc);
- decl = do_resolve_class (NULL_TREE, ptr, NULL_TREE, cl);
+ decl = do_resolve_class (NULL_TREE, NULL_TREE, ptr, NULL_TREE, cl);
}
/* A NULL qual and a decl means that the search ended
DECL_SOURCE_LOCATION (decl) = EXPR_LOCATION (cl);
#else
DECL_SOURCE_FILE (decl) = EXPR_WFL_FILENAME (cl);
- /* If we're emitting 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);
+ DECL_SOURCE_LINE (decl) = EXPR_WFL_LINENO (cl);
#endif
CLASS_FROM_SOURCE_P (TREE_TYPE (decl)) = 1;
CLASS_PARSED_P (TREE_TYPE (decl)) = 1;
virtual function table in java.lang.object. */
TYPE_VFIELD (TREE_TYPE (decl)) = TYPE_VFIELD (object_type_node);
+ /* We keep the compilation unit imports in the class so that
+ they can be used later to resolve type dependencies that
+ aren't necessary to solve now. */
+ TYPE_IMPORT_LIST (TREE_TYPE (decl)) = ctxp->import_list;
+ TYPE_IMPORT_DEMAND_LIST (TREE_TYPE (decl)) = ctxp->import_demand_list;
+
/* Add the private this$<n> field, Replicate final locals still in
scope as private final fields mangled like val$<local_name>.
This does not occur for top level (static) inner classes. */
if (PURE_INNER_CLASS_DECL_P (decl))
add_inner_class_fields (decl, current_function_decl);
- /* If doing xref, store the location at which the inherited class
- (if any) was seen. */
- if (flag_emit_xref && super)
- DECL_INHERITED_SOURCE_LINE (decl) = EXPR_WFL_LINECOL (super);
-
/* Eventually sets the @deprecated tag flag */
CHECK_DEPRECATED (decl);
#ifdef USE_MAPPED_LOCATION
input_location = EXPR_LOCATION (cl);
#else
- if (flag_emit_xref)
- input_line = EXPR_WFL_LINECOL (cl);
- else
- input_line = EXPR_WFL_LINENO (cl);
+ input_line = EXPR_WFL_LINENO (cl);
#endif
field_decl = add_field (class_type, current_name, real_type, flags);
CHECK_DEPRECATED_NO_RESET (field_decl);
/* Eventually set the @deprecated tag flag */
CHECK_DEPRECATED (meth);
- /* If doing xref, store column and line number information instead
- of the line number only. */
- if (flag_emit_xref)
- {
-#ifdef USE_MAPPED_LOCATION
- DECL_SOURCE_LOCATION (meth) = EXPR_LOCATION (id);
-#else
- DECL_SOURCE_LINE (meth) = EXPR_WFL_LINECOL (id);
-#endif
- }
-
return meth;
}
exit_block ();
/* Merge last line of the function with first line, directly in the
function decl. It will be used to emit correct debug info. */
- if (!flag_emit_xref)
- DECL_FUNCTION_LAST_LINE (current_function_decl) = ctxp->last_ccb_indent1;
+ DECL_FUNCTION_LAST_LINE (current_function_decl) = ctxp->last_ccb_indent1;
/* Since function's argument's list are shared, reset the
ARG_FINAL_P parameter that might have been set on some of this
{
jdep *dep;
- /* We keep the compilation unit imports in the class so that
- they can be used later to resolve type dependencies that
- aren't necessary to solve now. */
- TYPE_IMPORT_LIST (TREE_TYPE (cclass)) = ctxp->import_list;
- TYPE_IMPORT_DEMAND_LIST (TREE_TYPE (cclass)) = ctxp->import_demand_list;
-
for (dep = CLASSD_FIRST (cclassd); dep; dep = JDEP_CHAIN (dep))
{
tree decl;
WFL_STRIP_BRACKET (cl, cl);
/* 2- Resolve the bare type */
- if (!(resolved_type_decl = do_resolve_class (enclosing, class_type,
+ if (!(resolved_type_decl = do_resolve_class (enclosing, NULL_TREE, class_type,
decl, cl)))
return NULL_TREE;
resolved_type = TREE_TYPE (resolved_type_decl);
and (but it doesn't really matter) qualify_and_find. */
tree
-do_resolve_class (tree enclosing, tree class_type, tree decl, tree cl)
+do_resolve_class (tree enclosing, tree import_type, tree class_type, tree decl,
+ tree cl)
{
tree new_class_decl = NULL_TREE, super = NULL_TREE;
tree saved_enclosing_type = enclosing ? TREE_TYPE (enclosing) : NULL_TREE;
if (split_qualified_name (&left, &right, TYPE_NAME (class_type)) == 0)
{
BUILD_PTR_FROM_NAME (left_type, left);
- q = do_resolve_class (enclosing, left_type, decl, cl);
+ q = do_resolve_class (enclosing, import_type, left_type, decl, cl);
if (q)
{
enclosing = q;
return new_class_decl;
}
- /* 1- Check for the type in single imports. This will change
- TYPE_NAME() if something relevant is found */
+ /* 1- Check for the type in single imports. Look at enclosing classes and,
+ if we're laying out a superclass, at the import list for the subclass.
+ This will change TYPE_NAME() if something relevant is found. */
+ if (import_type && TYPE_IMPORT_LIST (import_type))
+ find_in_imports (import_type, class_type);
find_in_imports (saved_enclosing_type, class_type);
/* 2- And check for the type in the current compilation unit */
/* 4- Check the import on demands. Don't allow bar.baz to be
imported from foo.* */
if (!QUALIFIED_P (TYPE_NAME (class_type)))
- if (find_in_imports_on_demand (saved_enclosing_type, class_type))
- return NULL_TREE;
+ {
+ if (import_type
+ && TYPE_IMPORT_DEMAND_LIST (import_type)
+ && find_in_imports_on_demand (import_type, class_type))
+ return NULL_TREE;
+ if (find_in_imports_on_demand (saved_enclosing_type, class_type))
+ return NULL_TREE;
+ }
/* If found in find_in_imports_on_demand, the type has already been
loaded. */
{
tree mthrows;
- /* Can't check these things with class loaded from bytecode. FIXME */
- if (!CLASS_FROM_SOURCE_P (DECL_CONTEXT (found)))
- return;
-
for (mthrows = DECL_FUNCTION_THROWS (method);
mthrows; mthrows = TREE_CHAIN (mthrows))
{
tree to_be_found = EXPR_WFL_NODE (TREE_PURPOSE (import));
char *original_name;
- original_name = xmemdup (IDENTIFIER_POINTER (to_be_found),
- IDENTIFIER_LENGTH (to_be_found),
- IDENTIFIER_LENGTH (to_be_found) + 1);
-
/* Don't load twice something already defined. */
if (IDENTIFIER_CLASS_VALUE (to_be_found))
continue;
+ original_name = xmemdup (IDENTIFIER_POINTER (to_be_found),
+ IDENTIFIER_LENGTH (to_be_found),
+ IDENTIFIER_LENGTH (to_be_found) + 1);
+
while (1)
{
tree left;
static void
find_in_imports (tree enclosing_type, tree class_type)
{
- tree import = (enclosing_type ? TYPE_IMPORT_LIST (enclosing_type) :
- ctxp->import_list);
+ tree import;
+ if (enclosing_type && TYPE_IMPORT_LIST (enclosing_type))
+ import = TYPE_IMPORT_LIST (enclosing_type);
+ else
+ import = ctxp->import_list;
+
while (import)
{
if (TREE_VALUE (import) == TYPE_NAME (class_type))
find_in_imports_on_demand (tree enclosing_type, tree class_type)
{
tree class_type_name = TYPE_NAME (class_type);
- tree import = (enclosing_type ? TYPE_IMPORT_DEMAND_LIST (enclosing_type) :
- ctxp->import_demand_list);
tree cl = NULL_TREE;
int seen_once = -1; /* -1 when not set, 1 if seen once, >1 otherwise. */
int to_return = -1; /* -1 when not set, 0 or 1 otherwise */
tree node;
+ tree import;
+
+ if (enclosing_type && TYPE_IMPORT_DEMAND_LIST (enclosing_type))
+ import = TYPE_IMPORT_DEMAND_LIST (enclosing_type);
+ else
+ import = ctxp->import_demand_list;
for (; import; import = TREE_CHAIN (import))
{
DECL_FINAL (decl) = final_p;
BLOCK_CHAIN_DECL (decl);
- /* If doing xreferencing, replace the line number with the WFL
- compound value */
-#ifdef USE_MAPPED_LOCATION
- if (flag_emit_xref)
- DECL_SOURCE_LOCATION (decl) = EXPR_LOCATION (wfl);
-#else
- if (flag_emit_xref)
- DECL_SOURCE_LINE (decl) = EXPR_WFL_LINECOL (wfl);
-#endif
-
/* Don't try to use an INIT statement when an error was found */
if (init && java_error_count)
init = NULL_TREE;
BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (fndecl)) = NULL_TREE;
if (BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (fndecl))
- && ! flag_emit_class_files
- && ! flag_emit_xref)
+ && ! flag_emit_class_files)
finish_method (fndecl);
current_function_decl = NULL_TREE;
{
tree current;
- do_not_fold = flag_emit_xref;
-
for (current = ctxp->class_list; current; current = TREE_CHAIN (current))
if (!INNER_CLASS_DECL_P (current))
java_complete_expand_class (current);
/* Now we analyze the method body and look for something that
isn't a MODIFY_EXPR */
- if (!IS_EMPTY_STMT (bbody) && analyze_clinit_body (type, bbody))
+ if (bbody && !IS_EMPTY_STMT (bbody) && analyze_clinit_body (type, bbody))
return 0;
/* Get rid of <clinit> in the class' list of methods */
htab_traverse (DECL_FUNCTION_INIT_TEST_TABLE (mdecl),
attach_init_test_initialization_flags, block_body);
- if (! flag_emit_xref && ! METHOD_NATIVE (mdecl))
+ if (! METHOD_NATIVE (mdecl))
{
check_for_initialization (block_body, mdecl);
an error_mark_node here. */
if (block_body != error_mark_node
&& (block_body == NULL_TREE || CAN_COMPLETE_NORMALLY (block_body))
- && TREE_CODE (TREE_TYPE (TREE_TYPE (mdecl))) != VOID_TYPE
- && !flag_emit_xref)
+ && TREE_CODE (TREE_TYPE (TREE_TYPE (mdecl))) != VOID_TYPE)
missing_return_error (current_function_decl);
/* See if we can get rid of <clinit> if MDECL happens to be <clinit> */
if (currently_caught_type_list)
abort ();
- /* Restore the copy of the list of exceptions if emitting xrefs. */
+ /* Restore the copy of the list of exceptions. */
DECL_FUNCTION_THROWS (mdecl) = exception_copy;
}
#endif
/* If we've found error at that stage, don't try to generate
- anything, unless we're emitting xrefs or checking the syntax only
+ anything, unless we're checking the syntax only
(but not using -fsyntax-only for the purpose of generating
- bytecode. */
- if (java_error_count && !flag_emit_xref
+ bytecode). */
+ if (java_error_count
&& (!flag_syntax_only && !flag_emit_class_files))
return;
output_class = current_class = TREE_TYPE (TREE_VALUE (current));
if (flag_emit_class_files)
write_classfile (current_class);
- if (flag_emit_xref)
- expand_xref (current_class);
else if (! flag_syntax_only)
java_expand_method_bodies (current_class);
}
/* Resolve the LENGTH field of an array here */
if (DECL_P (decl) && DECL_NAME (decl) == length_identifier_node
&& type_found && TYPE_ARRAY_P (type_found)
- && ! flag_emit_class_files && ! flag_emit_xref)
+ && ! flag_emit_class_files)
{
tree length = build_java_array_length_access (where_found);
field_ref = length;
if (!type_found)
type_found = DECL_CONTEXT (decl);
is_static = FIELD_STATIC (decl);
- field_ref = build_field_ref ((is_static && !flag_emit_xref?
+ field_ref = build_field_ref ((is_static ?
NULL_TREE : where_found),
type_found, DECL_NAME (decl));
if (field_ref == error_mark_node)
looks like `field.ref', where `field' is a static field in an
interface we implement. */
if (!flag_emit_class_files
- && !flag_emit_xref
&& TREE_CODE (where_found) == VAR_DECL
&& FIELD_STATIC (where_found))
{
if (TREE_CODE (resolved) == VAR_DECL && FIELD_STATIC (resolved)
&& FIELD_FINAL (resolved)
&& !inherits_from_p (DECL_CONTEXT (resolved), current_class)
- && !flag_emit_class_files && !flag_emit_xref)
+ && !flag_emit_class_files)
resolved = build_class_init (DECL_CONTEXT (resolved), resolved);
if (resolved == error_mark_node)
if (TREE_CODE (t) == POINTER_TYPE && !CLASS_LOADED_P (TREE_TYPE (t)))
resolve_and_layout (TREE_TYPE (t), NULL);
- if (flag_emit_class_files || flag_emit_xref)
+ if (flag_emit_class_files)
func = method;
else
{
tree c1, saved_new, new;
tree alloc_node;
- if (flag_emit_class_files || flag_emit_xref)
+ if (flag_emit_class_files)
{
TREE_TYPE (patch) = build_pointer_type (class);
return patch;
{
node = java_complete_lhs (node);
if (JDECL_P (node) && CLASS_FINAL_VARIABLE_P (node)
- && DECL_INITIAL (node) != NULL_TREE
- && !flag_emit_xref)
+ && DECL_INITIAL (node) != NULL_TREE)
{
tree value = fold_constant_for_init (node, node);
if (value != NULL_TREE)
&& DECL_INITIAL (cn))
cn = fold_constant_for_init (DECL_INITIAL (cn), cn);
- if (!TREE_CONSTANT (cn) && !flag_emit_xref)
+ if (!TREE_CONSTANT (cn))
{
EXPR_WFL_LINECOL (wfl_operator) = EXPR_WFL_LINECOL (node);
parse_error_context (node, "Constant expression required");
if (!EXPR_WFL_NODE (node) /* Or a PRIMARY flag ? */
|| TREE_CODE (EXPR_WFL_NODE (node)) == IDENTIFIER_NODE)
{
- tree wfl = node;
node = resolve_expression_name (node, NULL);
if (node == error_mark_node)
return node;
- /* Keep line number information somewhere were it doesn't
- disrupt the completion process. */
- if (flag_emit_xref && TREE_CODE (node) != CALL_EXPR)
- {
- EXPR_WFL_NODE (wfl) = TREE_OPERAND (node, 1);
- TREE_OPERAND (node, 1) = wfl;
- }
CAN_COMPLETE_NORMALLY (node) = 1;
}
else
case INSTANCEOF_EXPR:
wfl_op1 = TREE_OPERAND (node, 0);
COMPLETE_CHECK_OP_0 (node);
- if (flag_emit_xref)
- {
- TREE_TYPE (node) = boolean_type_node;
- return node;
- }
return patch_binop (node, wfl_op1, TREE_OPERAND (node, 1));
case UNARY_PLUS_EXPR:
TREE_OPERAND (node, 0) = java_complete_tree (wfl_op1);
if (TREE_OPERAND (node, 0) == error_mark_node)
return error_mark_node;
- if (!flag_emit_class_files && !flag_emit_xref)
+ if (!flag_emit_class_files)
TREE_OPERAND (node, 0) = save_expr (TREE_OPERAND (node, 0));
/* The same applies to wfl_op2 */
wfl_op2 = TREE_OPERAND (node, 1);
TREE_OPERAND (node, 1) = java_complete_tree (wfl_op2);
if (TREE_OPERAND (node, 1) == error_mark_node)
return error_mark_node;
- if (!flag_emit_class_files && !flag_emit_xref)
+ if (!flag_emit_class_files)
TREE_OPERAND (node, 1) = save_expr (TREE_OPERAND (node, 1));
return patch_array_ref (node);
/* 10.10: Array Store Exception runtime check */
if (!flag_emit_class_files
- && !flag_emit_xref
&& lvalue_from_array
&& JREFERENCE_TYPE_P (TYPE_ARRAY_ELEMENT (lhs_type)))
{
/* Types have to be either references or the null type. If
they're references, it must be possible to convert either
type to the other by casting conversion. */
- else if (op1 == null_pointer_node || op2 == null_pointer_node
+ else if ((op1 == null_pointer_node && op2 == null_pointer_node)
+ || (op1 == null_pointer_node && JREFERENCE_TYPE_P (op2_type))
+ || (JREFERENCE_TYPE_P (op1_type) && op2 == null_pointer_node)
|| (JREFERENCE_TYPE_P (op1_type) && JREFERENCE_TYPE_P (op2_type)
&& (valid_ref_assignconv_cast_p (op1_type, op2_type, 1)
|| valid_ref_assignconv_cast_p (op2_type,
TREE_TYPE (node) = prom_type;
TREE_SIDE_EFFECTS (node) = TREE_SIDE_EFFECTS (op1) | TREE_SIDE_EFFECTS (op2);
- if (flag_emit_xref)
- return node;
-
/* fold does not respect side-effect order as required for Java but not C.
* Also, it sometimes create SAVE_EXPRs which are bad when emitting
* bytecode.
tree result;
int side_effects = TREE_SIDE_EFFECTS (op1) | TREE_SIDE_EFFECTS (op2);
- if (flag_emit_xref)
- return build2 (PLUS_EXPR, string_type_node, op1, op2);
-
/* Try to do some static optimization */
if ((result = string_constant_concatenation (op1, op2)))
return result;
/* OP1 is no longer the last node holding a crafted StringBuffer */
IS_CRAFTED_STRING_BUFFER_P (op1) = 0;
/* Create a node for `{new...,xxx}.append (op2)' */
- if (op2)
- op1 = make_qualified_primary (op1, BUILD_APPEND (op2), 0);
+ op1 = make_qualified_primary (op1, BUILD_APPEND (op2), 0);
}
/* Mark the last node holding a crafted StringBuffer */
array_type = TYPE_ARRAY_ELEMENT (array_type);
- if (flag_emit_class_files || flag_emit_xref)
+ if (flag_emit_class_files)
{
TREE_OPERAND (node, 0) = array;
TREE_OPERAND (node, 1) = index;
return error_mark_node;
}
- if (flag_emit_xref)
- {
- TREE_OPERAND (node, 0) = expr;
- TREE_OPERAND (node, 1) = java_complete_tree (block);
- CAN_COMPLETE_NORMALLY (node) = 1;
- return node;
- }
-
/* Generate a try-finally for the synchronized statement, except
that the handler that catches all throw exception calls
_Jv_MonitorExit and then rethrow the exception.
return error_mark_node;
}
- if (! flag_emit_class_files && ! flag_emit_xref)
+ if (! flag_emit_class_files)
BUILD_THROW (node, expr);
- /* If doing xrefs, keep the location where the `throw' was seen. */
- if (flag_emit_xref)
- EXPR_WFL_LINECOL (node) = EXPR_WFL_LINECOL (wfl_op1);
return node;
}
tree t1, t2, patched;
int error_found = 0;
- /* Operands of ?: might be StringBuffers crafted as a result of a
- string concatenation. Obtain a descent operand here. */
+ /* The condition and operands of ?: might be StringBuffers crafted
+ as a result of a string concatenation. Obtain decent ones here. */
+ if ((patched = patch_string (cond)))
+ TREE_OPERAND (node, 0) = cond = patched;
if ((patched = patch_string (op1)))
TREE_OPERAND (node, 1) = op1 = patched;
if ((patched = patch_string (op2)))
maybe_build_class_init_for_field (tree decl, tree expr)
{
tree clas = DECL_CONTEXT (decl);
- if (flag_emit_class_files || flag_emit_xref)
+ if (flag_emit_class_files)
return expr;
if (TREE_CODE (decl) == VAR_DECL && FIELD_STATIC (decl)