aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorBryce McKinlay <mckinlay@redhat.com>2004-07-10 05:38:15 +0000
committerBryce McKinlay <bryce@gcc.gnu.org>2004-07-10 06:38:15 +0100
commitd3ecb597b35d5b8c4176a0b60c10cbfdb40ace8b (patch)
treebcd4a6d234666cbea3ddc05897321cf2a6b159ef /gcc
parenta7e5372d6a8e2f12b6d9a15f71d5ad0794e6507f (diff)
downloadgcc-d3ecb597b35d5b8c4176a0b60c10cbfdb40ace8b.zip
gcc-d3ecb597b35d5b8c4176a0b60c10cbfdb40ace8b.tar.gz
gcc-d3ecb597b35d5b8c4176a0b60c10cbfdb40ace8b.tar.bz2
re PR java/8618 (call to private constructor allowed for anonymous inner class)
2004-07-09 Bryce McKinlay <mckinlay@redhat.com> PR java/8618 * parse.y (create_anonymous_class): Remove 'location' argument. Use the WFL from TYPE_NAME to get line number for the decl. Fix comment. (craft_constructor): Inherit access flags for implicit constructor from the enclosing class. (create_class): Fix comment typo. (resolve_qualified_expression_name): Pass type of qualifier to not_accessible_p, not the type in which target field was found. (not_accessible_p): Handle inner classes. Expand protected qualifier-subtype check to enclosing instances, but don't apply this check to static members. Allow protected access to inner classes of a subtype. Allow private access within common enclosing context. (build_super_invocation): Get WFL line number info from current class decl. (build_incomplete_class_ref): Update for new create_anonymous_class signature. * parse.h (INNER_ENCLOSING_SCOPE_CHECK): Use common_enclosing_instance_p. * class.c (common_enclosing_context_p): New. Determine if types share a common enclosing context, even across static contexts. (common_enclosing_instance_p): Renamed from common_enclosing_context_p. Determines if types share a common non-static enclosing instance. * java-tree.h (common_enclosing_instance_p): Declare. * jcf-write.c (get_method_access_flags): New. Surpress private flag for inner class constructors. (generate_classfile): Use get_method_access_flags. From-SVN: r84443
Diffstat (limited to 'gcc')
-rw-r--r--gcc/java/ChangeLog30
-rw-r--r--gcc/java/class.c26
-rw-r--r--gcc/java/java-tree.h1
-rw-r--r--gcc/java/jcf-write.c18
-rw-r--r--gcc/java/parse.h2
-rw-r--r--gcc/java/parse.y88
6 files changed, 125 insertions, 40 deletions
diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog
index b249267..fea2c21 100644
--- a/gcc/java/ChangeLog
+++ b/gcc/java/ChangeLog
@@ -1,5 +1,35 @@
2004-07-09 Bryce McKinlay <mckinlay@redhat.com>
+ PR java/8618
+ * parse.y (create_anonymous_class): Remove 'location' argument. Use
+ the WFL from TYPE_NAME to get line number for the decl. Fix comment.
+ (craft_constructor): Inherit access flags for implicit constructor
+ from the enclosing class.
+ (create_class): Fix comment typo.
+ (resolve_qualified_expression_name): Pass type of qualifier to
+ not_accessible_p, not the type in which target field was found.
+ (not_accessible_p): Handle inner classes. Expand protected
+ qualifier-subtype check to enclosing instances, but don't apply this
+ check to static members. Allow protected access to inner classes
+ of a subtype. Allow private access within common enclosing context.
+ (build_super_invocation): Get WFL line number info from current
+ class decl.
+ (build_incomplete_class_ref): Update for new create_anonymous_class
+ signature.
+ * parse.h (INNER_ENCLOSING_SCOPE_CHECK): Use
+ common_enclosing_instance_p.
+ * class.c (common_enclosing_context_p): New. Determine if types
+ share a common enclosing context, even across static contexts.
+ (common_enclosing_instance_p): Renamed from
+ common_enclosing_context_p. Determines if types share a common
+ non-static enclosing instance.
+ * java-tree.h (common_enclosing_instance_p): Declare.
+ * jcf-write.c (get_method_access_flags): New. Surpress private flag
+ for inner class constructors.
+ (generate_classfile): Use get_method_access_flags.
+
+2004-07-09 Bryce McKinlay <mckinlay@redhat.com>
+
* class.c (interface_of_p): Check for null TYPE_BINFO.
2004-07-09 Nathan Sidwell <nathan@codesourcery.com>
diff --git a/gcc/java/class.c b/gcc/java/class.c
index 90f2789..1273b62 100644
--- a/gcc/java/class.c
+++ b/gcc/java/class.c
@@ -587,12 +587,34 @@ enclosing_context_p (tree type1, tree type2)
return 0;
}
-/* Return 1 iff there exists a common enclosing context between TYPE1
- and TYPE2. */
+
+/* Return 1 iff TYPE1 and TYPE2 share a common enclosing class, regardless of
+ nesting level. */
int
common_enclosing_context_p (tree type1, tree type2)
{
+ for (type1; type1;
+ type1 = (INNER_CLASS_TYPE_P (type1) ?
+ TREE_TYPE (DECL_CONTEXT (TYPE_NAME (type1))) : NULL_TREE))
+ {
+ tree current;
+ for (current = type2; current;
+ current = (INNER_CLASS_TYPE_P (current) ?
+ TREE_TYPE (DECL_CONTEXT (TYPE_NAME (current))) :
+ NULL_TREE))
+ if (type1 == current)
+ return 1;
+ }
+ return 0;
+}
+
+/* Return 1 iff there exists a common enclosing "this" between TYPE1
+ and TYPE2, without crossing any static context. */
+
+int
+common_enclosing_instance_p (tree type1, tree type2)
+{
if (!PURE_INNER_CLASS_TYPE_P (type1) || !PURE_INNER_CLASS_TYPE_P (type2))
return 0;
diff --git a/gcc/java/java-tree.h b/gcc/java/java-tree.h
index 1fef832..d9e6415 100644
--- a/gcc/java/java-tree.h
+++ b/gcc/java/java-tree.h
@@ -1238,6 +1238,7 @@ extern int get_access_flags_from_decl (tree);
extern int interface_of_p (tree, tree);
extern int inherits_from_p (tree, tree);
extern int common_enclosing_context_p (tree, tree);
+extern int common_enclosing_instance_p (tree, tree);
extern int enclosing_context_p (tree, tree);
extern tree build_result_decl (tree);
extern void emit_handlers (void);
diff --git a/gcc/java/jcf-write.c b/gcc/java/jcf-write.c
index c95df1e..e34543c 100644
--- a/gcc/java/jcf-write.c
+++ b/gcc/java/jcf-write.c
@@ -2903,6 +2903,22 @@ get_classfile_modifiers (tree class)
return flags;
}
+/* Get the access flags (modifiers) for a method to be used in the class
+ file. */
+
+static int
+get_method_access_flags (tree decl)
+{
+ int flags = get_access_flags (decl);
+
+ /* Promote "private" inner-class constructors to package-private. */
+ if (DECL_CONSTRUCTOR_P (decl)
+ && INNER_CLASS_DECL_P (TYPE_NAME (DECL_CONTEXT (decl))))
+ flags &= ~(ACC_PRIVATE);
+
+ return flags;
+}
+
/* Generate and return a list of chunks containing the class CLAS
in the .class file representation. The list can be written to a
.class file using write_chunks. Allocate chunks from obstack WORK. */
@@ -3034,7 +3050,7 @@ generate_classfile (tree clas, struct jcf_partial *state)
current_function_decl = part;
ptr = append_chunk (NULL, 8, state);
- i = get_access_flags (part); PUT2 (i);
+ i = get_method_access_flags (part); PUT2 (i);
i = find_utf8_constant (&state->cpool, name); PUT2 (i);
i = find_utf8_constant (&state->cpool, build_java_signature (type));
PUT2 (i);
diff --git a/gcc/java/parse.h b/gcc/java/parse.h
index cf62dae..f0fb67a 100644
--- a/gcc/java/parse.h
+++ b/gcc/java/parse.h
@@ -842,7 +842,7 @@ struct parser_ctxt GTY(()) {
!= TYPE_NAME (TREE_TYPE (TREE_TYPE (current_this)))) \
&& !inherits_from_p (TREE_TYPE (TREE_TYPE (current_this)), \
TREE_TYPE (DECL_CONTEXT (TYPE_NAME (T)))) \
- && !common_enclosing_context_p (TREE_TYPE (TREE_TYPE (current_this)), \
+ && !common_enclosing_instance_p (TREE_TYPE (TREE_TYPE (current_this)),\
(T)) \
&& INNER_CLASS_TYPE_P (TREE_TYPE (TREE_TYPE (current_this))) \
&& !inherits_from_p \
diff --git a/gcc/java/parse.y b/gcc/java/parse.y
index 3df330d..8d65bd1 100644
--- a/gcc/java/parse.y
+++ b/gcc/java/parse.y
@@ -320,7 +320,7 @@ static int outer_field_expanded_access_p (tree, tree *,
static tree outer_field_access_fix (tree, tree, tree);
static tree build_incomplete_class_ref (int, tree);
static tree patch_incomplete_class_ref (tree);
-static tree create_anonymous_class (int, tree);
+static tree create_anonymous_class (tree);
static void patch_anonymous_class (tree, tree, tree);
static void add_inner_class_fields (tree, tree);
@@ -2034,7 +2034,7 @@ class_instance_creation_expression:
anonymous_class_creation:
NEW_TK class_type OP_TK argument_list CP_TK
- { create_anonymous_class ($1.location, $2); }
+ { create_anonymous_class ($2); }
class_body
{
tree id = build_wfl_node (DECL_NAME (GET_CPC ()));
@@ -2067,7 +2067,7 @@ anonymous_class_creation:
}
| NEW_TK class_type OP_TK CP_TK
- { create_anonymous_class ($1.location, $2); }
+ { create_anonymous_class ($2); }
class_body
{
tree id = build_wfl_node (DECL_NAME (GET_CPC ()));
@@ -3905,8 +3905,11 @@ patch_anonymous_class (tree type_decl, tree class_decl, tree wfl)
}
}
+/* Create an anonymous class which extends/implements TYPE_NAME, and return
+ its decl. */
+
static tree
-create_anonymous_class (int location, tree type_name)
+create_anonymous_class (tree type_name)
{
char buffer [80];
tree super = NULL_TREE, itf = NULL_TREE;
@@ -3915,7 +3918,7 @@ create_anonymous_class (int location, tree type_name)
/* The unqualified name of the anonymous class. It's just a number. */
sprintf (buffer, "%d", anonymous_class_counter++);
id = build_wfl_node (get_identifier (buffer));
- EXPR_WFL_LINECOL (id) = location;
+ EXPR_WFL_LINECOL (id) = EXPR_WFL_LINECOL (type_name);
/* We know about the type to extend/implement. We go ahead */
if ((type_decl = IDENTIFIER_CLASS_VALUE (EXPR_WFL_NODE (type_name))))
@@ -4035,7 +4038,7 @@ create_class (int flags, tree id, tree super, tree interfaces)
/* 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. */
+ This does not occur for top level (static) inner classes. */
if (PURE_INNER_CLASS_DECL_P (decl))
add_inner_class_fields (decl, current_function_decl);
@@ -5393,8 +5396,9 @@ craft_constructor (tree class_decl, tree args)
{
tree class_type = TREE_TYPE (class_decl);
tree parm = NULL_TREE;
- int flags = (get_access_flags_from_decl (class_decl) & ACC_PUBLIC ?
- ACC_PUBLIC : 0);
+ /* Inherit access flags for the constructor from its enclosing class. */
+ int valid_ctor_flags = ACC_PUBLIC | ACC_PROTECTED | ACC_PRIVATE;
+ int flags = (get_access_flags_from_decl (class_decl) & valid_ctor_flags);
int i = 0, artificial = 0;
tree decl, ctor_name;
char buffer [80];
@@ -9961,7 +9965,7 @@ resolve_qualified_expression_name (tree wfl, tree *found_decl,
/* Check on accessibility here */
if (not_accessible_p (current_class, field_decl,
- DECL_CONTEXT (field_decl), from_super))
+ *type_found, from_super))
return not_accessible_field_error (qual_wfl,field_decl);
check_deprecation (qual_wfl, field_decl);
@@ -10047,10 +10051,13 @@ static int
not_accessible_p (tree reference, tree member, tree where, int from_super)
{
int access_flag = get_access_flags_from_decl (member);
-
- /* Inner classes are processed by check_inner_class_access */
- if (INNER_CLASS_TYPE_P (reference))
- return 0;
+ bool is_static = false;
+
+ if (TREE_CODE (member) == FIELD_DECL ||
+ TREE_CODE (member) == VAR_DECL)
+ is_static = FIELD_STATIC (member);
+ else
+ is_static = METHOD_STATIC (member);
/* Access always granted for members declared public */
if (access_flag & ACC_PUBLIC)
@@ -10069,26 +10076,34 @@ not_accessible_p (tree reference, tree member, tree where, int from_super)
if (from_super)
return 0;
- /* If where is active, access was made through a
- qualifier. Access is granted if the type of the qualifier is
- or is a sublass of the type the access made from (6.6.2.1.) */
- if (where && !inherits_from_p (reference, where))
- return 1;
-
- /* Otherwise, access is granted if occurring from the class where
- member is declared or a subclass of it. Find the right
- context to perform the check */
- if (PURE_INNER_CLASS_TYPE_P (reference))
+ /* If WHERE is active, access was made through a qualifier. For
+ non-static members, access is granted if the type of the qualifier
+ is or is a sublass of the type the access is made from (6.6.2.1.) */
+ if (where && !is_static)
{
- while (INNER_CLASS_TYPE_P (reference))
+ while (reference)
{
- if (inherits_from_p (reference, DECL_CONTEXT (member)))
- return 0;
- reference = TREE_TYPE (DECL_CONTEXT (TYPE_NAME (reference)));
- }
+ if (inherits_from_p (where, reference))
+ return 0;
+ if (PURE_INNER_CLASS_TYPE_P (reference))
+ reference = TREE_TYPE (DECL_CONTEXT (TYPE_NAME (reference)));
+ else
+ break;
+ }
+ return 1;
+ }
+
+ /* Otherwise, access is granted if occurring from within the class
+ where member is declared, or a subclass of it. */
+ while (reference)
+ {
+ if (inherits_from_p (reference, DECL_CONTEXT (member)))
+ return 0;
+ if (PURE_INNER_CLASS_TYPE_P (reference))
+ reference = TREE_TYPE (DECL_CONTEXT (TYPE_NAME (reference)));
+ else
+ break;
}
- if (inherits_from_p (reference, DECL_CONTEXT (member)))
- return 0;
return 1;
}
@@ -10097,9 +10112,8 @@ not_accessible_p (tree reference, tree member, tree where, int from_super)
it for innerclasses too. */
if (access_flag & ACC_PRIVATE)
{
- if (reference == DECL_CONTEXT (member))
- return 0;
- if (enclosing_context_p (reference, DECL_CONTEXT (member)))
+ if (reference == DECL_CONTEXT (member) ||
+ common_enclosing_context_p (DECL_CONTEXT (member), reference))
return 0;
return 1;
}
@@ -10506,8 +10520,6 @@ patch_method_invocation (tree patch, tree primary, tree where, int from_super,
IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (current_class)));
const char *const what = (DECL_CONSTRUCTOR_P (list)
? "constructor" : "method");
- /* FIXME: WFL yields the wrong message here but I don't know
- what else to use. */
parse_error_context (wfl,
"Can't access %s %s `%s.%s' from `%s'",
access, what, klass, fct_name, refklass);
@@ -12343,6 +12355,10 @@ build_super_invocation (tree mdecl)
else
{
tree super_wfl = build_wfl_node (super_identifier_node);
+ /* This is called after parsing is done, so the parser context
+ won't be accurate. Set location info from current_class decl. */
+ tree class_wfl = lookup_cl (TYPE_NAME (current_class));
+ EXPR_WFL_LINECOL (super_wfl) = EXPR_WFL_LINECOL (class_wfl);
tree a = NULL_TREE, t;
/* If we're dealing with an anonymous class, pass the arguments
of the crafted constructor along. */
@@ -13922,7 +13938,7 @@ build_incomplete_class_ref (int location, tree class_name)
/* 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);
+ inner = create_anonymous_class (t);
target_class = TREE_TYPE (inner);
end_class_declaration (1);
GET_CPC_LIST() = cpc_list;