Topic: Core language issue: Operational semantics of dynamic_cast is


Author: "=?ISO-8859-1?Q?Daniel_Kr=FCgler?=" <daniel.kruegler@googlemail.com>
Date: Mon, 3 Dec 2007 11:43:03 CST
Raw View
[Remark to the mods: I sent this posting 12 hours
ago, but with the misleading title starting with
"Library issue: [...]". Since I got neither confirmation
nor approval I resend it. If you stumble across the
other one, you are allowed to delete it]

This issue report was initiated by a recent discussion in
c.l.c++.mod ("dynamic_cast"), see

http://tinyurl.com/2hqtfs

There seems to exists confusion on the interpretation of
[expr.dynamic.cast]/5, which is made clear with the O.P.'s
examples:

(I)
struct A {};
struct B : private A{} b;
A* pa = dynamic_cast<A*>(&b); // #1

(II)
struct A { virtual ~A(){} };
struct B : private A{} b;
A* pa = dynamic_cast<A*>(&b); // #2

Comeau Online as well as gcc 4.2.1 reject *both* lines
#1 and #2 (due to non-accessible base class),
VS2005 SP1 rejects only #1, but accepts #2 and
assigns (as expected) 0 to pa during runtime.

IMO this different behaviour is due to the unclear
meaning of [expr.dynamic.cast]/5: It seems that
the first two compilers read it's first sentence

"If T is "pointer to cv1 B" and v has type "pointer to cv2 D"
such that B is a base class of D, the result is a pointer to
the unique B sub-object of the D object pointed to by v.[..]"

to be a sufficient condition that this para should be obeyed,
and due to it's last sentence

"In both the pointer and reference cases, cv1 shall be the
same cv-qualification as, or greater cv-qualification than, cv2,
and B shall be an accessible unambiguous base class
of D."

they reject both snippets - independent whether the base
class is polymorphic or not. In contrast to this, VS2005
seems to consider the last sentence to be part of the
actual condition. This has the effect, that it goes on with
p.6:

"Otherwise, v shall be a pointer to or an lvalue of a
polymorphic type (10.3)."

and rejects *now* line #1 (because A is not polymorphic),
but goes ahead with #2 (which fulfills all requirements).

Considering the current wording - which has not significantly
been changed in N2461 - I intuitively would follow the
interpretation of the first school (rejecting both #1 and #2) -
but it seems that the actual intend seems to be that of the
second one which is somewhat indicated by the example
in p. 9, which in abridged form is given by:

"[..]
class B { virtual void g(); };
class D : public virtual A, private B {};
[..]
D d;
B* bp = ...;
[..]
bp = dynamic_cast<B*>(&d); // fails
[..]"

The last comment seems to support the idea,
that the code is well-formed and that it will fail
during run-time.

The standard should clarify it's intend and should
add wording to make the interpretation unambigious.

Proposed resolution (Interpretation school 2, wording
follows N2164):

1) Change the last sentence of p. 5, so that the para is now
written as:

"If T is "pointer to cv1 B" and v has type "pointer to cv2 D"
such that B is a base class of D, the result is a pointer to
the unique B subobject of the D object pointed to by v.
Similarly, if T is "reference to cv1 B" and v has type cv2 D
such that B is a base class of D, the result is the unique B
subobject of the D object referred to by v. 61) The result is
an lvalue if T is an lvalue reference, or an rvalue if T is
an rvalue reference. In both the pointer and reference cases,
cv1 shall be the same cv-qualification as, or greater cv-
qualification than, cv2, and - if B is not a polymorphic class -
B shall be an accessible unambiguous base class of D.
[ Example: ... end example ]"

Greetings from Bremen,

Daniel Kr   gler

---
[ 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://www.comeaucomputing.com/csc/faq.html                      ]