/* Local function prototypes */
static char *java_accstring_lookup (int);
+static const char *accessibility_string (int);
static void classitf_redefinition_error (const char *,tree, tree, tree);
static void variable_redefinition_error (tree, tree, tree, int);
static tree create_class (int, tree, tree, tree);
static int find_in_imports_on_demand (tree, tree);
static void find_in_imports (tree, tree);
static void check_inner_class_access (tree, tree, tree);
-static int check_pkg_class_access (tree, tree, bool);
+static int check_pkg_class_access (tree, tree, bool, tree);
static void register_package (tree);
static tree resolve_package (tree, tree *, tree *);
static tree resolve_class (tree, tree, tree, tree);
static tree maybe_generate_pre_expand_clinit (tree);
static int analyze_clinit_body (tree, tree);
static int maybe_yank_clinit (tree);
+static void start_complete_expand_method (tree);
static void java_complete_expand_method (tree);
static void java_expand_method_bodies (tree);
static int unresolved_type_p (tree, tree *);
static int class_in_current_package (tree);
static tree build_if_else_statement (int, tree, tree, tree);
static tree patch_if_else_statement (tree);
-static tree add_stmt_to_compound (tree, tree, tree);
static tree add_stmt_to_block (tree, tree, tree);
static tree patch_exit_expr (tree);
static tree build_labeled_block (int, tree);
static tree maybe_make_nested_class_name (tree);
static int make_nested_class_name (tree);
-static void set_nested_class_simple_name_value (tree, int);
static void link_nested_class_to_enclosing (void);
static tree resolve_inner_class (htab_t, tree, tree *, tree *, tree);
static tree find_as_inner_class (tree, tree, tree);
| constructor_declaration
| block /* Added, JDK1.1, instance initializer */
{
- if ($1 != empty_stmt_node)
+ if (!IS_EMPTY_STMT ($1))
{
TREE_CHAIN ($1) = CPC_INSTANCE_INITIALIZER_STMT (ctxp);
SET_CPC_INSTANCE_INITIALIZER_STMT (ctxp, $1);
addition (super invocation and field initialization) */
block_begin constructor_block_end
{
- BLOCK_EXPR_BODY ($2) = empty_stmt_node;
+ BLOCK_EXPR_BODY ($2) = build_java_empty_stmt ();
$$ = $2;
}
| block_begin explicit_constructor_invocation constructor_block_end
EXPR_WFL_ADD_COL ($1.location, 1);
$$ = exit_block ();
if (!BLOCK_SUBBLOCKS ($$))
- BLOCK_SUBBLOCKS ($$) = empty_stmt_node;
+ BLOCK_SUBBLOCKS ($$) = build_java_empty_stmt ();
}
;
EXPR_WFL_SET_LINECOL (wfl_operator, input_line, -1);
parse_warning_context (wfl_operator, "An empty declaration is a deprecated feature that should not be used");
}
- $$ = empty_stmt_node;
+ $$ = build_java_empty_stmt ();
}
;
switch_expression:
SWITCH_TK OP_TK expression CP_TK
{
- $$ = build (SWITCH_EXPR, NULL_TREE, $3, NULL_TREE);
+ $$ = build (SWITCH_EXPR, NULL_TREE, $3, NULL_TREE, NULL_TREE);
EXPR_WFL_LINECOL ($$) = $2.location;
}
| SWITCH_TK error
$$ = finish_for_loop (0, NULL_TREE, $4, $6);
/* We have not condition, so we get rid of the EXIT_EXPR */
LOOP_EXPR_BODY_CONDITION_EXPR (LOOP_EXPR_BODY ($$), 0) =
- empty_stmt_node;
+ build_java_empty_stmt ();
}
| for_begin SC_TK error
{yyerror ("Invalid control expression"); RECOVER;}
$$ = finish_for_loop (0, NULL_TREE, $4, $6);
/* We have not condition, so we get rid of the EXIT_EXPR */
LOOP_EXPR_BODY_CONDITION_EXPR (LOOP_EXPR_BODY ($$), 0) =
- empty_stmt_node;
+ build_java_empty_stmt ();
}
;
}
;
for_init: /* Can be empty */
- { $$ = empty_stmt_node; }
+ { $$ = build_java_empty_stmt (); }
| statement_expression_list
{
/* Init statement recorded within the previously
;
for_update: /* Can be empty */
- {$$ = empty_stmt_node;}
+ {$$ = build_java_empty_stmt ();}
| statement_expression_list
{ $$ = build_debugable_stmt (BUILD_LOCATION (), $1); }
;
declare_local_variables (0, TREE_VALUE ($3),
build_tree_list
(TREE_PURPOSE ($3), init));
- $$ = build1 (CATCH_EXPR, NULL_TREE, ccpb);
+ $$ = build1 (JAVA_CATCH_EXPR, NULL_TREE, ccpb);
EXPR_WFL_LINECOL ($$) = $1.location;
}
else
{
sorry (": `%s' JDK1.1(TM) feature", msg);
java_error_count++;
- return empty_stmt_node;
+ return build_java_empty_stmt ();
}
static int do_warning = 0;
{
parse_error_context
(wfl, "Can't access %s field `%s.%s' from `%s'",
- java_accstring_lookup (get_access_flags_from_decl (decl)),
+ accessibility_string (get_access_flags_from_decl (decl)),
GET_TYPE_NAME (DECL_CONTEXT (decl)),
IDENTIFIER_POINTER (DECL_NAME (decl)),
IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (current_class))));
#undef COPY_RETURN
}
+/* Returns a string denoting the accessibility of a class or a member as
+ indicated by FLAGS. We need a separate function from
+ java_accstring_lookup, as the latter can return spurious "static", etc.
+ if package-private access is defined (in which case none of the
+ relevant access control bits in FLAGS is set). */
+
+static const char *
+accessibility_string (int flags)
+{
+ if (flags & ACC_PRIVATE) return "private";
+ if (flags & ACC_PROTECTED) return "protected";
+ if (flags & ACC_PUBLIC) return "public";
+
+ return "package-private";
+}
+
/* Issuing error messages upon redefinition of classes, interfaces or
variables. */
return (!qual && enclosing ? enclosing : NULL_TREE);
}
-/* Reach all inner classes and tie their unqualified name to a
- DECL. */
-
-static void
-set_nested_class_simple_name_value (tree outer, int set)
-{
- tree l;
-
- for (l = DECL_INNER_CLASS_LIST (outer); l; l = TREE_CHAIN (l))
- IDENTIFIER_GLOBAL_VALUE (TREE_VALUE (l)) = (set ?
- TREE_PURPOSE (l) : NULL_TREE);
-}
-
static void
link_nested_class_to_enclosing (void)
{
/* Create a new decl if DECL is NULL, otherwise fix it */
decl = maybe_create_class_interface_decl (decl, raw_name, q_name, id);
+ /* Interfaces are always abstract. */
+ flags |= ACC_ABSTRACT;
+
+ /* Inner interfaces are always static. */
+ if (INNER_CLASS_DECL_P (decl))
+ flags |= ACC_STATIC;
+
/* Set super info and mark the class a complete */
set_super_info (ACC_INTERFACE | flags, TREE_TYPE (decl),
object_type_node, ctxp->interface_number);
/* If SUPER exists, use it, otherwise use Object */
if (super)
{
- /* Can't extend java.lang.Object */
+ /* java.lang.Object can't extend anything. */
if (TREE_TYPE (IDENTIFIER_CLASS_VALUE (class_id)) == object_type_node)
{
- parse_error_context (id, "Can't extend `java.lang.Object'");
+ parse_error_context (id, "`java.lang.Object' can't extend anything");
return NULL_TREE;
}
CLASS_COMPLETE_P (decl) = 1;
add_superinterfaces (decl, interfaces);
+ /* TYPE_VFIELD' is a compiler-generated field used to point to
+ virtual function tables. In gcj, every class has a common base
+ virtual function table in java.lang.object. */
+ TYPE_VFIELD (TREE_TYPE (decl)) = TYPE_VFIELD (object_type_node);
+
/* Add the private this$<n> field, Replicate final locals still in
scope as private final fields mangled like val$<local_name>.
This doesn't not occur for top level (static) inner classes. */
if (duplicate_declaration_error_p (current_name, real_type, cl))
continue;
- /* Set lineno to the line the field was found and create a
+ /* Set input_line to the line the field was found and create a
declaration for it. Eventually sets the @deprecated tag flag. */
if (flag_emit_xref)
input_line = EXPR_WFL_LINECOL (cl);
static int
unresolved_type_p (tree wfl, tree *returned)
-
{
if (TREE_CODE (wfl) == EXPR_WITH_FILE_LOCATION)
{
access rules (6.6.1). */
if (! INNER_CLASS_P (super_type)
&& check_pkg_class_access (DECL_NAME (super_decl),
- lookup_cl (this_decl), true))
+ NULL_TREE, true, this_decl))
return 1;
SOURCE_FRONTEND_DEBUG (("Completing interface %s with %s",
/* Check top-level class scope. Inner classes are subject to member access
rules (6.6.1). */
if (! INNER_CLASS_P (super_type)
- && (check_pkg_class_access (DECL_NAME (super_decl), wfl, true)))
+ && (check_pkg_class_access (DECL_NAME (super_decl), wfl, true, NULL_TREE)))
return 1;
SOURCE_FRONTEND_DEBUG (("Completing class %s with %s",
JDEP_MISC (new) = NULL_TREE;
/* For some dependencies, set the enclosing class of the current
class to be the enclosing context */
- if ((kind == JDEP_INTERFACE || kind == JDEP_ANONYMOUS)
+ if ((kind == JDEP_INTERFACE || kind == JDEP_ANONYMOUS || kind == JDEP_SUPER)
&& GET_ENCLOSING_CPC ())
JDEP_ENCLOSING (new) = TREE_VALUE (GET_ENCLOSING_CPC ());
- else if (kind == JDEP_SUPER)
- JDEP_ENCLOSING (new) = (GET_ENCLOSING_CPC () ?
- TREE_VALUE (GET_ENCLOSING_CPC ()) : NULL_TREE);
else
JDEP_ENCLOSING (new) = GET_CPC ();
JDEP_GET_PATCH (new) = (tree *)NULL;
}
/* 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, input_line, etc, information
about the class processed currently. */
void
if (!decl)
complete_class_report_errors (dep);
- else if (PURE_INNER_CLASS_DECL_P (decl))
+ else if (INNER_CLASS_DECL_P (decl))
{
tree inner = TREE_TYPE (decl);
if (! CLASS_LOADED_P (inner))
/* 2- And check for the type in the current compilation unit */
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)))
+ if (!CLASS_LOADED_P (TREE_TYPE (new_class_decl)))
load_class (TYPE_NAME (class_type), 0);
return IDENTIFIER_CLASS_VALUE (TYPE_NAME (class_type));
}
by the caller. */
if (cl)
{
- if (check_pkg_class_access (TYPE_NAME (class_type), cl, true))
+ if (check_pkg_class_access (TYPE_NAME (class_type), cl, true, NULL_TREE))
return NULL_TREE;
}
load_class (new_qualified, 0);
if ((new_class_decl = IDENTIFIER_CLASS_VALUE (new_qualified)))
{
- if (!CLASS_LOADED_P (TREE_TYPE (new_class_decl)) &&
- !CLASS_FROM_SOURCE_P (TREE_TYPE (new_class_decl)))
- load_class (new_qualified, 0);
+ if (!CLASS_LOADED_P (TREE_TYPE (new_class_decl)))
+ load_class (TREE_TYPE (new_class_decl), 0);
TYPE_NAME (class_type) = new_qualified;
return IDENTIFIER_CLASS_VALUE (new_qualified);
}
Also, multiple inheritance with conflicting throws
clauses is fine in the absence of a concrete
implementation. */
- if (method != NULL_TREE && !METHOD_ABSTRACT (method))
+ if (method != NULL_TREE && !METHOD_ABSTRACT (method)
+ && !METHOD_INVISIBLE (iface_method))
{
tree method_wfl = DECL_FUNCTION_WFL (method);
check_throws_clauses (method, method_wfl, iface_method);
QUALIFIED_P (to_be_found) = 1;
load_class (to_be_found, 0);
error_found =
- check_pkg_class_access (to_be_found, TREE_PURPOSE (import), true);
+ check_pkg_class_access (to_be_found, TREE_PURPOSE (import), true, NULL_TREE);
/* We found it, we can bail out */
if (IDENTIFIER_CLASS_VALUE (to_be_found))
if (! (node = maybe_get_identifier (id_name)))
continue;
- /* Setup lineno so that it refers to the line of the import (in
+ /* Setup input_line so that it refers to the line of the import (in
case we parse a class file and encounter errors */
input_line = EXPR_WFL_LINENO (TREE_PURPOSE (import));
access_check = -1;
/* If there is no DECL set for the class or if the class isn't
loaded and not seen in source yet, then load */
- if (!decl || (!CLASS_LOADED_P (TREE_TYPE (decl))
- && !CLASS_FROM_SOURCE_P (TREE_TYPE (decl))))
+ if (!decl || ! CLASS_LOADED_P (TREE_TYPE (decl)))
{
load_class (node, 0);
decl = IDENTIFIER_CLASS_VALUE (node);
}
if (decl && ! INNER_CLASS_P (TREE_TYPE (decl)))
access_check = check_pkg_class_access (node, TREE_PURPOSE (import),
- false);
+ false, NULL_TREE);
else
/* 6.6.1: Inner classes are subject to member access rules. */
access_check = 0;
/* Accessibility check for top-level classes. If CLASS_NAME is in a
foreign package, it must be PUBLIC. Return 0 if no access
violations were found, 1 otherwise. If VERBOSE is true and an error
- was found, it is reported and accounted for. */
+ was found, it is reported and accounted for. If CL is NULL then
+ look it up with THIS_DECL. */
static int
-check_pkg_class_access (tree class_name, tree cl, bool verbose)
+check_pkg_class_access (tree class_name, tree cl, bool verbose, tree this_decl)
{
tree type;
if (verbose)
parse_error_context
- (cl, "Can't access %s `%s'. Only public classes and interfaces in other packages can be accessed",
+ (cl == NULL ? lookup_cl (this_decl): cl,
+ "Can't access %s `%s'. Only public classes and interfaces in other packages can be accessed",
(CLASS_INTERFACE (TYPE_NAME (type)) ? "interface" : "class"),
IDENTIFIER_POINTER (class_name));
return 1;
if (init && java_error_count)
init = NULL_TREE;
+ /* Remember it if this is an initialized-upon-declaration final
+ variable. */
+ if (init && final_p)
+ {
+ DECL_LOCAL_FINAL_IUD (decl) = 1;
+ }
+
/* Add the initialization function to the current function's code */
if (init)
{
/* Turn function bodies with only a NOP expr null, so they don't get
generated at all and we won't get warnings when using the -W
-Wall flags. */
- if (BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (fndecl)) == empty_stmt_node)
+ if (IS_EMPTY_STMT (BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (fndecl))))
BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (fndecl)) = NULL_TREE;
- /* We've generated all the trees for this function, and it has been
- patched. Dump it to a file if the user requested it. */
- dump_java_tree (TDI_original, fndecl);
-
- /* Defer expanding the method until cgraph analysis is complete. */
- if (DECL_SAVED_TREE (fndecl))
- cgraph_finalize_function (fndecl, false);
+ if (BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (fndecl))
+ && ! flag_emit_class_files
+ && ! flag_emit_xref)
+ finish_method (fndecl);
current_function_decl = NULL_TREE;
java_parser_context_restore_global ();
+ current_function_decl = NULL_TREE;
}
/* Record EXPR in the current function block. Complements compound
return c;
}
-/* Add STMT to EXISTING if possible, otherwise create a new
- COMPOUND_EXPR and add STMT to it. */
+/* Lays out the methods for the classes seen so far. */
-static tree
-add_stmt_to_compound (tree existing, tree type, tree stmt)
-{
- if (existing)
- return build (COMPOUND_EXPR, type, existing, stmt);
- else
- return stmt;
-}
-
-void java_layout_seen_class_methods (void)
+void
+java_layout_seen_class_methods (void)
{
tree previous_list = all_class_list;
tree end = NULL_TREE;
{
for (current = previous_list;
current != end; current = TREE_CHAIN (current))
- layout_class_methods (TREE_TYPE (TREE_VALUE (current)));
+ {
+ tree cls = TREE_TYPE (TREE_VALUE (current));
+
+ if (! CLASS_LOADED_P (cls))
+ load_class (cls, 0);
+
+ layout_class_methods (cls);
+ }
+
+ /* Note that new classes might have been added while laying out
+ methods, changing the value of all_class_list. */
if (previous_list != all_class_list)
{
{
tree inner_list;
- set_nested_class_simple_name_value (outer, 1); /* Set */
-
/* We need to go after all inner classes and start expanding them,
starting with most nested ones. We have to do that because nested
classes might add functions to outer classes */
java_complete_expand_class (TREE_PURPOSE (inner_list));
java_complete_expand_methods (outer);
- set_nested_class_simple_name_value (outer, 0); /* Reset */
}
/* Expand methods registered in CLASS_DECL. The general idea is that
/* We build the assignment expression that will initialize the
field to its value. There are strict rules on static
initializers (8.5). FIXME */
- if (TREE_CODE (stmt) != BLOCK && stmt != empty_stmt_node)
+ if (TREE_CODE (stmt) != BLOCK && !IS_EMPTY_STMT (stmt))
stmt = build_debugable_stmt (EXPR_WFL_LINECOL (stmt), stmt);
java_method_add_stmt (mdecl, stmt);
}
bbody = BLOCK_EXPR_BODY (bbody);
else
return 0;
- if (bbody && ! flag_emit_class_files && bbody != empty_stmt_node)
+ if (bbody && ! flag_emit_class_files && !IS_EMPTY_STMT (bbody))
return 0;
type = DECL_CONTEXT (mdecl);
/* Now we analyze the method body and look for something that
isn't a MODIFY_EXPR */
- if (bbody != empty_stmt_node && analyze_clinit_body (type, bbody))
+ if (!IS_EMPTY_STMT (bbody) && analyze_clinit_body (type, bbody))
return 0;
/* Get rid of <clinit> in the class' list of methods */
for (decl = TYPE_METHODS (class); decl; decl = TREE_CHAIN (decl))
{
tree block;
- tree body;
if (! DECL_FUNCTION_BODY (decl))
continue;
block = BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (decl));
- if (TREE_CODE (block) != BLOCK)
- abort ();
-
- /* Save the function body for inlining. */
+ /* Save the function body for gimplify and inlining. */
DECL_SAVED_TREE (decl) = block;
- body = BLOCK_EXPR_BODY (block);
-
- if (TREE_TYPE (body) == NULL_TREE)
- abort ();
-
/* It's time to assign the variable flagging static class
initialization based on which classes invoked static methods
are definitely initializing. This should be flagged. */
}
}
- /* Prepend class initialization to static methods. */
- if (METHOD_STATIC (decl) && ! METHOD_PRIVATE (decl)
- && ! flag_emit_class_files
- && ! DECL_CLINIT_P (decl)
- && ! CLASS_INTERFACE (TYPE_NAME (class)))
- {
- tree init = build (CALL_EXPR, void_type_node,
- build_address_of (soft_initclass_node),
- build_tree_list (NULL_TREE,
- build_class_ref (class)),
- NULL_TREE);
- TREE_SIDE_EFFECTS (init) = 1;
- body = build (COMPOUND_EXPR, TREE_TYPE (body), init, body);
- BLOCK_EXPR_BODY (block) = body;
- }
-
- /* Wrap synchronized method bodies in a monitorenter
- plus monitorexit cleanup. */
- if (METHOD_SYNCHRONIZED (decl) && ! flag_emit_class_files)
- {
- tree enter, exit, lock;
- if (METHOD_STATIC (decl))
- lock = build_class_ref (class);
- else
- lock = DECL_ARGUMENTS (decl);
- BUILD_MONITOR_ENTER (enter, lock);
- BUILD_MONITOR_EXIT (exit, lock);
-
- body = build (COMPOUND_EXPR, void_type_node,
- enter,
- build (TRY_FINALLY_EXPR, void_type_node, body, exit));
- BLOCK_EXPR_BODY (block) = body;
- }
-
- /* Expand the the function body. */
+ /* Expand the function body. */
source_end_java_method ();
}
}
{
compound = add_stmt_to_compound (compound, NULL_TREE,
TREE_OPERAND (found_call, 0));
- TREE_OPERAND (found_call, 0) = empty_stmt_node;
+ TREE_OPERAND (found_call, 0) = build_java_empty_stmt ();
}
DECL_INIT_CALLS_THIS (mdecl) = invokes_this;
make_qualified_name (tree left, tree right, int location)
{
#ifdef USE_COMPONENT_REF
- tree node = build (COMPONENT_REF, NULL_TREE, left, right);
+ tree node = build (COMPONENT_REF, NULL_TREE, left, right, NULL_TREE);
EXPR_WFL_LINECOL (node) = location;
return node;
#else
{
int is_static = 0;
tree field_ref;
- tree decl, where_found, type_found;
+ tree decl = NULL_TREE, where_found, type_found;
if (resolve_qualified_expression_name (qual_wfl, &decl,
&where_found, &type_found))
tree list;
*where_found = decl;
+ check_pkg_class_access (DECL_NAME (decl), qual_wfl, true, NULL);
+
/* We want to be absolutely sure that the class is laid
out. We're going to search something inside it. */
*type_found = type = TREE_TYPE (decl);
decl = QUAL_RESOLUTION (q);
/* Sneak preview. If next we see a `new', we're facing a
- qualification with resulted in a type being selected
- instead of a field. Report the error */
+ qualification which resulted in a type being selected
+ instead of a field. Report the error. */
if(TREE_CHAIN (q)
&& TREE_CODE (TREE_PURPOSE (TREE_CHAIN (q))) == NEW_CLASS_EXPR)
{
return 1;
}
- if (not_accessible_p (TREE_TYPE (decl), decl, type, 0))
- {
- parse_error_context
- (qual_wfl, "Can't access %s class '%s' from '%s'",
- java_accstring_lookup (get_access_flags_from_decl (decl)),
- IDENTIFIER_POINTER (DECL_NAME (decl)),
- IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (current_class))));
- return 1;
- }
+ check_pkg_class_access (DECL_NAME (decl), qual_wfl, true, NULL);
+
check_deprecation (qual_wfl, decl);
type = TREE_TYPE (decl);
return 1;
}
- /* Default access are permitted only when occurring within the
- package in which the type (REFERENCE) is declared. In other words,
- REFERENCE is defined in the current package */
- if (ctxp->package)
- return !class_in_current_package (reference);
-
- /* Otherwise, access is granted */
- return 0;
+ /* Default access is permitted only when occurring from within the
+ package in which the context (MEMBER) is declared. */
+ return !class_in_current_package (DECL_CONTEXT (member));
}
/* Test deprecated decl access. */
{
const char *const fct_name = IDENTIFIER_POINTER (DECL_NAME (list));
const char *const access =
- java_accstring_lookup (get_access_flags_from_decl (list));
+ accessibility_string (get_access_flags_from_decl (list));
const char *const klass =
IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (DECL_CONTEXT (list))));
const char *const refklass =
(class_has_finalize_method (class) ? alloc_object_node
: alloc_no_finalizer_node);
new = build (CALL_EXPR, promote_type (class),
- build_address_of (alloc_node),
- tree_cons (NULL_TREE, build_class_ref (class),
- build_tree_list (NULL_TREE,
- size_in_bytes (class))),
- NULL_TREE);
+ build_address_of (alloc_node),
+ build_tree_list (NULL_TREE, build_class_ref (class)),
+ NULL_TREE);
saved_new = save_expr (new);
c1 = build_tree_list (NULL_TREE, saved_new);
TREE_CHAIN (c1) = TREE_OPERAND (original_call, 1);
/* We have to call force_evaluation_order now because creating a
COMPOUND_EXPR wraps the arg list in a way that makes it
unrecognizable by force_evaluation_order later. Yuk. */
- tree save = save_expr (force_evaluation_order (patch));
+ tree save = force_evaluation_order (patch);
tree type = TREE_TYPE (patch);
- patch = build (COMPOUND_EXPR, type, save, empty_stmt_node);
+ patch = build (COMPOUND_EXPR, type, save, build_java_empty_stmt ());
list = tree_cons (method, patch,
DECL_FUNCTION_STATIC_METHOD_INVOCATION_COMPOUND (fndecl));
search_not_done++;
*htab_find_slot (searched_classes, class, INSERT) = class;
- if (!CLASS_LOADED_P (class) && !CLASS_FROM_SOURCE_P (class))
+ if (!CLASS_LOADED_P (class))
{
load_class (class, 1);
safe_layout_class (class);
long blocks. */
ptr = &BLOCK_EXPR_BODY (node);
while (TREE_CODE (*ptr) == COMPOUND_EXPR
- && TREE_OPERAND (*ptr, 1) != empty_stmt_node)
+ && !IS_EMPTY_STMT (TREE_OPERAND (*ptr, 1)))
{
tree cur = java_complete_tree (TREE_OPERAND (*ptr, 0));
tree *next = &TREE_OPERAND (*ptr, 1);
TREE_OPERAND (*ptr, 0) = cur;
- if (cur == empty_stmt_node)
+ if (IS_EMPTY_STMT (cur))
{
/* Optimization; makes it easier to detect empty bodies.
Most useful for <clinit> with all-constant initializer. */
case TRY_FINALLY_EXPR:
COMPLETE_CHECK_OP_0 (node);
COMPLETE_CHECK_OP_1 (node);
- /* Reduce try/finally nodes with an empty try block. */
- if (TREE_OPERAND (node, 0) == empty_stmt_node
- || BLOCK_EMPTY_P (TREE_OPERAND (node, 0)))
+ if (IS_EMPTY_STMT (TREE_OPERAND (node, 0)))
+ /* Reduce try/finally nodes with an empty try block. */
return TREE_OPERAND (node, 1);
- /* Likewise for an empty finally block. */
- if (TREE_OPERAND (node, 1) == empty_stmt_node
- || BLOCK_EMPTY_P (TREE_OPERAND (node, 1)))
+ if (IS_EMPTY_STMT (TREE_OPERAND (node, 1)))
+ /* Likewise for an empty finally block. */
return TREE_OPERAND (node, 0);
CAN_COMPLETE_NORMALLY (node)
= (CAN_COMPLETE_NORMALLY (TREE_OPERAND (node, 0))
TREE_TYPE (node) = void_type_node;
POP_LABELED_BLOCK ();
- if (LABELED_BLOCK_BODY (node) == empty_stmt_node)
+ if (IS_EMPTY_STMT (LABELED_BLOCK_BODY (node)))
{
LABELED_BLOCK_BODY (node) = NULL_TREE;
CAN_COMPLETE_NORMALLY (node) = 1;
TREE_OPERAND (cn, 1));
}
/* Accept final locals too. */
- else if (TREE_CODE (cn) == VAR_DECL && DECL_FINAL (cn))
+ else if (TREE_CODE (cn) == VAR_DECL && DECL_FINAL (cn)
+ && DECL_INITIAL (cn))
cn = fold_constant_for_init (DECL_INITIAL (cn), cn);
if (!TREE_CONSTANT (cn) && !flag_emit_xref)
wfl_op2 = TREE_OPERAND (node, 1);
TREE_OPERAND (node, 0) = nn =
java_complete_tree (TREE_OPERAND (node, 0));
- if (wfl_op2 == empty_stmt_node)
+ if (IS_EMPTY_STMT (wfl_op2))
CAN_COMPLETE_NORMALLY (node) = CAN_COMPLETE_NORMALLY (nn);
else
{
EXPR_WFL_NODE (node) = body;
TREE_SIDE_EFFECTS (node) = TREE_SIDE_EFFECTS (body);
CAN_COMPLETE_NORMALLY (node) = CAN_COMPLETE_NORMALLY (body);
- if (body == empty_stmt_node || TREE_CONSTANT (body))
+ if (IS_EMPTY_STMT (body) || TREE_CONSTANT (body))
{
/* Makes it easier to constant fold, detect empty bodies. */
return body;
else
DECL_INITIAL (nn) = TREE_OPERAND (node, 1);
DECL_FIELD_FINAL_IUD (nn) = 1;
- return empty_stmt_node;
+ return build_java_empty_stmt ();
}
}
if (! flag_emit_class_files)
flag = 1;
continue;
}
- /* If have a string literal that we haven't transformed yet or a
- crafted string buffer, as a result of use of the the String
+ /* If we have a string literal that we haven't transformed yet or a
+ crafted string buffer, as a result of the use of the String
`+' operator. Build `parm.toString()' and expand it. */
if ((temp = patch_string (parm)))
parm = temp;
static tree
build_expr_block (tree body, tree decls)
-
{
tree node = make_node (BLOCK);
BLOCK_EXPR_DECLS (node) = decls;
return wfl;
}
-/* Build a super() constructor invocation. Returns empty_stmt_node if
+/* Build a super() constructor invocation. Returns an empty statement if
we're currently dealing with the class java.lang.Object. */
static tree
build_super_invocation (tree mdecl)
{
if (DECL_CONTEXT (mdecl) == object_type_node)
- return empty_stmt_node;
+ return build_java_empty_stmt ();
else
{
tree super_wfl = build_wfl_node (super_identifier_node);
)
{
TREE_CONSTANT (lvalue) = 1;
+ TREE_INVARIANT (lvalue) = 1;
DECL_INITIAL (lvalue) = new_rhs;
}
case INDIRECT_REF:
case COMPONENT_REF:
/* Transform a = foo.bar
- into a = { int tmp; tmp = foo.bar; tmp; ).
+ into a = ({int tmp; tmp = foo.bar;}).
We need to ensure that if a read from memory fails
because of a NullPointerException, a destination variable
will remain unchanged. An explicit temporary does what
DECL_CONTEXT (tmp) = current_function_decl;
TREE_TYPE (block) = TREE_TYPE (new_rhs);
BLOCK_VARS (block) = tmp;
- BLOCK_EXPR_BODY (block)
- = build (COMPOUND_EXPR, TREE_TYPE (new_rhs), assignment, tmp);
+ BLOCK_EXPR_BODY (block) = assignment;
TREE_SIDE_EFFECTS (block) = 1;
new_rhs = block;
}
{
parse_warning_context (wfl_operator, "Evaluating this expression will result in an arithmetic exception being thrown");
TREE_CONSTANT (node) = 0;
+ TREE_INVARIANT (node) = 0;
}
/* Change the division operator if necessary */
location = alloc_name_constant (CONSTANT_String, node);
node = build_ref_from_constant_pool (location);
}
- TREE_TYPE (node) = string_ptr_type_node;
TREE_CONSTANT (node) = 1;
+ TREE_INVARIANT (node) = 1;
+
+ /* ??? Guessing that the class file code can't handle casts. */
+ if (! flag_emit_class_files)
+ node = convert (string_ptr_type_node, node);
+ else
+ TREE_TYPE (node) = string_ptr_type_node;
+
return node;
}
&& !JPRIMITIVE_TYPE_P (class_name)
&& !(TREE_CODE (class_name) == VOID_TYPE))
{
+ tree cpc_list = GET_CPC_LIST();
+ tree cpc = cpc_list;
tree target_class;
- if (CLASS_INTERFACE (TYPE_NAME (this_class)))
+ /* For inner classes, add a 'class$' method to their outermost
+ context, creating it if necessary. */
+
+ while (GET_NEXT_ENCLOSING_CPC(cpc))
+ cpc = GET_NEXT_ENCLOSING_CPC(cpc);
+ class_decl = TREE_VALUE (cpc);
+
+ target_class = TREE_TYPE (class_decl);
+
+ if (CLASS_INTERFACE (TYPE_NAME (target_class)))
{
/* For interfaces, adding a static 'class$' method directly
is illegal. So create an inner class to contain the new
method. Empirically this matches the behavior of javac. */
- tree t = build_wfl_node (DECL_NAME (TYPE_NAME (object_type_node)));
- tree inner = create_anonymous_class (0, t);
+ tree t, inner;
+ /* We want the generated inner class inside the outermost class. */
+ GET_CPC_LIST() = cpc;
+ t = build_wfl_node (DECL_NAME (TYPE_NAME (object_type_node)));
+ inner = create_anonymous_class (0, t);
target_class = TREE_TYPE (inner);
end_class_declaration (1);
- }
- else
- {
- /* For inner classes, add a 'class$' method to their outermost
- context, creating it if necessary. */
- while (INNER_CLASS_DECL_P (class_decl))
- class_decl = DECL_CONTEXT (class_decl);
- target_class = TREE_TYPE (class_decl);
+ GET_CPC_LIST() = cpc_list;
}
if (TYPE_DOT_CLASS (target_class) == NULL_TREE)
static tree
build_array_ref (int location, tree array, tree index)
{
- tree node = build (ARRAY_REF, NULL_TREE, array, index);
+ tree node = build (ARRAY_REF, NULL_TREE, array, index, NULL_TREE, NULL_TREE);
EXPR_WFL_LINECOL (node) = location;
return node;
}
TREE_TYPE (init) = TREE_TYPE (TREE_CHAIN (TREE_CHAIN (TYPE_FIELDS (type))));
TREE_TYPE (node) = promote_type (type);
TREE_CONSTANT (init) = all_constant;
+ TREE_INVARIANT (init) = all_constant;
TREE_CONSTANT (node) = all_constant;
+ TREE_INVARIANT (node) = all_constant;
return node;
}
{
tree node;
if (!else_body)
- else_body = empty_stmt_node;
+ else_body = build_java_empty_stmt ();
node = build (COND_EXPR, NULL_TREE, expression, if_body, else_body);
EXPR_WFL_LINECOL (node) = location;
node = build_debugable_stmt (location, node);
return error_mark_node;
}
- if (TREE_CODE (expression) == INTEGER_CST)
- {
- if (integer_zerop (expression))
- node = TREE_OPERAND (node, 2);
- else
- node = TREE_OPERAND (node, 1);
- if (CAN_COMPLETE_NORMALLY (node) != can_complete_normally)
- {
- node = build (COMPOUND_EXPR, void_type_node, node, empty_stmt_node);
- CAN_COMPLETE_NORMALLY (node) = can_complete_normally;
- }
- return node;
- }
TREE_TYPE (node) = void_type_node;
TREE_SIDE_EFFECTS (node) = 1;
CAN_COMPLETE_NORMALLY (node) = can_complete_normally;
second = (reversed ? condition : body);
return
build (COMPOUND_EXPR, NULL_TREE,
- build (COMPOUND_EXPR, NULL_TREE, first, second), empty_stmt_node);
+ build (COMPOUND_EXPR, NULL_TREE, first, second),
+ build_java_empty_stmt ());
}
/* Install CONDITION (if any) and loop BODY (using REVERSED to tell
this because the (current interpretation of the) JLS requires
that the update expression be considered reachable even if the
for loop's body doesn't complete normally. */
- if (update != NULL_TREE && update != empty_stmt_node)
+ if (update != NULL_TREE && !IS_EMPTY_STMT (update))
{
tree up2 = update;
if (TREE_CODE (up2) == EXPR_WITH_FILE_LOCATION)
up2 = EXPR_WFL_NODE (up2);
/* It is possible for the update expression to be an
EXPR_WFL_NODE wrapping nothing. */
- if (up2 != NULL_TREE && up2 != empty_stmt_node)
+ if (up2 != NULL_TREE && !IS_EMPTY_STMT (up2))
{
/* Try to detect constraint violations. These would be
programming errors somewhere. */
tree node;
tree klass = GET_CPC ();
+ if (! enable_assertions (klass))
+ {
+ condition = build (TRUTH_ANDIF_EXPR, NULL_TREE,
+ boolean_false_node, condition);
+ if (value == NULL_TREE)
+ value = build_java_empty_stmt ();
+ return build_if_else_statement (location, condition,
+ value, NULL_TREE);
+ }
+
if (! CLASS_USES_ASSERTIONS (klass))
{
tree field, classdollar, id, call;
MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (field);
FIELD_SYNTHETIC (field) = 1;
- if (!TYPE_DOT_CLASS (class_type))
- build_dot_class_method (class_type);
- classdollar = build_dot_class_method_invocation (class_type, class_type);
+ classdollar = build_incomplete_class_ref (location, class_type);
/* Call CLASS.desiredAssertionStatus(). */
id = build_wfl_node (get_identifier ("desiredAssertionStatus"));
/* Add the catch statements */
add_stmt_to_block (catch_block, NULL_TREE, catch_stmts);
- /* Now we can build a CATCH_EXPR */
- catch_block = build1 (CATCH_EXPR, NULL_TREE, catch_block);
+ /* Now we can build a JAVA_CATCH_EXPR */
+ catch_block = build1 (JAVA_CATCH_EXPR, NULL_TREE, catch_block);
return build_try_statement (location, try_block, catch_block);
}
int unreachable;
/* At this point, the structure of the catch clause is
- CATCH_EXPR (catch node)
+ JAVA_CATCH_EXPR (catch node)
BLOCK (with the decl of the parameter)
COMPOUND_EXPR
MODIFY_EXPR (assignment of the catch parameter)