This is the mail archive of the
java-patches@gcc.gnu.org
mailing list for the Java project.
Java: Fix for PR 4695
- To: java-patches at gcc dot gnu dot org, gcc-patches at gcc dot gnu dot org
- Subject: Java: Fix for PR 4695
- From: Bryce McKinlay <bryce at waitaki dot otago dot ac dot nz>
- Date: Fri, 02 Nov 2001 20:17:48 +1300
This patch fixes PR 4695. The problem was that the check for illegal use
of this in explicit constructor invocation in patch_method_invocation is
a bit bogus, and the fix is to change it so that it looks at the
arguments being passed (after any implicit arguments have been
inserted). This makes the check simpler and more robust, but it was
complicated by resolve_qualified_expression_name playing games with the
"current_this" when trying to resolve something qualified by a primary.
To fix that I've added an "enclosing" argument to resolve_and_layout and
resolve_no_layout so that inner classes can be resolved relative to a
context other than current_class (note that resolve_class and friends
already have this argument).
Built libgcj, and jacks and "make check" both ran with no regressions.
OK to commit?
regards
Bryce.
2001-11-02 Bryce McKinlay <bryce@waitaki.otago.ac.nz>
Fix for PR java/4695.
* parse.y (resolve_and_layout): Add "enclosing" parameter.
(resolve_no_layout): Likewise. Call resolve_class with "enclosing"
or use current_class if it is null.
(resolve_qualified_expression_name): Don't change current_class and
current_this.
(patch_method_invocation): Call resolve_and_layout with "enclosing"
parameter, used in the case of an enclosing-instance qualified call or
new. Check for illegal use of "this" in constructor call by checking
the actual args being passed.
Index: parse.y
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/parse.y,v
retrieving revision 1.323
diff -u -r1.323 parse.y
--- parse.y 2001/10/26 01:53:56 1.323
+++ parse.y 2001/11/02 05:32:56
@@ -127,9 +127,9 @@
int *, tree *));
static int breakdown_qualified PARAMS ((tree *, tree *, tree));
static int in_same_package PARAMS ((tree, tree));
-static tree resolve_and_layout PARAMS ((tree, tree));
+static tree resolve_and_layout PARAMS ((tree, tree, tree));
static tree qualify_and_find PARAMS ((tree, tree, tree));
-static tree resolve_no_layout PARAMS ((tree, tree));
+static tree resolve_no_layout PARAMS ((tree, tree, tree));
static int invocation_mode PARAMS ((tree, int));
static tree find_applicable_accessible_methods_list PARAMS ((int, tree,
tree, tree));
@@ -5864,12 +5864,15 @@
/* Resolve NAME and lay it out (if not done and if not the current
parsed class). Return a decl node. This function is meant to be
- called when type resolution is necessary during the walk pass. */
+ called when type resolution is necessary during the walk pass.
+ ENCLOSING is the enclosing context in which to search for an inner
+ class. If it is NULL_TREE, the current_class is assumed. */
static tree
-resolve_and_layout (something, cl)
+resolve_and_layout (something, cl, enclosing)
tree something;
tree cl;
+ tree enclosing;
{
tree decl, decl_type;
@@ -5904,13 +5907,13 @@
if (TREE_CODE (something) == EXPR_WITH_FILE_LOCATION)
something = EXPR_WFL_NODE (something);
- /* Otherwise, if something is not and IDENTIFIER_NODE, it can be a a
+ /* Otherwise, if something is not and IDENTIFIER_NODE, it can be a
TYPE_DECL or a real TYPE */
else if (TREE_CODE (something) != IDENTIFIER_NODE)
something = (TREE_CODE (TYPE_NAME (something)) == TYPE_DECL ?
DECL_NAME (TYPE_NAME (something)) : TYPE_NAME (something));
- if (!(decl = resolve_no_layout (something, cl)))
+ if (!(decl = resolve_no_layout (something, cl, enclosing)))
return NULL_TREE;
/* Resolve and layout if necessary */
@@ -5930,13 +5933,15 @@
layout. The current parsing context is saved and restored */
static tree
-resolve_no_layout (name, cl)
- tree name, cl;
+resolve_no_layout (name, cl, enclosing)
+ tree name, cl, enclosing;
{
tree ptr, decl;
BUILD_PTR_FROM_NAME (ptr, name);
+ if (enclosing == NULL_TREE)
+ enclosing = current_class;
java_parser_context_save_global ();
- decl = resolve_class (TYPE_NAME (current_class), ptr, NULL_TREE, cl);
+ decl = resolve_class (TYPE_NAME (enclosing), ptr, NULL_TREE, cl);
java_parser_context_restore_global ();
return decl;
@@ -7035,7 +7040,7 @@
if (TREE_CODE (QUAL_WFL (current)) != EXPR_WITH_FILE_LOCATION)
break;
acc = merge_qualified_name (acc, EXPR_WFL_NODE (QUAL_WFL (current)));
- if ((type_name = resolve_no_layout (acc, NULL_TREE)))
+ if ((type_name = resolve_no_layout (acc, NULL_TREE, NULL_TREE)))
{
type_name = acc;
/* resolve_package should be used in a loop, hence we
@@ -9356,9 +9361,6 @@
int is_static;
tree decl = NULL_TREE, type = NULL_TREE, q;
/* For certain for of inner class instantiation */
- tree saved_current, saved_this;
-#define RESTORE_THIS_AND_CURRENT_CLASS \
- { current_class = saved_current; current_this = saved_this;}
*type_found = *where_found = NULL_TREE;
@@ -9387,12 +9389,6 @@
if (complete_function_arguments (qual_wfl))
return 1;
- /* We might have to setup a new current class and a new this
- for the search of an inner class, relative to the type of
- a expression resolved as `decl'. The current values are
- saved and restored shortly after */
- saved_current = current_class;
- saved_this = current_this;
if (decl
&& (TREE_CODE (qual_wfl) == NEW_CLASS_EXPR
|| from_qualified_this))
@@ -9405,8 +9401,6 @@
decl = java_complete_tree (decl);
type = TREE_TYPE (TREE_TYPE (decl));
}
- current_class = type;
- current_this = decl;
from_qualified_this = 0;
}
@@ -9418,10 +9412,8 @@
from_super,
&is_static, &ret_decl);
if (*where_found == error_mark_node)
- {
- RESTORE_THIS_AND_CURRENT_CLASS;
- return 1;
- }
+ return 1;
+
*type_found = type = QUAL_DECL_TYPE (*where_found);
/* If we're creating an inner class instance, check for that
@@ -9434,14 +9426,9 @@
lang_printable_name (type, 0),
(!current_this ? "" :
"; an explicit one must be provided when creating this inner class"));
- RESTORE_THIS_AND_CURRENT_CLASS;
return 1;
}
- /* In case we had to change then to resolve a inner class
- instantiation using a primary qualified by a `new' */
- RESTORE_THIS_AND_CURRENT_CLASS;
-
/* EH check. No check on access$<n> functions */
if (location
&& !OUTER_FIELD_ACCESS_IDENTIFIER_P
@@ -9617,7 +9604,8 @@
if (name)
{
tree list;
- *where_found = decl = resolve_no_layout (name, qual_wfl);
+ *where_found = decl = resolve_no_layout (name, qual_wfl,
+ NULL_TREE);
/* 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);
@@ -9794,7 +9782,7 @@
if (!JPRIMITIVE_TYPE_P (field_decl_type)
&& !CLASS_LOADED_P (field_decl_type)
&& !TYPE_ARRAY_P (field_decl_type))
- resolve_and_layout (field_decl_type, NULL_TREE);
+ resolve_and_layout (field_decl_type, NULL_TREE, NULL_TREE);
/* Check on accessibility here */
if (not_accessible_p (current_class, field_decl,
@@ -10080,6 +10068,7 @@
tree args = TREE_OPERAND (patch, 1);
tree name = EXPR_WFL_NODE (wfl);
tree list;
+ tree arg;
int is_static_flag = 0;
int is_super_init = 0;
tree this_arg = NULL_TREE;
@@ -10123,7 +10112,7 @@
PATCH_METHOD_RETURN_ERROR ();
type = GET_SKIP_TYPE (resolved);
- resolve_and_layout (type, NULL_TREE);
+ resolve_and_layout (type, NULL_TREE, NULL_TREE);
if (JPRIMITIVE_TYPE_P (type))
{
@@ -10202,7 +10191,8 @@
/* Class to search is NULL if we're searching the current one */
if (class_to_search)
{
- class_to_search = resolve_and_layout (class_to_search, wfl);
+ class_to_search = resolve_and_layout (class_to_search, wfl,
+ where);
if (!class_to_search)
{
@@ -10263,7 +10253,7 @@
/* NAME is a simple identifier or comes from a primary. Search
in the class whose declaration contain the method being
invoked. */
- resolve_and_layout (class_to_search, NULL_TREE);
+ resolve_and_layout (class_to_search, NULL_TREE, NULL_TREE);
list = lookup_method_invoke (lc, wfl, class_to_search, name, args);
/* Don't continue if no method were found, as the next statement
@@ -10448,17 +10438,15 @@
args = tree_cons (NULL_TREE, this_arg, args);
/* In the context of an explicit constructor invocation, we can't
- invoke any method relying on `this'. Exceptions are: we're
- invoking a static function, primary exists and is not the current
- this, we're creating a new object. */
- if (ctxp->explicit_constructor_p
- && !is_static_flag
- && (!primary || primary == current_this)
- && (TREE_CODE (patch) != NEW_CLASS_EXPR))
- {
- parse_error_context (wfl, "Can't reference `this' before the superclass constructor has been called");
- PATCH_METHOD_RETURN_ERROR ();
- }
+ invoke any method relying on `this'. */
+ if (ctxp->explicit_constructor_p)
+ for (arg = args; arg != NULL_TREE; arg = TREE_CHAIN (arg))
+ if (TREE_VALUE (arg) == current_this)
+ {
+ parse_error_context (wfl, "Can't reference `this' before the superclass constructor has been called");
+ PATCH_METHOD_RETURN_ERROR ();
+ }
+
java_parser_context_restore_global ();
if (is_static)
*is_static = is_static_flag;
@@ -10611,7 +10599,7 @@
/* Resolve unresolved returned type isses */
t = TREE_TYPE (TREE_TYPE (method));
if (TREE_CODE (t) == POINTER_TYPE && !CLASS_LOADED_P (TREE_TYPE (t)))
- resolve_and_layout (TREE_TYPE (t), NULL);
+ resolve_and_layout (TREE_TYPE (t), NULL_TREE, NULL_TREE);
if (flag_emit_class_files || flag_emit_xref)
func = method;
@@ -10781,7 +10769,7 @@
tree current_arg = TREE_TYPE (TREE_VALUE (node));
/* Non primitive type may have to be resolved */
if (!JPRIMITIVE_TYPE_P (current_arg))
- resolve_and_layout (current_arg, NULL_TREE);
+ resolve_and_layout (current_arg, NULL_TREE, NULL_TREE);
/* And promoted */
if (TREE_CODE (current_arg) == RECORD_TYPE)
current_arg = promote_type (current_arg);
@@ -11129,7 +11117,7 @@
while (m1_arg != end_params_node && m2_arg != end_params_node)
{
- resolve_and_layout (TREE_VALUE (m1_arg), NULL_TREE);
+ resolve_and_layout (TREE_VALUE (m1_arg), NULL_TREE, NULL_TREE);
if (!valid_method_invocation_conversion_p (TREE_VALUE (m1_arg),
TREE_VALUE (m2_arg)))
break;
@@ -11321,7 +11309,7 @@
else if (! this_found &&
(TREE_CODE (name) == STRING_CST ||
TREE_CODE (name) == INTEGER_CST ||
- (decl = resolve_and_layout (name, NULL_TREE))))
+ (decl = resolve_and_layout (name, NULL_TREE, NULL_TREE))))
{
RESOLVE_TYPE_NAME_P (qual_wfl) = 1;
QUAL_RESOLUTION (qual) = decl;
@@ -14397,7 +14385,8 @@
{
if (unresolved_type_p (type, NULL))
{
- tree type_decl = resolve_and_layout (EXPR_WFL_NODE (type), type);
+ tree type_decl = resolve_and_layout (EXPR_WFL_NODE (type), type,
+ NULL_TREE);
if (!type_decl)
{
parse_error_context (type,
@@ -15820,7 +15809,7 @@
tree exception;
{
tree list = currently_caught_type_list;
- resolve_and_layout (exception, NULL_TREE);
+ resolve_and_layout (exception, NULL_TREE, NULL_TREE);
/* First, all the nested try-catch-finally at that stage. The
last element contains `throws' clause exceptions, if any. */
if (IS_UNCHECKED_EXCEPTION_P (exception))