This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: [bug] Inheritance and friend access control broken
- To: Alexandre Oliva <oliva at dcc dot unicamp dot br>
- Subject: Re: [bug] Inheritance and friend access control broken
- From: Gabriel Dos Reis <Gabriel dot Dos-Reis at dptmaths dot ens-cachan dot fr>
- Date: Wed, 4 Mar 1998 12:25:07 +0100 (MET)
- Cc: Gabriel Dos Reis <Gabriel dot Dos-Reis at dptmaths dot ens-cachan dot fr>, egcs at cygnus dot com
- References: <199803032141.WAA09332@piano.dptmaths.ens-cachan.fr><orhg5ff544.fsf@iguacu.dcc.unicamp.br>
>>>>> ĞAlexandreğ, Alexandre Oliva <oliva@dcc.unicamp.br> wrote:
Alexandre> Gabriel Dos Reis writes:
>> protected member field access control seems to be broken in EGCS-980205.
Alexandre> I don't think your example is correct. Friendship is not transitive;
Alexandre> just because f() is friend of D, it doesn't mean it has any
Alexandre> priviledged access to B. However, since B::j is a member of D
Alexandre> (inherited from B), f() can access it as such.
The FDIS says :
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
______________________________________________________________________
11 Member access control [class.access]
______________________________________________________________________
1 A member of a class can be
--private; that is, its name can be used only by members and friends
of the class in which it is declared.
--protected; that is, its name can be used only by members and friends
of the class in which it is declared, and by members and friends of
classes derived from this class (see _class.protected_).
--public; that is, its name can be used anywhere without access
restriction.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
And further in 11.5 there is this clause:
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11.5 Protected member access [class.protected]
1 When a friend or a member function of a derived class references a
protected nonstatic member of a base class, an access check applies in
addition to those described earlier in clause _class.access_.4) Except
when forming a pointer to member (_expr.unary.op_), the access must be
through a pointer to, reference to, or object of the derived class
itself (or any class derived from that class) (_expr.ref_). If the
access is to form a pointer to member, the nested-name-specifier shall
name the derived class (or any class derived from that class). [Exam-
ple:
class B {
protected:
int i;
static int j;
};
class D1 : public B {
};
class D2 : public B {
friend void fr(B*,D1*,D2*);
void mem(B*,D1*);
};
_________________________
4) This additional check does not apply to other members, e.g. static
data members or enumerator member constants.
void fr(B* pb, D1* p1, D2* p2)
{
pb->i = 1; // ill-formed
p1->i = 2; // ill-formed
p2->i = 3; // OK (access through a D2)
p2->B::i = 4; // OK (access through a D2, even though
Z *pz; // naming class is B)
int B::* pmi_B = &B::i; // ill-formed
int B::* pmi_B2 = &D2::i; // OK (type of &D2::i is int B::*)
B::j = 5; // OK (because refers to static member)
D2::j =6; // OK (because refers to static member)
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
As you can note B::j is accessible in fr(B*, D1*, D2*) which is a
friend of class D2 derived form class B. We are exactly in the
sirtuation I reported.
-- Gaby