[cfe-dev] [PATCH] Friend class cannot access protected field of parent

Olivier Goffart ogoffart at kde.org
Tue Jun 8 00:23:56 PDT 2010


Le Tuesday 08 June 2010, John McCall a écrit :
> On Jun 7, 2010, at 8:36 AM, Olivier Goffart wrote:
> > So I spend my week end, trying to get into the clang code. I chosen to
> > try to fix Bug 6840 [1] which is one of the last issue preventing Qt to
> > compile.
> > 
> > 
> > So the problem is with code like this:
> > 
> > class N { protected: static int m; };
> > class P : public N { friend class R; };
> > class R { int foo() { return N::n; } };
> > 
> > The C++ specification says that [class.access.base]
> > A member m is accessible at the point R when named in class N if [...]
> > m as a member of N is protected, and R occurs in a [...] friend of a
> > class P derived from N, where m as a member of P is public, private, or
> > protected
> > 
> > So this code should compile, because in R::foo() we can access N::m
> > though P's friendship.
> 
> Actually, I intentionally haven't implemented this rule yet.  It is either
> a drafting error or a horrible mistake.  It neuters the entire 'protected'
> specifier, it makes the well-formedness of code dependent on the
> existence of completely unrelated classes, it imposes high costs on the
> implementation, and it's formally undecidable in the presence of templates.
> To wit:

I must agree this is weird. But this is the specification, and there is code 
that uses such constructs

>   // Assume this has lots of specializations
>   template <class> class Predicate;
> 
>   class A { protected: typedef int foo; };
>   template <class T, bool = Predicate<T>::value> class B {};
>   template <class T> class B<T, true> : public A { friend class C; };
> 
>   class C { A::foo x };
> 
> This reference is well-formed if and only if there exists a class T for
> which Predicate<T>::value is true.


I just noticed that my implementation of the patch always say that this code 
is valid.
GCC only accept the code if there is an instantiation of B<T,true>.
I guess I can modify the patch to require instantiation if needed.

> For a somewhat less abstract example, consider instead:
>   template <class> class D;
>   template <class T> class E : public D<T> { friend class C; };
> Now 'C' is ill-formed unless there's a specialization of D which derives
> from A.

Both with gcc and my patch, this will be ill-formed unless there is an 
instantiation of E which makes it derives from A

But I get your point.

Also would code like 
template<class T, class U> class A : T { friend class U; };
mean that every protected is public.

GCC forces instantiations, and i think it is a sensible choice.


So you think it is better not to try to make it work, even for the non-
template case?

-- 
Olivier







More information about the cfe-dev mailing list