Covariant returns

Jason Merrill jason at cygnus.com
Thu Jul 6 17:47:00 UTC 2000


>>>>> Jim Dehnert <dehnert at baalbek.engr.sgi.com> writes:

 > Suppose we have:

 > 	class A { ... };
 > 	class B: public A { ... };

 > 	class V {
 > 		...
 > 		virtual A* f ();
 > 		...
 > 	};
 > 	class W: virtual public V {
 > 		...
 > 		virtual B* f ();
 > 		...
 > 	};

 > 	W *w;
 > 	V *v = w;

 > Suppose initially that no bases are primary.  (And check my example
 > before you believe anything...)

 > Now, if I call w->f(), I get the basic W::f, with no adjustments.
 > This is what should happen if I use the "normal" entry for f in the W
 > vtable.

Yes.

 > If I call v->f(), it's more complicated.  I get a thunk which (a)
 > adjusts v to a W*, (b) calls W::f, and (c) adjusts the resulting B*
 > back to an A*.  This is what should happen if I use the "normal" entry
 > for f in the V-in-W secondary vtable.

Yes.

 > So far, so good.  The W vtable contains the overriding W::f vptr.
 > The V-in-W secondary vtable contains the thunk vptr.  Nothing special
 > for the covariant return types, except that the thunk is messier.

Yes.  I thought that Mark was suggesting that the W vtable in this case
would have two entries for f; that's what I was disagreeing with.

 > I note, as an aside so far, that if W did not override V::f, we would
 > have a "promoted" vptr for it in the W vtable to make it easier to
 > call.  But that has nothing to do with covariant return types either.

Yes.

 > Next, suppose V is the primary base of W.  Now they share a vtable, and
 > therefore an f vptr.  If the f's had the same return type, there would
 > be no adjustments to be made, and that f vptr could just point to the
 > overriding W::f.  But because they have covariant return types, v->f()
 > must still adjust on return, so the "shared" vptr must do that, and W's
 > vtable needs to have another entry for the "normal" W::f vptr.

Yes, we will have two entries in the primary vtable.  One is logically part
of the V-in-W vtable, one is logically part of the W vtable.

 > Finally, suppose we have:

 > 	class X: virtual public W {
 > 	  ...
 > 	};

 > Now, we specify that the vptrs from W get promoted to the X vtable.
 > That presumably means both of them in the case at hand.  Correct?

I disagree with this, too.  Only the W copy should be promoted.  The V copy
is only called through a V*, so there's no reason to promote it.

Each class' vtable only needs one entry per function, regardless of
covariant returns.  The only exception comes from the case where two
classes share a vtable, but that exception is only physical; the logical
rule stands.

Jason




More information about the cxx-abi-dev mailing list