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
This commit is contained in:
Nathan Sidwell 2001-03-26 08:37:27 +00:00 committed by Nathan Sidwell
parent 04c5433d68
commit 788bf0e34e
9 changed files with 165 additions and 27 deletions

View File

@ -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.

View File

@ -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));

View File

@ -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++ */

View File

@ -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 ();
}
;

View File

@ -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 ();

View File

@ -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.

View File

@ -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;

View File

@ -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;

View File

@ -2,6 +2,7 @@
// Build don't link:
class foo {
public:
typedef int sometype;
};