Topic: Nested classes: is this a bug in IBM's compiler?


Author: fjh@munta.cs.mu.OZ.AU (Fergus Henderson)
Date: Sat, 15 Jan 1994 17:26:07 GMT
Raw View
matt@physics16.berkeley.edu (Matt Austern) writes:

>The question, essentially, is whether the presence of an access
>specifier changes the behavior of a nested class.
[...]
>When I compile this using C Set++, I get the error message
>foo.cc(16:1) : error EDC3016: private member "outer::inner" cannot be accessed.
>
>That is, the compiler thinks that the class outer::inner is in some
>sense private (it follows the access specifier private, after all),
>and that objects of this type can only be created or accessed accessed
>by members of outer.  Note that the constructor of outer::inner itself
>is declared as public, and that outer::inner has no private members.
>
>The problem is that, I can't find any indication in the ARM's
>discussion of nested classes that access specifiers ought to behave
>this way.  Class nesting, as far as I can tell, should only affect
>scope, not access permission.
>
>I compiled this same code using gcc and cfront, both of which agree
>with my interpretation---they both compiled it with no errors or
>warnings.  So, the question: are gcc, cfront, and I wrong, or is
>C Set++ wrong?

I'm afraid that gcc, cfront, and you are all wrong, and C Set++ is right.
The commentary at the start of chapter 11 makes it clear that nested
classes _are_ subject to access control:

 "Access control applies uniformly to function members, data
 members, member constants, and nested types".

If you want a quote from the main text rather than the commentary, then
consider ARM 9.2:

 "A member-list may declare ... classes ...
  A member-list may also contain declarations adjusting the access
  to member names; ...
  The member-list defines the full set of members of the class"

This makes it clear that a nested class is a member.
ARM Chapter 11 states that

 "A member of a class can be private: that is, its name can be
 used only by member functions, member initializers, and friends
 of the class in which it is declared."

and 11.1 makes it clear that access specifiers apply to all members.
Hence a nested class can be private.

--
Fergus Henderson        |   "People who brook no compromise in programming
                        |   languages should program in lambda calculus or
fjh@munta.cs.mu.OZ.AU   |   machine language, depending." --Andrew Koenig.




Author: maxtal@physics.su.OZ.AU (John Max Skaller)
Date: Sat, 15 Jan 1994 06:39:22 GMT
Raw View
In article <MATT.94Jan13142855@physics16.berkeley.edu> matt@physics.berkeley.edu writes:
>
>The question, essentially, is whether the presence of an access
>specifier changes the behavior of a nested class.

 Yes. Access applies to types: a private nested type
or typedef cannot be accessed outside the class. A protected
one cant be accessed except by derived classes.

--
        JOHN (MAX) SKALLER,         INTERNET:maxtal@suphys.physics.su.oz.au
 Maxtal Pty Ltd,      CSERVE:10236.1703
        6 MacKay St ASHFIELD,     Mem: SA IT/9/22,SC22/WG21
        NSW 2131, AUSTRALIA




Author: maxtal@physics.su.OZ.AU (John Max Skaller)
Date: Sat, 15 Jan 1994 06:52:18 GMT
Raw View
In article <MATT.94Jan13220748@physics16.berkeley.edu> matt@physics.berkeley.edu writes:
>
>A couple of people have pointed out to me in email that I was
>insufficiently attentive in reading the ARM.  The crucial sentence is
>the second paragraph of the abstract of Chapter 11: "Access control
>applies uniformly to function members, data members, member constants,
>and nested types."
>
>This is completely unambiguous.

 But its wrong in general. In this case, its correct.
But there are different rules for static and nonstatic members,
constructors, mem-initialisers, etc.

 For example, a public static member is accessible
to all derived classes whether the mode of inheritance is
public or private. (in the ARM).

Similarly, mem -initialisers may
initialise what would otherwise be inaccessible virtual bases,
because non-private members of virtual bases should always
be accessible to the derived class. (Virtual bases are
"inherited": they bases of virtually everything :-)

This is not in the ARM or WP but there is clearly a problem
that requires a solution.

--
        JOHN (MAX) SKALLER,         INTERNET:maxtal@suphys.physics.su.oz.au
 Maxtal Pty Ltd,      CSERVE:10236.1703
        6 MacKay St ASHFIELD,     Mem: SA IT/9/22,SC22/WG21
        NSW 2131, AUSTRALIA




Author: matt@physics16.berkeley.edu (Matt Austern)
Date: 13 Jan 1994 22:28:55 GMT
Raw View
[Sorry about the cross-posting, but I do think that this is germane to
all three groups...  Please note that followups have been directed to
comp.std.c++; you may wish to edit the Newsgroups line if another group
is more appropriate for your response.]

IBM's C++ compiler, C Set++, is doing something with nested classes
and access specifiers that I don't expect.  I'm not sure whether I'm
misreading the ARM, or whether this is a compiler bug.  Can someone
give a definitive answer?

The question, essentially, is whether the presence of an access
specifier changes the behavior of a nested class.  Consider, for
example, the following code fragment:
    class outer {
    private:
        class inner {
        public:
            inner(int x) {X = x;}
            int X;
        };
    public:
        outer(int a) {A = a;}
        int A;
    };

    void foo()
    {
        outer O(1);
        outer::inner I(2);
    }

When I compile this using C Set++, I get the error message
  icc -c -q -tdp foo.cc
   16       |  outer::inner I(2);
foo.cc(16:1) : error EDC3016: private member "outer::inner" cannot be accessed.

That is, the compiler thinks that the class outer::inner is in some
sense private (it follows the access specifier private, after all),
and that objects of this type can only be created or accessed accessed
by members of outer.  Note that the constructor of outer::inner itself
is declared as public, and that outer::inner has no private members.

The problem is that, I can't find any indication in the ARM's
discussion of nested classes that access specifiers ought to behave
this way.  Class nesting, as far as I can tell, should only affect
scope, not access permission.

I compiled this same code using gcc and cfront, both of which agree
with my interpretation---they both compiled it with no errors or
warnings.  So, the question: are gcc, cfront, and I wrong, or is
C Set++ wrong?
--
Matthew Austern                       Never express yourself more clearly
matt@physics.berkeley.edu             than you think.    ---N. Bohr




Author: matt@physics16.berkeley.edu (Matt Austern)
Date: 14 Jan 1994 06:07:46 GMT
Raw View
In article <MATT.94Jan13142855@physics16.berkeley.edu> matt@physics16.berkeley.edu (Matt Austern) writes:

> The question, essentially, is whether the presence of an access
> specifier changes the behavior of a nested class.  Consider, for
> example, the following code fragment:
>     class outer {
>     private:
>         class inner {
>         public:
>             int X;
>         };
>     public:
>         int A;
>     };

A couple of people have pointed out to me in email that I was
insufficiently attentive in reading the ARM.  The crucial sentence is
the second paragraph of the abstract of Chapter 11: "Access control
applies uniformly to function members, data members, member constants,
and nested types."

This is completely unambiguous.  IBM's compiler is quite right in
forbidding access to inner::outer from outside outer.  Those compilers
that do allow such access are getting it wrong.

--
Matthew Austern                       Never express yourself more clearly
matt@physics.berkeley.edu             than you think.    ---N. Bohr