Bug 52136 - g++ is wrongly propagating "friend class" to the parent class
Summary: g++ is wrongly propagating "friend class" to the parent class
Status: RESOLVED INVALID
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.6.2
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2012-02-06 13:14 UTC by Sylvestre Ledru
Modified: 2014-02-16 13:15 UTC (History)
0 users

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Sylvestre Ledru 2012-02-06 13:14:21 UTC
---
class address 
{
protected:
    static int parseNext(int a);
};


class mailbox : public address
{
    friend class mailboxField;
};

class mailboxField
{
    void parse(int a)
        {
            address::parseNext(a);
            // will work with:
            // mailbox::parseNext(a);
        }
};
---

It should trigger:
address.cpp: In member function ‘void mailboxField::parse(int)’:
address.cpp:4:16: error: ‘static int address::parseNext(int)’ is protected
address.cpp:17:33: error: within this context

Tested with g++ 4.6.2
Comment 1 Jonathan Wakely 2012-02-06 13:40:08 UTC
EDG and Solaris CC also accept it, clang doesn't

The code looks similar to this example from [class.protected] in the standard:

class B {
protected:
    int i;
    static int j;
};
class D1 : public B {
};
class D2 : public B {
    friend void fr(B*,D1*,D2*);
};
void fr(B* pb, D1* p1, D2* p2) {
    // ...
    p2->i = 3;    // OK (access through a D2)
    p2->B::i = 4; // OK (access through a D2, even though
                  // naming class is B)
    // ...
    B::j = 5;     // OK (because refers to static member)
    D2::j = 6;    // OK (because refers to static member)
}

Note that the friend of D2 can access non-static members of B through D2* and can access static members of B directly.
Comment 2 Jonathan Wakely 2012-02-06 13:50:40 UTC
I think G++ is correct here.

[class.protected]p1
An additional access check beyond those described earlier in Clause 11 is applied when a non-static data member or non-static member function is a protected member of its naming class (11.2)*

* This additional check does not apply to other members, e.g., static data members or enumerator member constants.


address::parseNext refers to the same entity as mailbox::parseNext and access to static members does not involve an object expression, so there is no need for that access to be done through an object expression of the derived type.
Comment 3 Jonathan Wakely 2012-02-06 13:56:58 UTC
Clang gets this wrong on purpose: http://llvm.org/bugs/show_bug.cgi?id=6840

But G++ implements what the standard says, so INVALID
Comment 4 Sylvestre Ledru 2012-02-06 14:08:21 UTC
I found this bug (or behavior) while playing with clang. 

I am not really sure to understand why friend class should impact his parent but if g++ respects the standard, why not...
Comment 5 Jonathan Wakely 2012-02-06 14:24:39 UTC
(In reply to comment #4)
> I am not really sure to understand why friend class should impact his parent
> but if g++ respects the standard, why not...

It doesn't "impact his parent"

Read comment 2 again.  To access a protected non-static member you must do so though an object expression of the derived type, because in the expression 'p->address::m' you only know if 'm' is a member of a 'mailbox' object when 'p' has type 'mailbox*'

But for a static member that is irrelevant, the static member just exists independently of any 'mailbox' or 'address' instance, so if mailboxField can access members of 'mailbox' then it can access the static member, and it doesn't matter if you refer to it as 'mailbox::parseNext' or 'address::parseNext' because both refer to the exact same entity.
Comment 6 Jackie Rosen 2014-02-16 13:15:47 UTC Comment hidden (spam)