From 788bf0e34ebec318ef42f6a7ffd9e8632756908a Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Mon, 26 Mar 2001 08:37:27 +0000 Subject: [PATCH] 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 --- gcc/cp/ChangeLog | 17 +++++ gcc/cp/cp-tree.h | 2 + gcc/cp/decl.c | 51 ++++++------- gcc/cp/parse.y | 2 + gcc/cp/semantics.c | 36 +++++++++- gcc/testsuite/ChangeLog | 6 ++ .../g++.old-deja/g++.other/friend12.C | 71 +++++++++++++++++++ .../g++.old-deja/g++.other/friend9.C | 6 +- gcc/testsuite/g++.old-deja/g++.robertl/eb56.C | 1 + 9 files changed, 165 insertions(+), 27 deletions(-) create mode 100644 gcc/testsuite/g++.old-deja/g++.other/friend12.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 63ce6c9ba60..3b89a973e06 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,20 @@ +2001-03-26 Nathan Sidwell + + 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 * class.c (add_method): Use memcpy/memmove, not bcopy. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 28f519dd29b..5015349156a 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 04d4c4ffc59..03f94a35fa1 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 3d4ab4400f6..f13614b750a 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 6e037f4d727..c99a0db4e70 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 d8d9633990e..86736d39462 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2001-03-26 Nathan Sidwell + + * 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 * 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 00000000000..df767b35d14 --- /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 + +// 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 442d9899e3a..e51b0274c66 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 2d497f8b4e3..2249a40b24c 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; }; -- 2.30.2