[comp.sys.sgi] SGI C++ 2.0 Polymorphic Reference Bug

jeff@contex.UUCP (Jeff Carey) (03/13/91)

I am using:

System release:		IRIX Release 4D1-3.3.1
C++ release:		S4-C++-2.0
Software Option:	C++ Translator Version 2.0

on a Silicon Graphics PI.
The other day I was testing the code found in the discussion
of "Virtual Base Classes with Virtual Functions", section 10.10c, pp. 233-4,
of _The_Annotated_C++_Reference_Manual_ and found the following bug.  You'll
notice that the bug is in the call made to f() from the MW object reference
(MW&).

---------------------- beginning of test.c++ code ----------------------------

#include <iostream.h>

class W { public: virtual void f() { cout << "W::f\n"; } };

class MW : public virtual W {};

class BW : public virtual W { public: void f() { cout << "BW::f\n"; } };

class BMW : public BW, public MW {};

main()
{
    BMW bmw;

    MW* pmw = &bmw;
    pmw->f();

    MW& rmw = bmw;
    rmw.f();

    return(0);
}

----------------------------- end of test code -------------------------------

I got this result:

$ test
BW::f
W::f

I would have predicted and hoped that the two lines of diagnostics would
result in the same text.
This is a bug isn't it...polymorphism of this sort should be supported by
references as well as pointers, right?!

Ouch ---
jeff
-- 
------------------------
Jeff Carey
contex!jeff@uunet.uu.net

robert@texas.asd.sgi.com (Robert Skinner) (03/13/91)

In article <1688@contex.UUCP>, jeff@contex.UUCP (Jeff Carey) writes:
|> 
|> I am using:
|> 
|> System release:		IRIX Release 4D1-3.3.1
|> C++ release:		S4-C++-2.0
|> Software Option:	C++ Translator Version 2.0
|> 
|> on a Silicon Graphics PI.
|> The other day I was testing the code found in the discussion
|> of "Virtual Base Classes with Virtual Functions", section 10.10c, pp. 233-4,
|> of _The_Annotated_C++_Reference_Manual_ and found the following bug.  You'll
|> notice that the bug is in the call made to f() from the MW object reference
|> (MW&).
|> 
|> ---------------------- beginning of test.c++ code ----------------------------
|> 
|> #include <iostream.h>
|> 
|> class W { public: virtual void f() { cout << "W::f\n"; } };
|> 
|> class MW : public virtual W {};
|> 
|> class BW : public virtual W { public: void f() { cout << "BW::f\n"; } };
|> 
|> class BMW : public BW, public MW {};
|> 
|> main()
|> {
|>     BMW bmw;
|> 
|>     MW* pmw = &bmw;
|>     pmw->f();
|> 
|>     MW& rmw = bmw;
|>     rmw.f();
|> 
|>     return(0);
|> }
|> 
|> ----------------------------- end of test code -------------------------------
|> 
|> I got this result:
|> 
|> $ test
|> BW::f
|> W::f
|> 
|> I would have predicted and hoped that the two lines of diagnostics would
|> result in the same text.
|> This is a bug isn't it...polymorphism of this sort should be supported by
|> references as well as pointers, right?!
|> 
|> Ouch ---
|> jeff
|> -- 
|> ------------------------
|> Jeff Carey
|> contex!jeff@uunet.uu.net


no, its not a bug.  I'll let one of our compiler wizards explain the
details, but here's my rationalization:

You've declared rmw to be a MW, and the compiler treats it as one,
calling MW::f() directly.  (I think of the '&' operator as a
convenience.  I really don't know what effect it has here.)
Polymorphism is only supported for pointers, where the compiler doesn't
really know what subclass the pointer really points at.

-- 
Robert Skinner
robert@sgi.com

	Some rich men came and raped the land,
	nobody caught 'em.
	Put up a bunch of ugly boxes, 
	and Jesus people bought 'em.

	They call it Paradise, I don't know why.
	You call someplace Paradise, kiss it goodbye.

			- The Eagles

linton@sgi.com (Mark Linton) (03/13/91)

In article <1991Mar12.213359.25893@odin.corp.sgi.com>, robert@texas.asd.sgi.com (Robert Skinner) writes:
|> In article <1688@contex.UUCP>, jeff@contex.UUCP (Jeff Carey) writes:
|> |> 
|> |> The other day I was testing the code found in the discussion
|> |> of "Virtual Base Classes with Virtual Functions", section 10.10c, pp. 233-4,
|> |> of _The_Annotated_C++_Reference_Manual_ and found the following bug.  You'll
|> |> notice that the bug is in the call made to f() from the MW object reference
|> |> (MW&).
|> |> 
|> |> ---------------------- beginning of test.c++ code ----------------------------
|> |> 
|> |> #include <iostream.h>
|> |> 
|> |> class W { public: virtual void f() { cout << "W::f\n"; } };
|> |> 
|> |> class MW : public virtual W {};
|> |> 
|> |> class BW : public virtual W { public: void f() { cout << "BW::f\n"; } };
|> |> 
|> |> class BMW : public BW, public MW {};
|> |> 
|> |> main()
|> |> {
|> |>     BMW bmw;
|> |> 
|> |>     MW* pmw = &bmw;
|> |>     pmw->f();
|> |> 
|> |>     MW& rmw = bmw;
|> |>     rmw.f();
|> |> 
|> |>     return(0);
|> |> }
|> |> 
|> |> ----------------------------- end of test code -------------------------------
|> |> 
|> |> I got this result:
|> |> 
|> |> $ test
|> |> BW::f
|> |> W::f
|> |> 
|> |> I would have predicted and hoped that the two lines of diagnostics would
|> |> result in the same text.
|> |> This is a bug isn't it...polymorphism of this sort should be supported by
|> |> references as well as pointers, right?!
|> |> 
|> |> Ouch ---
|> |> jeff
|> |> -- 
|> |> ------------------------
|> |> Jeff Carey
|> |> contex!jeff@uunet.uu.net
|> 
|> 
|> no, its not a bug.  I'll let one of our compiler wizards explain the
|> details, but here's my rationalization:

This _is_ a bug.  If you remove the multiple inheritance, it behaves
as you would expect (prints BW::f twice).  Note this bug still exists
in cfront 2.1 as it comes from AT&T.

|> Polymorphism is only supported for pointers, where the compiler doesn't
|> really know what subclass the pointer really points at.

Not true.  If that were so, then reference parameters would be pretty useless.
From the ARM, page 209, bottom third:

     ... When a virtual function is called through a pointer or reference, the actual
     type of the object is not necessarily known, so the virtual call mechanism
     must be used.

jeff@contex.UUCP (Jeff Carey) (03/14/91)

In article <1991Mar12.213359.25893@odin.corp.sgi.com>, robert@texas.asd.sgi.com (Robert Skinner) writes:
> In article <1688@contex.UUCP>, jeff@contex.UUCP (Jeff Carey) writes:
> |> 
> |> 			(deleted text)
> |> 
> |> of _The_Annotated_C++_Reference_Manual_ and found the following bug.  You'll
> |> notice that the bug is in the call made to f() from the MW object reference
> |> (MW&).
> |> 
> |> 			(deleted code, results, and more text)
> |> 
> |> This is a bug isn't it...polymorphism of this sort should be supported by
> |> references as well as pointers, right?!
> 
> no, its not a bug.  I'll let one of our compiler wizards explain the
> details, but here's my rationalization:
> 
> You've declared rmw to be a MW, and the compiler treats it as one,
> calling MW::f() directly.  (I think of the '&' operator as a
> convenience.  I really don't know what effect it has here.)
> Polymorphism is only supported for pointers, where the compiler doesn't
> really know what subclass the pointer really points at.
> 
> -- 
> Robert Skinner
> robert@sgi.com
> 

Robert-

If this is not a bug, and "polymorphism is only supported for pointers,"
then the call to the additional g() functions in the following code will
illustrate what must certainly be a bug:

------------------ beginning of enlarged test.c++ code -----------------------

#include <iostream.h>

class W { public: virtual void f() { cout << "W::f\n"; } };

class MW : public virtual W {
    public: virtual void g() { cout << "MW::g\n"; } };

class BW : public virtual W { public: void f() { cout << "BW::f\n"; } };

class BMW : public BW, public MW { public: void g() { cout << "BMW::g\n"; } };

main()
{
    BMW bmw;

    MW* pmw = &bmw;
    pmw->f();
    pmw->g();

    MW& rmw = bmw;
    rmw.f();
    rmw.g();

    return(0);
}

-------------------------- end of enlarged test code -------------------------

With these results:

$ test
BW::f
BMW::g
W::f
BMW::g

Based on your assertion, I would have predicted that the two lines of
diagnostics related to the g() call would have been different; the first
is OK, but the second would have to be "MW::g".
Polymorphism appears to be currently supported in this context by references.

Something must be wrong ---
And just trying to comprehend ---
Thanks for helping ---
I'm sure this won't be the end ---
jeff
-- 
------------------------
Jeff Carey
contex!jeff@uunet.uu.net

jeff@contex.UUCP (Jeff Carey) (03/14/91)

In article <1991Mar13.015608.1334@odin.corp.sgi.com>, linton@sgi.com (Mark Linton) writes:
> In article <1991Mar12.213359.25893@odin.corp.sgi.com>, robert@texas.asd.sgi.com (Robert Skinner) writes:
> |> In article <1688@contex.UUCP>, jeff@contex.UUCP (Jeff Carey) writes:
> |> |> This is a bug isn't it...[?]
> |> no, its not a bug.
> This _is_ a bug.  If you remove the multiple inheritance, it behaves
> as you would expect (prints BW::f twice).  Note this bug still exists
> in cfront 2.1 as it comes from AT&T.

Does AT&T know about this ?

Would you or someone there please tell them about this...

Or should I; I just need to be told how to tell 'em (who to tell).

Thanks ---
jeff
-- 
------------------------
Jeff Carey
contex!jeff@uunet.uu.net