This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Java: bytecode compiler and source parser fixes.
- To: gcc-patches at gcc dot gnu dot org
- Subject: [PATCH] Java: bytecode compiler and source parser fixes.
- From: Alexandre Petit-Bianco <apbianco at cygnus dot com>
- Date: Tue, 10 Oct 2000 10:47:21 -0700
- Reply-to: apbianco at redhat dot com
I'm about to check this in. The patch to decl.c fixes problems
witnessed with the bytecode compiler in some corner cases. The patch
to parse.y cleans up the code a bit and provide better error messages
with declarations like `int x[3]', which are wrong in Java.
./A
2000-10-07 Alexandre Petit-Bianco <apbianco@cygnus.com>
Patch contributed by Corey Minyard.
* decl.c (check_local_named_variable): New function.
(tree check_local_unnamed_variable): Likewise.
(find_local_variable): Splitted. Call check_local_{un}named_variable.
2000-08-11 Alexandre Petit-Bianco <apbianco@cygnus.com>
* parse.y (variable_declarator_id:): Better error message.
(expression_statement:): Use YYNOT_TWICE.
(cast_expression:): Likewise.
(assignment:): Likewise.
Index: decl.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/java/decl.c,v
retrieving revision 1.74
diff -u -p -r1.74 decl.c
--- decl.c 2000/10/05 07:17:34 1.74
+++ decl.c 2000/10/10 17:34:27
@@ -50,6 +50,8 @@ static struct binding_level *make_bindin
static boolean emit_init_test_initialization PARAMS ((struct hash_entry *,
hash_table_key));
static tree create_primitive_vtable PARAMS ((const char *));
+static tree check_local_named_variable PARAMS ((tree, tree, int, int *));
+static tree check_local_unnamed_variable PARAMS ((tree, tree, tree));
/* Set to non-zero value in order to emit class initilization code
before static field references. */
@@ -140,6 +142,58 @@ push_jvm_slot (index, decl)
return decl;
}
+/* Find out if 'decl' passed in fits the defined PC location better than
+ 'best'. Return decl if it does, return best if it doesn't. If decl
+ is returned, then updated is set to true. */
+
+static tree
+check_local_named_variable (best, decl, pc, updated)
+ tree best;
+ tree decl;
+ int pc;
+ int *updated;
+{
+ if (pc >= DECL_LOCAL_START_PC (decl)
+ && pc < DECL_LOCAL_END_PC (decl))
+ {
+ if (best == NULL_TREE
+ || (DECL_LOCAL_START_PC (decl) > DECL_LOCAL_START_PC (best)
+ && DECL_LOCAL_END_PC (decl) < DECL_LOCAL_END_PC (best)))
+ {
+ *updated = 1;
+ return decl;
+ }
+ }
+
+ return best;
+}
+
+/* Find the best declaration based upon type. If 'decl' fits 'type' better
+ than 'best', return 'decl'. Otherwise return 'best'. */
+
+static tree
+check_local_unnamed_variable (best, decl, type)
+ tree best;
+ tree decl;
+ tree type;
+{
+ if (TREE_TYPE (decl) == type
+ || (TREE_CODE (TREE_TYPE (decl)) == TREE_CODE (type)
+ && TYPE_PRECISION (TREE_TYPE (decl)) <= 32
+ && TYPE_PRECISION (type) <= 32
+ && TREE_CODE (type) != POINTER_TYPE)
+ || (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE
+ && type == ptr_type_node))
+ {
+ if (best == NULL_TREE
+ || (TREE_TYPE (decl) == type && TREE_TYPE (best) != type))
+ return decl;
+ }
+
+ return best;
+}
+
+
/* Find a VAR_DECL (or PARM_DECL) at local index INDEX that has type TYPE,
that is valid at PC (or -1 if any pc).
If there is no existing matching decl, allocate one. */
@@ -152,32 +206,41 @@ find_local_variable (index, type, pc)
{
tree decl = TREE_VEC_ELT (decl_map, index);
tree best = NULL_TREE;
+ int found_scoped_var = 0;
+ /* Scan through every declaration that has been created in this slot. */
while (decl != NULL_TREE)
{
- int in_range;
- in_range = pc < 0
- || (pc >= DECL_LOCAL_START_PC (decl)
- && pc < DECL_LOCAL_END_PC (decl));
-
- if ((TREE_TYPE (decl) == type
- || (TREE_CODE (TREE_TYPE (decl)) == TREE_CODE (type)
- && TYPE_PRECISION (TREE_TYPE (decl)) <= 32
- && TYPE_PRECISION (type) <= 32
- && TREE_CODE (type) != POINTER_TYPE)
- || (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE
- && type == ptr_type_node))
- && in_range)
+ /* Variables created in give_name_to_locals() have a name and have
+ a specified scope, so we can handle them specifically. We want
+ to use the specific decls created for those so they are assigned
+ the right variables in the debugging information. */
+ if (DECL_NAME (decl) != NULL_TREE)
{
- if (best == NULL_TREE
- || (DECL_LOCAL_START_PC (decl) > DECL_LOCAL_START_PC (best)
- && DECL_LOCAL_END_PC (decl) < DECL_LOCAL_START_PC (best)))
- best = decl;
- }
+ /* This is a variable we have a name for, so it has a scope
+ supplied in the class file. But it only matters when we
+ actually have a PC to use. If pc<0, then we are asking
+ for a stack slot and this decl won't be one of those. */
+ if (pc >= 0)
+ best = check_local_named_variable (best, decl, pc,
+ &found_scoped_var);
+ }
+ /* We scan for type information unless we found a variable in the
+ proper scope already. */
+ else if (!found_scoped_var)
+ {
+ /* If we don't have scoping information for a variable, we use
+ a different method to look it up. */
+ best = check_local_unnamed_variable (best, decl, type);
+ }
+
decl = DECL_LOCAL_SLOT_CHAIN (decl);
}
+
if (best != NULL_TREE)
return best;
+
+ /* If we don't find a match, create one with the type passed in. */
return push_jvm_slot (index, build_decl (VAR_DECL, NULL_TREE, type));
}
Index: parse.y
===================================================================
RCS file: /cvs/gcc/egcs/gcc/java/parse.y,v
retrieving revision 1.214
diff -u -p -r1.214 parse.y
--- parse.y 2000/10/05 07:17:34 1.214
+++ parse.y 2000/10/10 17:35:04
@@ -971,7 +971,15 @@ variable_declarator_id:
| identifier error
{yyerror ("Invalid declaration"); DRECOVER(vdi);}
| variable_declarator_id OSB_TK error
- {yyerror ("']' expected"); DRECOVER(vdi);}
+ {
+ tree node = java_lval.node;
+ if (node && (TREE_CODE (node) == INTEGER_CST
+ || TREE_CODE (node) == EXPR_WITH_FILE_LOCATION))
+ yyerror ("Can't specify array dimension in a declaration");
+ else
+ yyerror ("']' expected");
+ DRECOVER(vdi);
+ }
| variable_declarator_id CSB_TK error
{yyerror ("Unbalanced ']'"); DRECOVER(vdi);}
;
@@ -1465,20 +1473,17 @@ expression_statement:
}
| error SC_TK
{
- if (ctxp->prevent_ese != lineno)
- yyerror ("Invalid expression statement");
+ YYNOT_TWICE yyerror ("Invalid expression statement");
DRECOVER (expr_stmt);
}
| error OCB_TK
{
- if (ctxp->prevent_ese != lineno)
- yyerror ("Invalid expression statement");
+ YYNOT_TWICE yyerror ("Invalid expression statement");
DRECOVER (expr_stmt);
}
| error CCB_TK
{
- if (ctxp->prevent_ese != lineno)
- yyerror ("Invalid expression statement");
+ YYNOT_TWICE yyerror ("Invalid expression statement");
DRECOVER (expr_stmt);
}
| this_or_super OP_TK error
@@ -2342,8 +2347,7 @@ cast_expression: /* Error handling here
{yyerror ("']' expected, invalid type expression");}
| OP_TK error
{
- if (ctxp->prevent_ese != lineno)
- yyerror ("Invalid type expression"); RECOVER;
+ YYNOT_TWICE yyerror ("Invalid type expression"); RECOVER;
RECOVER;
}
| OP_TK primitive_type dims CP_TK error
@@ -2560,8 +2564,7 @@ assignment:
{ $$ = build_assignment ($2.token, $2.location, $1, $3); }
| left_hand_side assignment_operator error
{
- if (ctxp->prevent_ese != lineno)
- yyerror ("Missing term");
+ YYNOT_TWICE yyerror ("Missing term");
DRECOVER (assign);
}
;