aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@codesourcery.com>2001-03-26 08:37:27 +0000
committerNathan Sidwell <nathan@gcc.gnu.org>2001-03-26 08:37:27 +0000
commit788bf0e34ebec318ef42f6a7ffd9e8632756908a (patch)
treee80deebc6a447417a1ef0f9eae56f55fd7dabfbb /gcc
parent04c5433d684a6e22d266a2bd067eb42e28ee9d60 (diff)
downloadgcc-788bf0e34ebec318ef42f6a7ffd9e8632756908a.zip
gcc-788bf0e34ebec318ef42f6a7ffd9e8632756908a.tar.gz
gcc-788bf0e34ebec318ef42f6a7ffd9e8632756908a.tar.bz2
Implement DR 209
cp: Implement DR 209 * cp-tree.h (skip_type_access_control, reset_type_access_control): Prototype. * decl.c (grokdeclarator): Access of friends is not checked. * parse.y (component_decl_list): Reset type access control. * semantics.c (decl_type_access_control): Clear current_type_lookups. (save_type_access_control): Don't save if not deferring. (skip_type_access_control, reset_type_access_control): New functions. (begin_class_definition): Do type access control for basetypes. Start deferred access control. (finish_class_definition): Resume immediate access control if this is a local class. testsuite: * g++.old-deja/g++.other/friend12.C: New test. * g++.old-deja/g++.other/friend9.C: Expect no errors. * g++.old-deja/g++.robertl/eb56.C: Make typedef public. From-SVN: r40841
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog17
-rw-r--r--gcc/cp/cp-tree.h2
-rw-r--r--gcc/cp/decl.c51
-rw-r--r--gcc/cp/parse.y2
-rw-r--r--gcc/cp/semantics.c36
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/friend12.C71
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/friend9.C6
-rw-r--r--gcc/testsuite/g++.old-deja/g++.robertl/eb56.C1
9 files changed, 165 insertions, 27 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 63ce6c9..3b89a97 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,20 @@
+2001-03-26 Nathan Sidwell <nathan@codesourcery.com>
+
+ Implement DR 209
+ * cp-tree.h (skip_type_access_control,
+ reset_type_access_control): Prototype.
+ * decl.c (grokdeclarator): Access of friends is not checked.
+ * parse.y (component_decl_list): Reset type access control.
+ * semantics.c (decl_type_access_control): Clear
+ current_type_lookups.
+ (save_type_access_control): Don't save if not deferring.
+ (skip_type_access_control, reset_type_access_control): New
+ functions.
+ (begin_class_definition): Do type access control for basetypes.
+ Start deferred access control.
+ (finish_class_definition): Resume immediate access control if
+ this is a local class.
+
2001-03-25 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* class.c (add_method): Use memcpy/memmove, not bcopy.
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 28f519d..5015349 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -4175,6 +4175,8 @@ extern tree get_binfo PARAMS ((tree, tree, int));
extern int get_base_distance PARAMS ((tree, tree, int, tree *));
extern tree get_dynamic_cast_base_type PARAMS ((tree, tree));
extern void type_access_control PARAMS ((tree, tree));
+extern void skip_type_access_control PARAMS ((void));
+extern void reset_type_access_control PARAMS ((void));
extern int accessible_p PARAMS ((tree, tree));
extern tree lookup_field PARAMS ((tree, tree, int, int));
extern int lookup_fnfields_1 PARAMS ((tree, tree));
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 04d4c4f..03f94a3 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -11131,7 +11131,9 @@ friend declaration requires class-key, i.e. `friend %#T'",
/* Only try to do this stuff if we didn't already give up. */
if (type != integer_type_node)
{
- decl_type_access_control (TYPE_NAME (type));
+ /* DR 209. The friendly class does not need to be accessible
+ in the scope of the class granting friendship. */
+ skip_type_access_control ();
/* A friendly class? */
if (current_class_type)
@@ -11393,32 +11395,33 @@ friend declaration requires class-key, i.e. `friend %#T'",
if (friendp)
{
/* Friends are treated specially. */
+ tree t = NULL_TREE;
+
+ /* DR 209. The friend does not need to be accessible at this
+ point. */
+ skip_type_access_control ();
+
if (ctype == current_class_type)
warning ("member functions are implicitly friends of their class");
- else
- {
- tree t = NULL_TREE;
- if (decl && DECL_NAME (decl))
- {
- if (template_class_depth (current_class_type) == 0)
- {
- decl
- = check_explicit_specialization
- (declarator, decl,
- template_count, 2 * (funcdef_flag != 0) + 4);
- if (decl == error_mark_node)
- return error_mark_node;
- }
- t = do_friend (ctype, declarator, decl,
- last_function_parms, attrlist, flags, quals,
- funcdef_flag);
- }
- if (t && funcdef_flag)
- return t;
-
- return void_type_node;
- }
+ if (decl && DECL_NAME (decl))
+ {
+ if (template_class_depth (current_class_type) == 0)
+ {
+ decl = check_explicit_specialization
+ (declarator, decl,
+ template_count, 2 * (funcdef_flag != 0) + 4);
+ if (decl == error_mark_node)
+ return error_mark_node;
+ }
+
+ t = do_friend (ctype, declarator, decl,
+ last_function_parms, attrlist, flags, quals,
+ funcdef_flag);
+ }
+ if (t && funcdef_flag)
+ return t;
+ return void_type_node;
}
/* Structure field. It may not be a function, except for C++ */
diff --git a/gcc/cp/parse.y b/gcc/cp/parse.y
index 3d4ab44..f13614b 100644
--- a/gcc/cp/parse.y
+++ b/gcc/cp/parse.y
@@ -2548,11 +2548,13 @@ component_decl_list:
{
finish_member_declaration ($1);
current_aggr = NULL_TREE;
+ reset_type_access_control ();
}
| component_decl_list component_decl
{
finish_member_declaration ($2);
current_aggr = NULL_TREE;
+ reset_type_access_control ();
}
;
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 6e037f4..c99a0db4 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -1593,13 +1593,41 @@ decl_type_access_control (decl)
added to type_lookups after typed_declspecs saved the copy that
ended up in current_type_lookups. */
type_lookups = current_type_lookups;
+
+ current_type_lookups = NULL_TREE;
}
+/* Record the lookups, if we're doing deferred access control. */
+
void
save_type_access_control (lookups)
tree lookups;
{
- current_type_lookups = lookups;
+ if (type_lookups != error_mark_node)
+ {
+ my_friendly_assert (!current_type_lookups, 20010301);
+ current_type_lookups = lookups;
+ }
+ else
+ my_friendly_assert (!lookups || lookups == error_mark_node, 20010301);
+}
+
+/* Set things up so that the next deferred access control will succeed.
+ This is needed for friend declarations see grokdeclarator for details. */
+
+void
+skip_type_access_control ()
+{
+ type_lookups = NULL_TREE;
+}
+
+/* Reset the deferred access control. */
+
+void
+reset_type_access_control ()
+{
+ type_lookups = NULL_TREE;
+ current_type_lookups = NULL_TREE;
}
/* Begin a function definition declared with DECL_SPECS and
@@ -1732,6 +1760,10 @@ tree
begin_class_definition (t)
tree t;
{
+ /* Check the bases are accessible. */
+ decl_type_access_control (TYPE_NAME (t));
+ reset_type_access_control ();
+
if (processing_template_parmlist)
{
cp_error ("definition of `%#T' inside template parameter list", t);
@@ -1953,6 +1985,8 @@ finish_class_definition (t, attributes, semi, pop_scope_p)
check_for_missing_semicolon (t);
if (pop_scope_p)
pop_scope (CP_DECL_CONTEXT (TYPE_MAIN_DECL (t)));
+ if (current_function_decl)
+ type_lookups = error_mark_node;
if (current_scope () == current_function_decl)
do_pending_defargs ();
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index d8d96339..86736d3 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2001-03-26 Nathan Sidwell <nathan@codesourcery.com>
+
+ * g++.old-deja/g++.other/friend12.C: New test.
+ * g++.old-deja/g++.other/friend9.C: Expect no errors.
+ * g++.old-deja/g++.robertl/eb56.C: Make typedef public.
+
2001-03-25 Joseph S. Myers <jsm28@cam.ac.uk>
* gcc.c-torture/execute/20010325-1.c: New test.
diff --git a/gcc/testsuite/g++.old-deja/g++.other/friend12.C b/gcc/testsuite/g++.old-deja/g++.other/friend12.C
new file mode 100644
index 0000000..df767b3
--- /dev/null
+++ b/gcc/testsuite/g++.old-deja/g++.other/friend12.C
@@ -0,0 +1,71 @@
+// Build don't link:
+
+// Copyright (C) 2001 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 1 Mar 2001 <nathan@codesourcery.com>
+
+// DR 209. friend access is not checked.
+
+class Z;
+class A
+{
+ class Inner {}; // ERROR - private
+ Inner f (Inner);
+ public:
+ A ();
+ friend class Z;
+};
+
+class B
+{
+ A::Inner j (); // ERROR - private
+ A::Inner k (); // ERROR - private
+ friend A::Inner A::f (Inner);
+ int t;
+ friend class A::Inner;
+};
+
+A::Inner l (); // ERROR - private
+A::Inner m (); // ERROR - private
+A::Inner a, // ERROR - private
+ b; // ERROR - private
+A::Inner a1; // ERROR - private
+int b2;
+
+A::Inner A::f (Inner)
+{
+ B b;
+ b.t = 1;
+ return A::Inner ();
+}
+
+void Foo ()
+{
+ A::Inner i; // ERROR - private
+ class Local
+ {
+ friend A::Inner A::f (Inner);
+ A::Inner k; // ERROR - private
+ };
+ class Local1 : A::Inner
+ { // ERROR - private
+
+ };
+ A::Inner k; // ERROR - private
+}
+
+class X : A::Inner
+{ // ERROR - private
+ class I : A::Inner
+ { // ERROR - private
+
+ };
+};
+
+class Z : A::Inner
+{ // ERROR - private
+ class I : A::Inner
+ { // ok, the base A::Inner is in the scope of Z which is a friend of A
+
+ };
+};
+int b4;
diff --git a/gcc/testsuite/g++.old-deja/g++.other/friend9.C b/gcc/testsuite/g++.old-deja/g++.other/friend9.C
index 442d989..e51b027 100644
--- a/gcc/testsuite/g++.old-deja/g++.other/friend9.C
+++ b/gcc/testsuite/g++.old-deja/g++.other/friend9.C
@@ -5,14 +5,16 @@
// Bug 853: We reported the wrong line no for a friend access violation
+// Since DR 209, friend declaration access is not checked.
+
class F
{
- class Internal; // ERROR - is private
+ class Internal;
};
class C
{
- friend class F::Internal; // ERROR - in this context
+ friend class F::Internal;
public:
typedef enum { A, B } e;
diff --git a/gcc/testsuite/g++.old-deja/g++.robertl/eb56.C b/gcc/testsuite/g++.old-deja/g++.robertl/eb56.C
index 2d497f8b..2249a40 100644
--- a/gcc/testsuite/g++.old-deja/g++.robertl/eb56.C
+++ b/gcc/testsuite/g++.old-deja/g++.robertl/eb56.C
@@ -2,6 +2,7 @@
// Build don't link:
class foo {
+ public:
typedef int sometype;
};