re PR java/12374 (Segfault on "".x)
PR java/12374: * parse.y (qualify_ambiguous_name): Remove lots of broken field access processing - there's no need to do that here, because we have resolve_field_access. Remove RESOLVE_EXPRESSION_NAME_P as it isn't used anywhere else. * java-tree.h: Remove RESOLVE_EXPRESSION_NAME_P as it isn't used. From-SVN: r74217
This commit is contained in:
parent
a0506b54dd
commit
c6a25d3a3d
5 changed files with 73 additions and 196 deletions
|
@ -1,3 +1,13 @@
|
||||||
|
2003-12-03 Ralph Loader <rcl@ihug.co.nz>
|
||||||
|
|
||||||
|
PR java/12374:
|
||||||
|
* parse.y (qualify_ambiguous_name): Remove lots of broken
|
||||||
|
field access processing - there's no need to do that here,
|
||||||
|
because we have resolve_field_access. Remove
|
||||||
|
RESOLVE_EXPRESSION_NAME_P as it isn't used anywhere else.
|
||||||
|
* java-tree.h: Remove RESOLVE_EXPRESSION_NAME_P as it isn't
|
||||||
|
used.
|
||||||
|
|
||||||
2003-12-01 Jeff Sturm <jsturm@one-point.com>
|
2003-12-01 Jeff Sturm <jsturm@one-point.com>
|
||||||
|
|
||||||
Fix PR java/13237
|
Fix PR java/13237
|
||||||
|
|
|
@ -44,7 +44,6 @@ struct JCF;
|
||||||
|
|
||||||
/* Usage of TREE_LANG_FLAG_?:
|
/* Usage of TREE_LANG_FLAG_?:
|
||||||
0: IS_A_SINGLE_IMPORT_CLASSFILE_NAME_P (in IDENTIFIER_NODE)
|
0: IS_A_SINGLE_IMPORT_CLASSFILE_NAME_P (in IDENTIFIER_NODE)
|
||||||
RESOLVE_EXPRESSION_NAME_P (in EXPR_WITH_FILE_LOCATION)
|
|
||||||
FOR_LOOP_P (in LOOP_EXPR)
|
FOR_LOOP_P (in LOOP_EXPR)
|
||||||
SUPPRESS_UNREACHABLE_ERROR (for other _EXPR nodes)
|
SUPPRESS_UNREACHABLE_ERROR (for other _EXPR nodes)
|
||||||
ANONYMOUS_CLASS_P (in RECORD_TYPE)
|
ANONYMOUS_CLASS_P (in RECORD_TYPE)
|
||||||
|
@ -1550,9 +1549,6 @@ extern tree *type_map;
|
||||||
feature a finalizer method. */
|
feature a finalizer method. */
|
||||||
#define HAS_FINALIZER_P(EXPR) TREE_LANG_FLAG_3 (EXPR)
|
#define HAS_FINALIZER_P(EXPR) TREE_LANG_FLAG_3 (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)
|
|
||||||
|
|
||||||
/* True if EXPR (a LOOP_EXPR in that case) is part of a for statement */
|
/* True if EXPR (a LOOP_EXPR in that case) is part of a for statement */
|
||||||
#define FOR_LOOP_P(EXPR) TREE_LANG_FLAG_0 (EXPR)
|
#define FOR_LOOP_P(EXPR) TREE_LANG_FLAG_0 (EXPR)
|
||||||
|
|
||||||
|
|
223
gcc/java/parse.y
223
gcc/java/parse.y
|
@ -9802,7 +9802,6 @@ resolve_qualified_expression_name (tree wfl, tree *found_decl,
|
||||||
list = TREE_CHAIN (q);
|
list = TREE_CHAIN (q);
|
||||||
while (list)
|
while (list)
|
||||||
{
|
{
|
||||||
RESOLVE_EXPRESSION_NAME_P (QUAL_WFL (list)) = 1;
|
|
||||||
RESOLVE_PACKAGE_NAME_P (QUAL_WFL (list)) = 0;
|
RESOLVE_PACKAGE_NAME_P (QUAL_WFL (list)) = 0;
|
||||||
list = TREE_CHAIN (list);
|
list = TREE_CHAIN (list);
|
||||||
}
|
}
|
||||||
|
@ -11280,211 +11279,58 @@ argument_types_convertible (tree m1, tree m2_or_arglist)
|
||||||
|
|
||||||
/* Qualification routines */
|
/* Qualification routines */
|
||||||
|
|
||||||
|
/* Given a name x.y.z, look up x locally. If it's found, save the
|
||||||
|
decl. If it's not found, mark the name as RESOLVE_PACKAGE_NAME_P,
|
||||||
|
so that we later try and load the appropriate classes. */
|
||||||
static void
|
static void
|
||||||
qualify_ambiguous_name (tree id)
|
qualify_ambiguous_name (tree id)
|
||||||
{
|
{
|
||||||
tree qual, qual_wfl, name = NULL_TREE, decl, ptr_type = NULL_TREE,
|
tree name, decl;
|
||||||
saved_current_class;
|
|
||||||
int again, super_found = 0, this_found = 0, new_array_found = 0;
|
|
||||||
int code;
|
|
||||||
|
|
||||||
/* We first qualify the first element, then derive qualification of
|
/* We inspect the first item of the qualification list. As a sanity
|
||||||
others based on the first one. If the first element is qualified
|
check, make sure that it is an identfier node. */
|
||||||
by a resolution (field or type), this resolution is stored in the
|
tree qual = EXPR_WFL_QUALIFICATION (id);
|
||||||
QUAL_RESOLUTION of the qual element being examined. We need to
|
tree qual_wfl = QUAL_WFL (qual);
|
||||||
save the current_class since the use of SUPER might change the
|
|
||||||
its value. */
|
|
||||||
saved_current_class = current_class;
|
|
||||||
qual = EXPR_WFL_QUALIFICATION (id);
|
|
||||||
do {
|
|
||||||
|
|
||||||
/* Simple qualified expression feature a qual_wfl that is a
|
if (TREE_CODE (qual_wfl) != EXPR_WITH_FILE_LOCATION)
|
||||||
WFL. Expression derived from a primary feature more complicated
|
return;
|
||||||
things like a CALL_EXPR. Expression from primary need to be
|
|
||||||
worked out to extract the part on which the qualification will
|
|
||||||
take place. */
|
|
||||||
qual_wfl = QUAL_WFL (qual);
|
|
||||||
switch (TREE_CODE (qual_wfl))
|
|
||||||
{
|
|
||||||
case CALL_EXPR:
|
|
||||||
qual_wfl = TREE_OPERAND (qual_wfl, 0);
|
|
||||||
if (TREE_CODE (qual_wfl) != EXPR_WITH_FILE_LOCATION
|
|
||||||
|| (EXPR_WFL_QUALIFICATION (qual_wfl)
|
|
||||||
&& TREE_CODE (EXPR_WFL_QUALIFICATION (qual_wfl)) == TREE_LIST))
|
|
||||||
{
|
|
||||||
qual = EXPR_WFL_QUALIFICATION (qual_wfl);
|
|
||||||
qual_wfl = QUAL_WFL (qual);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case NEW_ARRAY_EXPR:
|
|
||||||
case NEW_ANONYMOUS_ARRAY_EXPR:
|
|
||||||
qual = TREE_CHAIN (qual);
|
|
||||||
again = new_array_found = 1;
|
|
||||||
continue;
|
|
||||||
case CONVERT_EXPR:
|
|
||||||
break;
|
|
||||||
case NEW_CLASS_EXPR:
|
|
||||||
qual_wfl = TREE_OPERAND (qual_wfl, 0);
|
|
||||||
break;
|
|
||||||
case ARRAY_REF:
|
|
||||||
while (TREE_CODE (qual_wfl) == ARRAY_REF)
|
|
||||||
qual_wfl = TREE_OPERAND (qual_wfl, 0);
|
|
||||||
break;
|
|
||||||
case STRING_CST:
|
|
||||||
qual = TREE_CHAIN (qual);
|
|
||||||
qual_wfl = QUAL_WFL (qual);
|
|
||||||
break;
|
|
||||||
case CLASS_LITERAL:
|
|
||||||
qual = TREE_CHAIN (qual);
|
|
||||||
qual_wfl = QUAL_WFL (qual);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
/* Fix for -Wall. Just break doing nothing */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
ptr_type = current_class;
|
name = EXPR_WFL_NODE (qual_wfl);
|
||||||
again = 0;
|
|
||||||
code = TREE_CODE (qual_wfl);
|
|
||||||
|
|
||||||
/* Pos evaluation: non WFL leading expression nodes */
|
/* If we don't have an identifier, or we have a 'this' or 'super',
|
||||||
if (code == CONVERT_EXPR
|
then field access processing is all we need : there is nothing
|
||||||
&& TREE_CODE (TREE_TYPE (qual_wfl)) == EXPR_WITH_FILE_LOCATION)
|
for us to do. */
|
||||||
name = EXPR_WFL_NODE (TREE_TYPE (qual_wfl));
|
if (!name || TREE_CODE (name) != IDENTIFIER_NODE ||
|
||||||
|
name == this_identifier_node ||
|
||||||
else if (code == INTEGER_CST)
|
name == super_identifier_node)
|
||||||
name = qual_wfl;
|
return;
|
||||||
|
|
||||||
else if (code == CONVERT_EXPR &&
|
|
||||||
TREE_CODE (TREE_OPERAND (qual_wfl, 0)) == EXPR_WITH_FILE_LOCATION)
|
|
||||||
name = TREE_OPERAND (qual_wfl, 0);
|
|
||||||
|
|
||||||
else if (code == CONVERT_EXPR
|
|
||||||
&& TREE_CODE (TREE_OPERAND (qual_wfl, 0)) == CALL_EXPR
|
|
||||||
&& (TREE_CODE (TREE_OPERAND (TREE_OPERAND (qual_wfl, 0), 0))
|
|
||||||
== EXPR_WITH_FILE_LOCATION))
|
|
||||||
name = TREE_OPERAND (TREE_OPERAND (qual_wfl, 0), 0);
|
|
||||||
|
|
||||||
else if ((code == ARRAY_REF || code == CALL_EXPR || code == MODIFY_EXPR) &&
|
|
||||||
TREE_CODE (TREE_OPERAND (qual_wfl, 0)) == EXPR_WITH_FILE_LOCATION)
|
|
||||||
name = EXPR_WFL_NODE (TREE_OPERAND (qual_wfl, 0));
|
|
||||||
|
|
||||||
else if (code == TREE_LIST)
|
|
||||||
name = EXPR_WFL_NODE (TREE_PURPOSE (qual_wfl));
|
|
||||||
|
|
||||||
else if (code == STRING_CST || code == CONDITIONAL_EXPR
|
|
||||||
|| code == PLUS_EXPR)
|
|
||||||
{
|
|
||||||
qual = TREE_CHAIN (qual);
|
|
||||||
qual_wfl = QUAL_WFL (qual);
|
|
||||||
again = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
name = EXPR_WFL_NODE (qual_wfl);
|
|
||||||
if (!name)
|
|
||||||
{
|
|
||||||
qual = EXPR_WFL_QUALIFICATION (qual_wfl);
|
|
||||||
again = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If we have a THIS (from a primary), we set the context accordingly */
|
|
||||||
if (name == this_identifier_node)
|
|
||||||
{
|
|
||||||
/* This isn't really elegant. One more added irregularity
|
|
||||||
before I start using COMPONENT_REF (hopefully very soon.) */
|
|
||||||
if (TREE_CODE (TREE_PURPOSE (qual)) == ARRAY_REF
|
|
||||||
&& TREE_CODE (TREE_OPERAND (TREE_PURPOSE (qual), 0)) ==
|
|
||||||
EXPR_WITH_FILE_LOCATION
|
|
||||||
&& EXPR_WFL_NODE (TREE_OPERAND (TREE_PURPOSE (qual), 0)) ==
|
|
||||||
this_identifier_node)
|
|
||||||
{
|
|
||||||
qual = TREE_OPERAND (TREE_PURPOSE (qual), 0);
|
|
||||||
qual = EXPR_WFL_QUALIFICATION (qual);
|
|
||||||
}
|
|
||||||
qual = TREE_CHAIN (qual);
|
|
||||||
qual_wfl = QUAL_WFL (qual);
|
|
||||||
if (TREE_CODE (qual_wfl) == CALL_EXPR)
|
|
||||||
again = 1;
|
|
||||||
else if (TREE_CODE (qual_wfl) == EXPR_WITH_FILE_LOCATION)
|
|
||||||
name = EXPR_WFL_NODE (qual_wfl);
|
|
||||||
else if (TREE_CODE (qual_wfl) == NEW_CLASS_EXPR)
|
|
||||||
name = TREE_OPERAND (qual_wfl, 0);
|
|
||||||
this_found = 1;
|
|
||||||
}
|
|
||||||
/* If we have a SUPER, we set the context accordingly */
|
|
||||||
if (name == super_identifier_node)
|
|
||||||
{
|
|
||||||
current_class = CLASSTYPE_SUPER (ptr_type);
|
|
||||||
/* Check that there is such a thing as a super class. If not,
|
|
||||||
return. The error will be caught later on, during the
|
|
||||||
resolution */
|
|
||||||
if (!current_class)
|
|
||||||
{
|
|
||||||
current_class = saved_current_class;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
qual = TREE_CHAIN (qual);
|
|
||||||
/* Do one more iteration to set things up */
|
|
||||||
super_found = again = 1;
|
|
||||||
}
|
|
||||||
} while (again);
|
|
||||||
|
|
||||||
/* If name appears within the scope of a local variable declaration
|
/* If name appears within the scope of a local variable declaration
|
||||||
or parameter declaration, then it is an expression name. We don't
|
or parameter declaration, or is a field within an enclosing
|
||||||
carry this test out if we're in the context of the use of SUPER
|
class, then it is an expression name. Save the decl and let
|
||||||
or THIS */
|
resolve_field_access do it's work. */
|
||||||
if (!this_found && !super_found
|
if ((decl = IDENTIFIER_LOCAL_VALUE (name)) ||
|
||||||
&& TREE_CODE (name) != STRING_CST && TREE_CODE (name) != INTEGER_CST
|
(decl = lookup_field_wrapper (current_class, name)))
|
||||||
&& (decl = IDENTIFIER_LOCAL_VALUE (name)))
|
|
||||||
{
|
{
|
||||||
RESOLVE_EXPRESSION_NAME_P (qual_wfl) = 1;
|
|
||||||
QUAL_RESOLUTION (qual) = decl;
|
QUAL_RESOLUTION (qual) = decl;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If within the class/interface NAME was found to be used there
|
/* If name is a known class name (either declared or imported), mark
|
||||||
exists a (possibly inherited) field named NAME, then this is an
|
us as a type name. */
|
||||||
expression name. If we saw a NEW_ARRAY_EXPR before and want to
|
if ((decl = resolve_and_layout (name, NULL_TREE)))
|
||||||
address length, it is OK. */
|
|
||||||
else if ((decl = lookup_field_wrapper (ptr_type, name))
|
|
||||||
|| name == length_identifier_node)
|
|
||||||
{
|
|
||||||
RESOLVE_EXPRESSION_NAME_P (qual_wfl) = 1;
|
|
||||||
QUAL_RESOLUTION (qual) = (new_array_found ? NULL_TREE : decl);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We reclassify NAME as yielding to a type name resolution if:
|
|
||||||
- NAME is a class/interface declared within the compilation
|
|
||||||
unit containing NAME,
|
|
||||||
- NAME is imported via a single-type-import declaration,
|
|
||||||
- NAME is declared in an another compilation unit of the package
|
|
||||||
of the compilation unit containing NAME,
|
|
||||||
- NAME is declared by exactly on type-import-on-demand declaration
|
|
||||||
of the compilation unit containing NAME.
|
|
||||||
- NAME is actually a STRING_CST.
|
|
||||||
This can't happen if the expression was qualified by `this.' */
|
|
||||||
else if (! this_found &&
|
|
||||||
(TREE_CODE (name) == STRING_CST ||
|
|
||||||
TREE_CODE (name) == INTEGER_CST ||
|
|
||||||
(decl = resolve_and_layout (name, NULL_TREE))))
|
|
||||||
{
|
{
|
||||||
RESOLVE_TYPE_NAME_P (qual_wfl) = 1;
|
RESOLVE_TYPE_NAME_P (qual_wfl) = 1;
|
||||||
QUAL_RESOLUTION (qual) = decl;
|
QUAL_RESOLUTION (qual) = decl;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Method call, array references and cast are expression name */
|
|
||||||
else if (TREE_CODE (QUAL_WFL (qual)) == CALL_EXPR
|
|
||||||
|| TREE_CODE (QUAL_WFL (qual)) == ARRAY_REF
|
|
||||||
|| TREE_CODE (QUAL_WFL (qual)) == CONVERT_EXPR
|
|
||||||
|| TREE_CODE (QUAL_WFL (qual)) == MODIFY_EXPR)
|
|
||||||
RESOLVE_EXPRESSION_NAME_P (qual_wfl) = 1;
|
|
||||||
|
|
||||||
/* Check here that NAME isn't declared by more than one
|
/* Check here that NAME isn't declared by more than one
|
||||||
type-import-on-demand declaration of the compilation unit
|
type-import-on-demand declaration of the compilation unit
|
||||||
containing NAME. FIXME */
|
containing NAME. FIXME */
|
||||||
|
|
||||||
/* Otherwise, NAME is reclassified as a package name */
|
/* We couldn't find a declaration for the name. Assume for now that
|
||||||
|
we have a qualified class name that needs to be loaded from an
|
||||||
|
external class file. */
|
||||||
else
|
else
|
||||||
RESOLVE_PACKAGE_NAME_P (qual_wfl) = 1;
|
RESOLVE_PACKAGE_NAME_P (qual_wfl) = 1;
|
||||||
|
|
||||||
|
@ -11495,21 +11341,14 @@ qualify_ambiguous_name (tree id)
|
||||||
{
|
{
|
||||||
if (RESOLVE_PACKAGE_NAME_P (qual_wfl))
|
if (RESOLVE_PACKAGE_NAME_P (qual_wfl))
|
||||||
RESOLVE_PACKAGE_NAME_P (QUAL_WFL (qual)) = 1;
|
RESOLVE_PACKAGE_NAME_P (QUAL_WFL (qual)) = 1;
|
||||||
else
|
|
||||||
RESOLVE_EXPRESSION_NAME_P (QUAL_WFL (qual)) = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Store the global qualification for the ambiguous part of ID back
|
/* Store the global qualification for the ambiguous part of ID back
|
||||||
into ID fields */
|
into ID fields */
|
||||||
if (RESOLVE_EXPRESSION_NAME_P (qual_wfl))
|
if (RESOLVE_TYPE_NAME_P (qual_wfl))
|
||||||
RESOLVE_EXPRESSION_NAME_P (id) = 1;
|
|
||||||
else if (RESOLVE_TYPE_NAME_P (qual_wfl))
|
|
||||||
RESOLVE_TYPE_NAME_P (id) = 1;
|
RESOLVE_TYPE_NAME_P (id) = 1;
|
||||||
else if (RESOLVE_PACKAGE_NAME_P (qual_wfl))
|
else if (RESOLVE_PACKAGE_NAME_P (qual_wfl))
|
||||||
RESOLVE_PACKAGE_NAME_P (id) = 1;
|
RESOLVE_PACKAGE_NAME_P (id) = 1;
|
||||||
|
|
||||||
/* Restore the current class */
|
|
||||||
current_class = saved_current_class;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
2003-12-03 Ralph Loader <rcl@ihug.co.nz>
|
||||||
|
|
||||||
|
PR java/12374:
|
||||||
|
* libjava.compile/PR12374.java: New file.
|
||||||
|
|
||||||
2003-12-01 Jeff Sturm <jsturm@one-point.com>
|
2003-12-01 Jeff Sturm <jsturm@one-point.com>
|
||||||
|
|
||||||
PR optimization/13024
|
PR optimization/13024
|
||||||
|
|
27
libjava/testsuite/libjava.compile/PR12374.java
Normal file
27
libjava/testsuite/libjava.compile/PR12374.java
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
public class PR12374 {
|
||||||
|
|
||||||
|
/* We weren't coping with field refs on a string constant... */
|
||||||
|
|
||||||
|
Object Foo()
|
||||||
|
{
|
||||||
|
return "".CASE_INSENSITIVE_ORDER;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Special casing access to array.length while analysing syntax is
|
||||||
|
evil. Especially when it means we can't cope with a type
|
||||||
|
called length. */
|
||||||
|
|
||||||
|
class length
|
||||||
|
{
|
||||||
|
static final int i = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bar()
|
||||||
|
{
|
||||||
|
return length.i;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main (String[] argv)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue