Patch to correct compilation errors related to class friend declarations

I checked out cfe/trunk today and attempted a build using an older gcc compiler (4.0.3) on Linux. The build failed in a few places with the errors below. The attached patch corrects these. Each of the errors was related to class friend declarations.

llvm-trunk/tools/clang/include/clang/Basic/Diagnostic.h:590: error: 'clang::DiagnosticsEngine::<anonymous enum> clang::DiagnosticsEngine::MaxArguments' is private
llvm-trunk/tools/clang/include/clang/Basic/PartialDiagnostic.h:36: error: within this context
llvm-trunk/tools/clang/include/clang/Basic/Diagnostic.h:621: error: 'clang::DiagnosticsEngine::<anonymous enum> clang::DiagnosticsEngine::MaxFixItHints' is private
llvm-trunk/tools/clang/include/clang/Basic/PartialDiagnostic.h:68: error: within this context

This error looks legit to me. The code appears to be violating C++03 11.4.2 [class.friend] and 11.8.1 [class.access.nest]. Granting friendship to a class does not confer friendship to nested classes of the befriended class. Since, as far as I know, there is no way to forward declare a nested class without first defining the parent class, nor to grant friendship to a nested class of an undefined class, I "fixed" this by proxying the enum constants through the befriended class. It might make more sense to simply make these few enum types public.

llvm-trunk/tools/clang/include/clang/Parse/Parser.h: In destructor 'clang::Parser::BalancedDelimiterTracker::~BalancedDelimiterTracker()':
llvm-trunk/tools/clang/include/clang/Parse/Parser.h:439: error: 'void clang::Parser::DelimiterTracker::pop(clang::tok::TokenKind)' is private
llvm-trunk/tools/clang/include/clang/Parse/Parser.h:479: error: within this context

This error also looks legit to me. A nested class is attempting to access a private method of a peer nested class without being declared a friend. This appears to me to violate C++03 11.8.1 [class.access.nest]. The patch adds a friendship declaration and a forward declaration for the befriended class.

Tom.

clang-friend-fixes.patch (2.3 KB)

It does, actually:
  [class.access]p2: A member of a class can also access all the names to which the class has access.
  [class.access.nest]p1: A nested class is a member and as such has the same access rights as any other member.
It's the other way that doesn't hold; having access to a class doesn't give you access to its nested classes.

John.

I checked out cfe/trunk today and attempted a build using an older
gcc compiler (4.0.3) on Linux. The build failed in a few places
with the errors below. The attached patch corrects these. Each of
the errors was related to class friend declarations.

llvm-trunk/tools/clang/include/clang/Basic/Diagnostic.h:590: error: 'clang::DiagnosticsEngine::<anonymous enum> clang::DiagnosticsEngine::MaxArguments' is private
llvm-trunk/tools/clang/include/clang/Basic/PartialDiagnostic.h:36: error: within this context
llvm-trunk/tools/clang/include/clang/Basic/Diagnostic.h:621: error: 'clang::DiagnosticsEngine::<anonymous enum> clang::DiagnosticsEngine::MaxFixItHints' is private
llvm-trunk/tools/clang/include/clang/Basic/PartialDiagnostic.h:68: error: within this context

This error looks legit to me. The code appears to be violating
C++03 11.4.2 [class.friend] and 11.8.1 [class.access.nest].
Granting friendship to a class does not confer friendship to nested
classes of the befriended class.

It does, actually: [class.access]p2: A member of a class can also
access all the names to which the class has access.
[class.access.nest]p1: A nested class is a member and as such has the
same access rights as any other member. It's the other way that
doesn't hold; having access to a class doesn't give you access to
its nested classes.

It looks like you are quoting from C++11 (or draft) and that the behavior has changed from C++03 (or, there was a CWG defect related to this?). C++03 11.4.2 [class.friend] and 11.8.1 [class.access.nest] are explicit that friendship does not confer to nested classes of a befriended class. The example from C++03 11.4.2 is:

     class A {
         class B { };
         friend class X;
     };
     class X : A::B { // ill-formed: A::B cannot be accessed
                           // in the base-clause for X
         class Y : A::B { // OK: A::B used to declare member of X
                           // to declare members of nested class of X
         };
     };

C++03 11.8.1 states: "The members of a nested class have no special access to members of an enclosing class, nor to classes or functions that have granted friendship to an enclosing class"

Tom.

Yes, this was DR 45, with proposed resolution as stated in 2001. It didn't make it into C++03 because <bureaucracy>.
  C++ Standard Core Language Defect Reports and Accepted Issues

John.

I went ahead and committed this as r144161, thanks!

  - Doug