Topic: access control not performed on all class members (Code Warrior)


Author: daniel@reichardt.ch (Daniel Hartmeier)
Date: 1999/01/14
Raw View
On 12 Jan 1999 06:41:56 GMT, blargg@flash.net (Gargantua Blargg) wrote:

> (sorry, I don't have the final standard because the ANSI credit card
> verification on their online order store fails for some reason, so these
> quotes are from the CD2. Flame me if the final standard has changed in any
> significant way, or even if it hasn't; I deserve it :-)

I paid the $18 and downloaded the final standard document. Only to
discover that they have disabled the possibility to copy text to the
clipboard. Another user-friendly feature of the great PDF format.

This was the last time I paid for an ANSI document. I will continue to
quote from the CD2. :-(

Regards,
--
Daniel Hartmeier  <daniel@reichardt.ch>  PGP 6A3A7409  ICQ# 12742482

"The woods are lovely, dark and deep.  But I have promises to keep,
And lines to code before I sleep, And lines to code before I sleep."
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: blargg@flash.net (Gargantua Blargg)
Date: 1999/01/13
Raw View
First, the relevant quotes from the standard

(sorry, I don't have the final standard because the ANSI credit card
verification on their online order store fails for some reason, so these
quotes are from the CD2. Flame me if the final standard has changed in any
significant way, or even if it hasn't; I deserve it :-)

>  9   Classes                                                    [class]
>  ______________________________________________________________________
>
>1 A class is a type.   Its  name  becomes  a  class-name  (_class.name_)
>  within its scope.
>          class-name:
>                  identifier
>                  template-id
>  Class-specifiers  and elaborated-type-specifiers (_dcl.type.elab_) are
>  used to make class-names.  An object of a class consists of a  (possi-
>  bly empty) sequence of members and base class objects.
>          class-specifier:
>                  class-head { member-specificationopt }
>          class-head:
>                  class-key identifieropt base-clauseopt
>                  class-key nested-name-specifier identifier base-clauseopt
>          class-key:
>                  class
>                  struct
>                  union
>

Summary: A class consists members, and base classes.

>  9.2  Class members                                         [class.mem]
>          member-specification:
>                  member-declaration member-specificationopt
>                  access-specifier : member-specificationopt
>          member-declaration:
>                  decl-specifier-seqopt member-declarator-listopt ;
>                  function-definition ;opt
>                  qualified-id ;
>                  using-declaration
>                  template-declaration
>          member-declarator-list:
>                  member-declarator
>                  member-declarator-list , member-declarator
>          member-declarator:
>                  declarator pure-specifieropt
>                  declarator constant-initializeropt
>                  identifieropt : constant-expression
>          pure-specifier:
>                   = 0
>          constant-initializer:
>                   = constant-expression
>
>1 The  member-specification  in a class definition declares the full set
>  of members of the class; no member can be added elsewhere.  Members of
>  a  class  are  data  members,  member functions (_class.mfct_), nested
>  types, and enumerators.  Data members and member functions are  static
>  or   nonstatic;   see   _class.static_.    Nested  types  are  classes
>  (_class.name_, _class.nest_) and enumerations (_dcl.enum_) defined  in
>  the class, and arbitrary types declared as members by use of a typedef
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>  declaration  (_dcl.typedef_).   The  enumerators  of  an   enumeration
   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>  (_dcl.enum_)  defined  in  the class are members of the class.  Except
>  when used to declare friends (_class.friend_) or to introduce the name
>  of   a   member  of  a  base  class  into  a  derived  class  (_names-
>  pace.udecl_,_class.access.dcl_), member-declarations  declare  members
>  of  the class, and each such member-declaration shall declare at least
>  one member name of the class.  A member shall not be declared twice in
>  the  member-specification,  except that a nested class or member class
>  template can be declared and then later defined.

Summary: This is what members can be. This includes enumerations, nested
classes, and typedefs.

>  11   Member access control                              [class.access]
>  ______________________________________________________________________
>
>1 A member of a class can be
>
>  --private; that is, its name can be used  only  by  member  functions,
>    static  data  members,  and  friends  of  the  class  in which it is
>    declared.
>
>  --protected; that is, its name can be used only by  member  functions,
>    static  data  members,  and  friends  of  the  class  in which it is
>    declared and by member functions, static data members,  and  friends
>    of classes derived from this class (see _class.protected_).
>
>  --public;  that  is,  its  name  can  be  used anywhere without access
>    restriction.
...
>3 Access control is applied uniformly to all names,  whether  the  names
>  are  referred to from declarations or expressions.  [Note: access con-
>  trol   applies   to   names   nominated   by    friend    declarations
>  (_class.friend_) and using-declarations (_namespace.udecl_).  ] In the
>  case of overloaded function names, access control is  applied  to  the
>  function  selected by overload resolution.  [Note: because access con-
>  trol applies to names, if access control is applied to a typedef name,
                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>  only  the accessibility of the typedef name itself is considered.  The
   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>  accessibility of the entity referred to by the typedef is not  consid-
>  ered.  For example,

Summary: Access control applies to all members the same way. Specifically,
it applies to typedefs in this way.

And, the link to the entry for this bug on my CW bugs list page:

    <http://www.flash.net/~blargg/cwbugs/bugs.html#bug4-013>

Now, with the formalities...

In article
<MWRon-1101992326530001@dyn1-tnt1-142.kalamazoo.mi.ameritech.net>,
MWRon@metrowerks.com (MW Ron) wrote:

>In article <blargg-1101991845470001@p209.amax20.dialup.aus1.flash.net>,
>blargg@flash.net (Gargantua Blargg) wrote:
>
>Lets take one issue at a time.
>
>> > >     class X {
>> > >     private:    // Just a reminder
>> > >         typedef int T;
>> > >         struct Y { };
>> > >     };
>> > >
>> > >     X::T t; // T is private to X. This is illegal!
>> > >     X::Y y; // Ditto
>> > >
>> > > Pretty bad, huh?
>> >
>> > No, it isn't like you can access the classes private members etc.
>>
>> That's what the above is doing.
>
>No it isn't  X::T is not a member it is merely a declaration

T is a member of class X.

>If you had a member  of type T
>
> class X {
>    private:    // Just a reminder
>      typedef int T;
>      T t;
> };
>
> int main()
> {
>
>     X::t = 3;
> }
>
>This correctly gives an error.

Yes. This is also an error:

X::T foo = 3;

>furthermore:
>
>>[dcl.typedef] 7.1.3 The typedef specifier
>>
>>1 Declarations containing the decl-specifier typedef declare identifiers
>>that can be used later for naming fundamental (3.9.1) or compound (3.9.2)
>>types. The typedef specifier shall not be used in a function-definition
>>(8.4), and it shall not be combined in a decl-specifier-seq with any other
>>kind of specifier except a type-specifier.
>>
>>typedef-name:
>>   identifier
>>
>>A name declared with the typedef specifier becomes a typedef-name. Within
>>the scope of its declaration, a typedef-name is syntactically equivalent
>>to a keyword and names the type associated with the identifier in the way
>>described in clause 8.
>
>Your hypothesis is that a mere type declaration is a member,

That's my reading of the standard, yes.

>it isn't so the items you quoted do not apply.

Our interpretations of the standard differ.

I warned you in a friendly manner that I was tempted to post this to
comp.std.c++. Seems I'm going to have to :-)

>so again, seeing as how the above says that a typedef has scope of its
>declaration I ask you to quote a relevant item where this is indeed a bug.

Scope is a totally separate issue, and is not relevant here.

>I think this is legal
>
>class X {
>   private:    // Just a reminder
>     typedef int T;
>    public:
>     T t;
>};
>
>int main()
>{
>
>   X::T t = 3;
>
>   X x;
>   x.t = t;
>
>   return 0;
>}

It seems illegal to me, based on my reading of the standard.

>and logically it makes sense to do it this way so more complicated types
>can utilize the benefits of a typedef.

No, it does not logically make sense. If the programmer made the typedef
private, they did so for a reason. C++ is designed to be intuitive, where
this is possible.

I'll let you in on a little secret: Most of the bugs I find are not due to
my spending hours reading the standard and trying out the compiler.
Instead I find them by chance when the language, as compiled by the
compiler, does not behave in an intuitive manner that I expect. Either I
find, after reading the standard, that the language just has an
unintuitive feature there, and make a mental note of it, or I find that
the compiler is in error.

>I'm not as sure on the struct type  but my point is a declaration is not a
>member and member access does not apply.

I used to think "members" only applied to member functions and member
objects, but I have since educated myself by reading the standard, and,
more importantly, reading the comments of other knowledgable C++ users on
comp.lang.c++.moderated and comp.std.c++. You learn a lot by reading their
discussions.

Sorry to have to do this, but I think we need to get to the bottom of this.

--
D.A.R.E. to say no to majority. Think for yourself.

Gargantua Blargg | blargg@flash.net | http://www.flash.net/~blargg/
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: MWRon@metrowerks.com (MW Ron)
Date: 1999/01/14
Raw View
In article <199901122222.QAA21212@centurion.flash.net>, blargg@flash.net
(Gargantua Blargg) wrote:

> Summary: Access control applies to all members the same way. Specifically,
> it applies to typedefs in this way.
>
> And, the link to the entry for this bug on my CW bugs list page:
>
>     <http://www.flash.net/~blargg/cwbugs/bugs.html#bug4-013>

Our engineering staff has agreed with this sumary and entered this as a bug.

Ron

--
http://www.zdnet.com/pcweek/stories/news/0,4153,361176,00.html
Pro 4.0 C++ 30% edge in Tak benchmark over VC++ 6.0

Battle of the Java development tools By Rex Baldazo
http://www.builder.com/Servers/RexTech/111698/?dd.cn

METROWERKS - Ron Liechty - MWRon@metrowerks.com
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: blargg@flash.net (Gargantua Blargg)
Date: 1999/01/12
Raw View
First, the relevant quotes from the standard

(sorry, I don't have the final standard because the ANSI credit card
verification on their online order store fails for some reason, so these
quotes are from the CD2. Flame me if the final standard has changed in any
significant way, or even if it hasn't; I deserve it :-)

>  9   Classes                                                    [class]
>  ______________________________________________________________________
>
>1 A class is a type.   Its  name  becomes  a  class-name  (_class.name_)
>  within its scope.
>          class-name:
>                  identifier
>                  template-id
>  Class-specifiers  and elaborated-type-specifiers (_dcl.type.elab_) are
>  used to make class-names.  An object of a class consists of a  (possi-
>  bly empty) sequence of members and base class objects.
>          class-specifier:
>                  class-head { member-specificationopt }
>          class-head:
>                  class-key identifieropt base-clauseopt
>                  class-key nested-name-specifier identifier base-clauseopt
>          class-key:
>                  class
>                  struct
>                  union
>

Summary: A class consists members, and base classes.

>  9.2  Class members                                         [class.mem]
>          member-specification:
>                  member-declaration member-specificationopt
>                  access-specifier : member-specificationopt
>          member-declaration:
>                  decl-specifier-seqopt member-declarator-listopt ;
>                  function-definition ;opt
>                  qualified-id ;
>                  using-declaration
>                  template-declaration
>          member-declarator-list:
>                  member-declarator
>                  member-declarator-list , member-declarator
>          member-declarator:
>                  declarator pure-specifieropt
>                  declarator constant-initializeropt
>                  identifieropt : constant-expression
>          pure-specifier:
>                   = 0
>          constant-initializer:
>                   = constant-expression
>
>1 The  member-specification  in a class definition declares the full set
>  of members of the class; no member can be added elsewhere.  Members of
>  a  class  are  data  members,  member functions (_class.mfct_), nested
>  types, and enumerators.  Data members and member functions are  static
>  or   nonstatic;   see   _class.static_.    Nested  types  are  classes
>  (_class.name_, _class.nest_) and enumerations (_dcl.enum_) defined  in
>  the class, and arbitrary types declared as members by use of a typedef
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>  declaration  (_dcl.typedef_).   The  enumerators  of  an   enumeration
   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>  (_dcl.enum_)  defined  in  the class are members of the class.  Except
>  when used to declare friends (_class.friend_) or to introduce the name
>  of   a   member  of  a  base  class  into  a  derived  class  (_names-
>  pace.udecl_,_class.access.dcl_), member-declarations  declare  members
>  of  the class, and each such member-declaration shall declare at least
>  one member name of the class.  A member shall not be declared twice in
>  the  member-specification,  except that a nested class or member class
>  template can be declared and then later defined.

Summary: This is what members can be. This includes enumerations, nested
classes, and typedefs.

>  11   Member access control                              [class.access]
>  ______________________________________________________________________
>
>1 A member of a class can be
>
>  --private; that is, its name can be used  only  by  member  functions,
>    static  data  members,  and  friends  of  the  class  in which it is
>    declared.
>
>  --protected; that is, its name can be used only by  member  functions,
>    static  data  members,  and  friends  of  the  class  in which it is
>    declared and by member functions, static data members,  and  friends
>    of classes derived from this class (see _class.protected_).
>
>  --public;  that  is,  its  name  can  be  used anywhere without access
>    restriction.
...
>3 Access control is applied uniformly to all names,  whether  the  names
>  are  referred to from declarations or expressions.  [Note: access con-
>  trol   applies   to   names   nominated   by    friend    declarations
>  (_class.friend_) and using-declarations (_namespace.udecl_).  ] In the
>  case of overloaded function names, access control is  applied  to  the
>  function  selected by overload resolution.  [Note: because access con-
>  trol applies to names, if access control is applied to a typedef name,
                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>  only  the accessibility of the typedef name itself is considered.  The
   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>  accessibility of the entity referred to by the typedef is not  consid-
>  ered.  For example,

Summary: Access control applies to all members the same way. Specifically,
it applies to typedefs in this way.

And, the link to the entry for this bug on my CW bugs list page:

    <http://www.flash.net/~blargg/cwbugs/bugs.html#bug4-013>

Now, with the formalities...

In article
<MWRon-1101992326530001@dyn1-tnt1-142.kalamazoo.mi.ameritech.net>,
MWRon@metrowerks.com (MW Ron) wrote:

>In article <blargg-1101991845470001@p209.amax20.dialup.aus1.flash.net>,
>blargg@flash.net (Gargantua Blargg) wrote:
>
>Lets take one issue at a time.
>
>> > >     class X {
>> > >     private:    // Just a reminder
>> > >         typedef int T;
>> > >         struct Y { };
>> > >     };
>> > >
>> > >     X::T t; // T is private to X. This is illegal!
>> > >     X::Y y; // Ditto
>> > >
>> > > Pretty bad, huh?
>> >
>> > No, it isn't like you can access the classes private members etc.
>>
>> That's what the above is doing.
>
>No it isn't  X::T is not a member it is merely a declaration

T is a member of class X.

>If you had a member  of type T
>
> class X {
>    private:    // Just a reminder
>      typedef int T;
>      T t;
> };
>
> int main()
> {
>
>     X::t = 3;
> }
>
>This correctly gives an error.

Yes. This is also an error:

X::T foo = 3;

>furthermore:
>
>>[dcl.typedef] 7.1.3 The typedef specifier
>>
>>1 Declarations containing the decl-specifier typedef declare identifiers
>>that can be used later for naming fundamental (3.9.1) or compound (3.9.2)
>>types. The typedef specifier shall not be used in a function-definition
>>(8.4), and it shall not be combined in a decl-specifier-seq with any other
>>kind of specifier except a type-specifier.
>>
>>typedef-name:
>>   identifier
>>
>>A name declared with the typedef specifier becomes a typedef-name. Within
>>the scope of its declaration, a typedef-name is syntactically equivalent
>>to a keyword and names the type associated with the identifier in the way
>>described in clause 8.
>
>Your hypothesis is that a mere type declaration is a member,

That's my reading of the standard, yes.

>it isn't so the items you quoted do not apply.

Our interpretations of the standard differ.

I warned you in a friendly manner that I was tempted to post this to
comp.std.c++. Seems I'm going to have to :-)

>so again, seeing as how the above says that a typedef has scope of its
>declaration I ask you to quote a relevant item where this is indeed a bug.

Scope is a totally separate issue, and is not relevant here.

>I think this is legal
>
>class X {
>   private:    // Just a reminder
>     typedef int T;
>    public:
>     T t;
>};
>
>int main()
>{
>
>   X::T t = 3;
>
>   X x;
>   x.t = t;
>
>   return 0;
>}

It seems illegal to me, based on my reading of the standard.

>and logically it makes sense to do it this way so more complicated types
>can utilize the benefits of a typedef.

No, it does not logically make sense. If the programmer made the typedef
private, they did so for a reason. C++ is designed to be intuitive, where
this is possible.

I'll let you in on a little secret: Most of the bugs I find are not due to
my spending hours reading the standard and trying out the compiler.
Instead I find them by chance when the language, as compiled by the
compiler, does not behave in an intuitive manner that I expect. Either I
find, after reading the standard, that the language just has an
unintuitive feature there, and make a mental note of it, or I find that
the compiler is in error.

>I'm not as sure on the struct type  but my point is a declaration is not a
>member and member access does not apply.

I used to think "members" only applied to member functions and member
objects, but I have since educated myself by reading the standard, and,
more importantly, reading the comments of other knowledgable C++ users on
comp.lang.c++.moderated and comp.std.c++. You learn a lot by reading their
discussions.

Sorry to have to do this, but I think we need to get to the bottom of this.

--
D.A.R.E. to say no to majority. Think for yourself.

Gargantua Blargg | blargg@flash.net | http://www.flash.net/~blargg/


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]