This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Java: miscellaneous fixes.
- To: gcc-patches at gcc dot gnu dot org
- Subject: [PATCH] Java: miscellaneous fixes.
- From: Alexandre Petit-Bianco <apbianco at cygnus dot com>
- Date: Fri, 11 Aug 2000 14:56:03 -0700
- Reply-to: apbianco at redhat dot com
I'm checking in the following patch to fix:
- A bug in the code reading UTF-8 strings from bytecode,
- A bug in the bytecode generator when emitting `invokeinterface.'
- Several front-end problems: error resilience, method checking,
EH checks, declaration of field with innerclass array type, class name
clashes and local finals.
./A
2000-08-10 Alexandre Petit-Bianco <apbianco@cygnus.com>
* class.c (maybe_layout_super_class): Fixed indentation.
* java-tree.h (CLASS_METHOD_CHECKED_P): New macro.
(java_check_methods): New function declaration.
* jcf-parse.c (get_constant): Let `char_len' go up to 3. Use `str'
instead of `str_ptr'.
* jcf-write.c (generate_bytecode_insns): Emit number the of args
of a `invokeinterface' at the right time.
* parse.h (WFL_STRIP_BRACKET): New macro.
(SET_TYPE_FOR_RESOLUTION): Use it.
* parse.y (build_unresolved_array_type): Reuse `type_or_wfl.'
(check_class_interface_creation): Don't check for cross package
innerclass name clashes.
(method_header): Behave properly if MDECL is `error_mark_node.'
(method_declarator): Return `error_mark_node' if bogus current
class.
(resolve_class): Apply WFL_STRIP_BRACKET on `cl' if necessary.
(resolve_and_layout): New local `decl_type', set and used. Call
java_check_methods.
(java_check_methods): New method.
(java_layout_classes): Use it.
(resolve_qualified_expression_name): No EH check necessary in
access$<n>.
(java_complete_lhs): Use VAR_DECL's DECL_INITIAL when evaluating
`case' statement.
(patch_assignment): Set DECL_INITIAL on integral final local.
Index: class.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/java/class.c,v
retrieving revision 1.73
diff -u -p -r1.73 class.c
--- class.c 2000/08/02 17:01:13 1.73
+++ class.c 2000/08/11 21:31:47
@@ -1748,8 +1748,7 @@ maybe_layout_super_class (super_class, t
{
if (TREE_CODE (super_class) == RECORD_TYPE)
{
- if (!CLASS_LOADED_P (super_class)
- && CLASS_FROM_SOURCE_P (super_class))
+ if (!CLASS_LOADED_P (super_class) && CLASS_FROM_SOURCE_P (super_class))
safe_layout_class (super_class);
if (!CLASS_LOADED_P (super_class))
load_class (super_class, 1);
Index: java-tree.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/java/java-tree.h,v
retrieving revision 1.76
diff -u -p -r1.76 java-tree.h
--- java-tree.h 2000/07/21 00:01:43 1.76
+++ java-tree.h 2000/08/11 21:31:51
@@ -52,6 +52,7 @@ struct JCF;
QUALIFIED_P (in IDENTIFIER_NODE)
PRIMARY_P (in EXPR_WITH_FILE_LOCATION)
MODIFY_EXPR_FROM_INITIALIZATION_P (in MODIFY_EXPR)
+ CLASS_METHOD_CHECKED_P (in RECORD_TYPE)
3: IS_AN_IMPORT_ON_DEMAND_P (in IDENTIFIER_NODE)
RESOLVE_PACKAGE_NAME_P (in EXPR_WITH_FILE_LOCATION)
SWITCH_HAS_DEFAULT (in SWITCH_EXPR)
@@ -788,6 +789,7 @@ extern tree get_boehm_type_descriptor PA
extern unsigned long java_hash_hash_tree_node PARAMS ((hash_table_key));
extern boolean java_hash_compare_tree_node PARAMS ((hash_table_key,
hash_table_key));
+extern void java_check_methods PARAMS ((tree));
/* We use ARGS_SIZE_RTX to indicate that gcc/expr.h has been included
to declare `enum expand_modifier'. */
@@ -998,6 +1000,8 @@ extern tree *type_map;
/* True if EXPR (a MODIFY_EXPR in that case) is the result of variable
initialization during its declaration */
#define MODIFY_EXPR_FROM_INITIALIZATION_P(EXPR) TREE_LANG_FLAG_2 (EXPR)
+
+#define CLASS_METHOD_CHECKED_P(EXPR) TREE_LANG_FLAG_2 (EXPR)
/* True if EXPR (a WFL in that case) resolves into an expression name */
#define RESOLVE_EXPRESSION_NAME_P(WFL) TREE_LANG_FLAG_0 (WFL)
Index: jcf-parse.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/java/jcf-parse.c,v
retrieving revision 1.50
diff -u -p -r1.50 jcf-parse.c
--- jcf-parse.c 2000/07/27 11:13:51 1.50
+++ jcf-parse.c 2000/08/11 21:31:53
@@ -341,8 +341,8 @@ get_constant (jcf, index)
for (str_len = 0; i > 0; str_len++)
{
int char_len = UT8_CHAR_LENGTH (*str);
- if (char_len < 0 || char_len > 2 || char_len > i)
- fatal ("bad string constant");
+ if (char_len < 0 || char_len > 3 || char_len > i)
+ fatal ("bad string constant");
str += char_len;
i -= char_len;
}
@@ -368,7 +368,7 @@ get_constant (jcf, index)
char_value = (char_value << 6) | (*str++ & 0x3F);
break;
case 3:
- char_value = *str_ptr++ & 0x0F;
+ char_value = *str++ & 0x0F;
char_value = (char_value << 6) | (*str++ & 0x3F);
char_value = (char_value << 6) | (*str++ & 0x3F);
break;
Index: jcf-write.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/java/jcf-write.c,v
retrieving revision 1.65
diff -u -p -r1.65 jcf-write.c
--- jcf-write.c 2000/07/13 19:23:57 1.65
+++ jcf-write.c 2000/08/11 21:32:00
@@ -2561,9 +2561,13 @@ generate_bytecode_insns (exp, target, st
TREE_TYPE (TREE_TYPE (TREE_VALUE (TREE_OPERAND (exp, 1))));
}
index = find_methodref_index (&state->cpool, f);
- if (interface)
- DECL_CONTEXT (f) = saved_context;
OP2 (index);
+ if (interface)
+ {
+ DECL_CONTEXT (f) = saved_context;
+ OP1 (nargs);
+ OP1 (0);
+ }
f = TREE_TYPE (TREE_TYPE (f));
if (TREE_CODE (f) != VOID_TYPE)
{
@@ -2572,11 +2576,6 @@ generate_bytecode_insns (exp, target, st
emit_pop (size, state);
else
NOTE_PUSH (size);
- }
- if (interface)
- {
- OP1 (nargs);
- OP1 (0);
}
break;
}
Index: parse.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/java/parse.h,v
retrieving revision 1.56
diff -u -p -r1.56 parse.h
--- parse.h 2000/07/21 18:11:52 1.56
+++ parse.h 2000/08/11 21:32:03
@@ -535,27 +535,50 @@ typedef struct _jdeplist {
java.lang.Object. */
#define SET_TYPE_FOR_RESOLUTION(TYPE, SAVE, CHAIN) \
{ \
- tree returned_type; \
+ tree _returned_type; \
(CHAIN) = 0; \
if (TREE_TYPE (GET_CPC ()) == object_type_node \
- && TREE_CODE (TYPE) == EXPR_WITH_FILE_LOCATION \
+ && TREE_CODE (TYPE) == EXPR_WITH_FILE_LOCATION \
&& EXPR_WFL_NODE (TYPE) == unqualified_object_id_node) \
(TYPE) = object_type_node; \
else \
{ \
- if (unresolved_type_p (type, &returned_type)) \
+ if (unresolved_type_p (type, &_returned_type)) \
{ \
- if (returned_type) \
- (TYPE) = returned_type; \
+ if (_returned_type) \
+ (TYPE) = _returned_type; \
else \
{ \
- (SAVE) = (TYPE); \
+ tree _type; \
+ WFL_STRIP_BRACKET (_type, TYPE); \
+ (SAVE) = (_type); \
(TYPE) = obtain_incomplete_type (TYPE); \
CHAIN = 1; \
} \
} \
} \
}
+
+#define WFL_STRIP_BRACKET(TARGET, TYPE) \
+{ \
+ tree __type = (TYPE); \
+ if (TYPE && TREE_CODE (TYPE) == EXPR_WITH_FILE_LOCATION) \
+ { \
+ tree _node = EXPR_WFL_NODE (TYPE); \
+ const char *_ptr = IDENTIFIER_POINTER (_node); \
+ const char *_ref = _ptr; \
+ while (_ptr[0] == '[') \
+ _ptr++; \
+ if (_ref != _ptr) \
+ { \
+ tree _new = copy_node (TYPE); \
+ EXPR_WFL_NODE (_new) = get_identifier (_ptr); \
+ __type = _new; \
+ } \
+ } \
+ (TARGET) = __type; \
+}
+
/* Promote a type if it won't be registered as a patch */
#define PROMOTE_RECORD_IF_COMPLETE(TYPE, IS_INCOMPLETE) \
{ \
Index: parse.y
===================================================================
RCS file: /cvs/gcc/egcs/gcc/java/parse.y,v
retrieving revision 1.199
diff -u -p -r1.199 parse.y
--- parse.y 2000/08/08 03:33:36 1.199
+++ parse.y 2000/08/11 21:32:37
@@ -3265,10 +3265,8 @@ build_unresolved_array_type (type_or_wfl
IDENTIFIER_POINTER (EXPR_WFL_NODE (type_or_wfl)),
IDENTIFIER_LENGTH (EXPR_WFL_NODE (type_or_wfl)));
ptr = obstack_finish (&temporary_obstack);
- return build_expr_wfl (get_identifier (ptr),
- EXPR_WFL_FILENAME (type_or_wfl),
- EXPR_WFL_LINENO (type_or_wfl),
- EXPR_WFL_COLNO (type_or_wfl));
+ EXPR_WFL_NODE (type_or_wfl) = get_identifier (ptr);
+ return type_or_wfl;
}
static void
@@ -3303,7 +3301,8 @@ check_class_interface_creation (is_inter
- Can't be imported by a single type import
- Can't already exists in the package */
if (IS_A_SINGLE_IMPORT_CLASSFILE_NAME_P (raw_name)
- && (node = find_name_in_single_imports (raw_name)))
+ && (node = find_name_in_single_imports (raw_name))
+ && !CPC_INNER_P ())
{
parse_error_context
(cl, "%s name `%s' clashes with imported type `%s'",
@@ -4260,14 +4259,18 @@ method_header (flags, type, mdecl, throw
int flags;
tree type, mdecl, throws;
{
- tree meth = TREE_VALUE (mdecl);
- tree id = TREE_PURPOSE (mdecl);
tree type_wfl = NULL_TREE;
tree meth_name = NULL_TREE;
tree current, orig_arg, this_class = NULL;
+ tree id, meth;
int saved_lineno;
int constructor_ok = 0, must_chain;
int count;
+
+ if (mdecl == error_mark_node)
+ return error_mark_node;
+ meth = TREE_VALUE (mdecl);
+ id = TREE_PURPOSE (mdecl);
check_modifiers_consistency (flags);
@@ -4665,6 +4668,9 @@ method_declarator (id, list)
patch_stage = JDEP_NO_PATCH;
+ if (GET_CPC () == error_mark_node)
+ return error_mark_node;
+
/* If we're dealing with an inner class constructor, we hide the
this$<n> decl in the name field of its parameter declaration. We
also might have to hide the outer context local alias
@@ -5391,7 +5397,10 @@ resolve_class (enclosing, class_type, de
while (name[0] == '[')
name++;
if (base != name)
- TYPE_NAME (class_type) = get_identifier (name);
+ {
+ TYPE_NAME (class_type) = get_identifier (name);
+ WFL_STRIP_BRACKET (cl, cl);
+ }
/* 2- Resolve the bare type */
if (!(resolved_type_decl = do_resolve_class (enclosing, class_type,
@@ -5562,7 +5571,7 @@ resolve_and_layout (something, cl)
tree something;
tree cl;
{
- tree decl;
+ tree decl, decl_type;
/* Don't do that on the current class */
if (something == current_class)
@@ -5605,13 +5614,14 @@ resolve_and_layout (something, cl)
return NULL_TREE;
/* Resolve and layout if necessary */
- layout_class_methods (TREE_TYPE (decl));
- /* Check methods, but only once */
- if (CLASS_FROM_SOURCE_P (TREE_TYPE (decl))
- && !CLASS_LOADED_P (TREE_TYPE (decl)))
- CHECK_METHODS (decl);
- if (TREE_TYPE (decl) != current_class && !CLASS_LOADED_P (TREE_TYPE (decl)))
- safe_layout_class (TREE_TYPE (decl));
+ decl_type = TREE_TYPE (decl);
+ layout_class_methods (decl_type);
+ /* Check methods */
+ if (CLASS_FROM_SOURCE_P (decl_type))
+ java_check_methods (decl);
+ /* Layout the type if necessary */
+ if (decl_type != current_class && !CLASS_LOADED_P (decl_type))
+ safe_layout_class (decl_type);
return decl;
}
@@ -5957,6 +5967,23 @@ check_method_types_complete (decl)
return 1;
}
+/* Visible interface to check methods contained in CLASS_DECL */
+
+void
+java_check_methods (class_decl)
+ tree class_decl;
+{
+ if (CLASS_METHOD_CHECKED_P (TREE_TYPE (class_decl)))
+ return;
+
+ if (CLASS_INTERFACE (class_decl))
+ java_check_abstract_methods (class_decl);
+ else
+ java_check_regular_methods (class_decl);
+
+ CLASS_METHOD_CHECKED_P (TREE_TYPE (class_decl)) = 1;
+}
+
/* Check all the methods of CLASS_DECL. Methods are first completed
then checked according to regular method existance rules. If no
constructor for CLASS_DECL were encountered, then build its
@@ -7288,7 +7315,7 @@ java_layout_classes ()
/* Then check the methods of all parsed classes */
for (current = ctxp->gclass_list; current; current = TREE_CHAIN (current))
if (CLASS_FROM_SOURCE_P (TREE_TYPE (TREE_VALUE (current))))
- CHECK_METHODS (TREE_VALUE (current));
+ java_check_methods (TREE_VALUE (current));
java_parse_abort_on_error ();
for (current = ctxp->gclass_list; current; current = TREE_CHAIN (current))
@@ -8951,8 +8978,10 @@ resolve_qualified_expression_name (wfl,
instantiation using a primary qualified by a `new' */
RESTORE_THIS_AND_CURRENT_CLASS;
- /* EH check */
- if (location)
+ /* EH check. No check on access$<n> functions */
+ if (location
+ && !OUTER_FIELD_ACCESS_IDENTIFIER_P
+ (DECL_NAME (current_function_decl)))
check_thrown_exceptions (location, ret_decl);
/* If the previous call was static and this one is too,
@@ -10988,6 +11017,8 @@ java_complete_lhs (node)
/* Multiple instance of a case label bearing the same
value is checked during code generation. The case
expression is allright so far. */
+ if (TREE_CODE (cn) == VAR_DECL)
+ cn = DECL_INITIAL (cn);
TREE_OPERAND (node, 0) = cn;
TREE_TYPE (node) = void_type_node;
CAN_COMPLETE_NORMALLY (node) = 1;
@@ -12035,6 +12066,19 @@ patch_assignment (node, wfl_op1, wfl_op2
else
lvalue = build (COMPOUND_EXPR, lhs_type, check, lvalue);
}
+ }
+
+ /* Final locals can be used as case values in switch
+ statement. Prepare them for this eventuality. */
+ if (TREE_CODE (lvalue) == VAR_DECL
+ && LOCAL_FINAL (lvalue)
+ && TREE_CONSTANT (new_rhs)
+ && IDENTIFIER_LOCAL_VALUE (DECL_NAME (lvalue))
+ && JINTEGRAL_TYPE_P (TREE_TYPE (lvalue))
+ )
+ {
+ TREE_CONSTANT (lvalue) = 1;
+ DECL_INITIAL (lvalue) = new_rhs;
}
TREE_OPERAND (node, 0) = lvalue;