[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