This is the mail archive of the egcs@egcs.cygnus.com mailing list for the EGCS project. See the EGCS home page for more information.


[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index] [Subject Index] [Author Index] [Thread Index]

dynamic_cast behavior differs from standard?



In egcs, dynamic_cast seems to have behavior different from that
prescribed by the C++ standard.  However, all other C++ compilers I've
tried do exactly the same thing as egcs, so I think that I'm probably
misunderstand the standard.  If someone could clarify to me if and why
the standard actually prescribes egcs's behavior, I would appreciate
it.

Keep in mind that I don't actually like the way dynamic cast is
defined by the standard.  However, this is a question about what what
the standard requires, not what it should have required.  I'm trying
to write ANSI-compliant code and would like 'g++ -ansi' to reject or
warn about any violations of standard C++.

5.2.7.8 says of the run-time check done by dynamic_cast:

  The run-time check logically executes as follows: 

     If, in the most derived object pointed (referred) to by v, v
     points (refers) to a public base class sub object of a T object,
     and if only one object of type T is derived from the sub-object
     pointed (referred) to by v, the result is a pointer (an lvalue
     referring) to that T object.

     Otherwise, if v points (refers) to a public base class sub-object
     of the most derived object, and the type of the most derived
     object has an unambiguous public base class of type T, the result
     is a pointer (an lvalue referring) to the T sub-object of the
     most derived object.

     Otherwise, the run-time check fails. 

The code pasted below produces the following output:

 bp is NULL
 bigger:: bp is NULL

That means that in a method or friend of T, egcs allows a dynamic_cast
from a private base clase of T to T, but not from a private base class
of T to another private base class of T.  Obviously if you are not in
a private base class of T, you cannot dynamic_cast to T.  However, I
don't see any language in the standard suggesting that access to a
class's private members should allow otherwise prohibited
dynamic_casts.  Thus, the output I would expect would be:

 bp is NULL
 bbp is NULL
 bigger:: bp is NULL
 bigger:: bbp is NULL

Since all compilers do seem to give special dynamic_casts powers to
friends and methods, and doing so must require additional
implementation work in the compiler, I'm willing to believe this is in
fact correct behavior.  I wish I could understand why, however.  And
if it's a bug in the egcs, obviously I'd like to see it fixed (this
should be easy to detect at compile time).

Any clues?

Thanks,
David

===

#include <stdio.h>

struct small {
  virtual ~small () {}
};

struct big : public small {
  friend void dyncast (small *);
};

struct bigger : private big {
  big *getbig () { return this; }
  void test () {
    small *sp = this;
    big *bp = dynamic_cast<big *> (sp);
    if (!bp)
      fprintf (stderr, "bigger:: bp is NULL\n");
    bigger *bbp = dynamic_cast<bigger *> (sp);
    if (!bbp)
      fprintf (stderr, "bigger:: bbp is NULL\n");
  }
  friend void dyncast (small *);
};

void
dyncast (small *sp)
{
  big *bp = dynamic_cast<big *> (sp);
  if (!bp)
    fprintf (stderr, "bp is NULL\n");
  bigger *bbp = dynamic_cast<bigger *> (sp);
  if (!bbp)
    fprintf (stderr, "bbp is NULL\n");
}

int
main ()
{
  bigger b;
  dyncast (b.getbig ());
  b.test ();
  return 0;
}