Topic: typeid(*(int*)0)
Author: Martin von Loewis <loewis@informatik.hu-berlin.de>
Date: 1998/11/08 Raw View
What is the semantics of evaluating 'typeid(*(int*)0)'?
It seems there are three options
1. this is a null-pointer dereference, and thus undefined behaviour.
2. this is an expression of the structure *(T*)0, and should therefore
throw std::bad_typeid.
3. the expression has a static type int, and should therefore return
a reference to typeid(int).
Which of these is expected in a conforming implementation?
TIA,
Martin
---
[ 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: James Kuyper <kuyper@wizard.net>
Date: 1998/11/09 Raw View
Martin von Loewis wrote:
>
> What is the semantics of evaluating 'typeid(*(int*)0)'?
>
> It seems there are three options
>
> 1. this is a null-pointer dereference, and thus undefined behaviour.
> 2. this is an expression of the structure *(T*)0, and should therefore
> throw std::bad_typeid.
> 3. the expression has a static type int, and should therefore return
> a reference to typeid(int).
>
> Which of these is expected in a conforming implementation?
By my reading of section 5.2.8, it should be 2.
[ 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: "Ross Smith" <ross.s@ihug.co.nz>
Date: 1998/11/09 Raw View
Martin von Loewis wrote in message ...
>What is the semantics of evaluating 'typeid(*(int*)0)'?
>
>It seems there are three options
>
>1. this is a null-pointer dereference, and thus undefined behaviour.
>2. this is an expression of the structure *(T*)0, and should therefore
> throw std::bad_typeid.
>3. the expression has a static type int, and should therefore return
> a reference to typeid(int).
>
>Which of these is expected in a conforming implementation?
The standard seems to be a bit unclear on this, but I'd go for 3. The
situation seems to fit paragraph 3 of [expr.typeid], which says that
the expression is not evaluated and presumably therefore can include
a dereferenced null pointer without hardship. Quoting CD2 (yes, I know
-- #include <std_moderator_moan_about_un_american_activities>):
5.2.8 Type identification [expr.typeid]
2 When typeid is applied to an lvalue expression whose type is a poly-
morphic class type (_class.virtual_), the result refers to a type_info
object representing the type of the most derived object
(_intro.object_) (that is, the dynamic type) to which the lvalue
refers. If the lvalue expression is obtained by applying the unary *
operator to a pointer8) and the pointer is a null pointer value
(_conv.ptr_), the typeid expression throws the bad_typeid exception
(_lib.bad.typeid_).
3 When typeid is applied to an expression other than an lvalue of a
polymorphic class type, the result refers to a type_info object repre-
senting the static type of the expression. Lvalue-to-rvalue
(_conv.lval_), array-to-pointer (_conv.array_), and function-to-
pointer (_conv.func_) conversions are not applied to the expression.
If the type of the expression is a class type, the class shall be com-
pletely-defined. The expression is not evaluated.
8) If p is an expression of pointer type, then *p, (*p), *(p), ((*p)),
*((p)), and so on all meet this requirement.
--
Ross Smith ................................... mailto:ross.s@ihug.co.nz
.............. The Internet Group, Auckland, New Zealand ..............
* * * * *
"Screw up your courage. You've screwed up everything else."
[ 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: "Christopher M. Gurnee" <gurnec_at_mediaone_dot_net@127.0.0.1>
Date: 1998/11/09 Raw View
Martin von Loewis wrote in message ...
>What is the semantics of evaluating 'typeid(*(int*)0)'?
>
>It seems there are three options
>
>1. this is a null-pointer dereference, and thus undefined behaviour.
>2. this is an expression of the structure *(T*)0, and should therefore
> throw std::bad_typeid.
>3. the expression has a static type int, and should therefore return
> a reference to typeid(int).
>
>Which of these is expected in a conforming implementation?
>
typeid considers the static type of the expression without evaluating
it; from above, number 3 is expected. An exception to this rule occurs
when the expression is an lvalue of polymorphic class type; in this
case, typeid considers the dynamic type of the expression, throwing
bad_typeid if and only if the expression consists of a dereferenced
pointer, and the pointer is a null pointer value. Unfortunately, the
standard (quoted at the bottom) is a bit unclear in one point. When
applied to an lvalue of polymorphic class type, is the expression
evaluated? More specifically, given
class Foo {virtual ~Foo();};
Foo& getFoo();
void main() { cout << typeid(getFoo()).name(); }
is bar called? The expression bar() is an lvalue of type Foo; in order
to determine its dynamic type, it must be evaluated. I don't know if
this is the intent, but that's the way I interpret it. This seems to
break the rule of least surprise, evaluating the expression only under
certain circumstances.
Perhaps it's just assumed that the user is knowledgable enough to know
when the expression is evaluated and when it isn't; after all, typeid
does parallel dynamic_cast in some manner. However, if you try to take
the typeid of a non-polymorphic class type lvalue, you don't get an
error (as you shouldn't); with dynamic_cast, you always get either an
error or what's expected.
Also, a completely unrelated and pretty pointless question: Is typeid
considered an operator? sizeof is stated as one in the standard, is
typeid?
-Chris Gurnee
5.2.8:
2 When typeid is applied to an lvalue expression whose type is a poly-
morphic class type (_class.virtual_), the result refers to a type_info
object representing the type of the most derived object
(_intro.object_) (that is, the dynamic type) to which the lvalue
refers. If the lvalue expression is obtained by applying the unary *
operator to a pointer8) and the pointer is a null pointer value
(_conv.ptr_), the typeid expression throws the bad_typeid exception
(_lib.bad.typeid_).
3 When typeid is applied to an expression other than an lvalue of a
polymorphic class type, the result refers to a type_info object repre-
senting the static type of the expression. Lvalue-to-rvalue
(_conv.lval_), array-to-pointer (_conv.array_), and function-to-
pointer (_conv.func_) conversions are not applied to the expression.
If the type of the expression is a class type, the class shall be com-
pletely-defined. The expression is not evaluated.
[ 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: Miniussi <miniussi@ilog.fr>
Date: 1998/11/09 Raw View
Martin von Loewis wrote:
> What is the semantics of evaluating 'typeid(*(int*)0)'?
> It seems there are three options
> 1. this is a null-pointer dereference, and thus undefined behaviour.
> 2. this is an expression of the structure *(T*)0, and should therefore
> throw std::bad_typeid.
> 3. the expression has a static type int, and should therefore return
> a reference to typeid(int).
> Which of these is expected in a conforming implementation?
I would say 3:
1) no, 5.2.8(3) says that the expression is not evaluated for a non
plymorphic type.
2) *(T*)0 is not of polymorphic type, so 5.2.8(2) doe not apply
Alain
[ 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: "Alfred Kellner" <alfkellner@magnet.at>
Date: 1998/11/10 Raw View
Martin von Loewis <loewis@informatik.hu-berlin.de>
> What is the semantics of evaluating 'typeid(*(int*)0)'?
>
> It seems there are three options
>
> 1. this is a null-pointer dereference, and thus undefined behaviour.
> 2. this is an expression of the structure *(T*)0, and should therefore
> throw std::bad_typeid.
> 3. the expression has a static type int, and should therefore return
> a reference to typeid(int).
>
> Which of these is expected in a conforming implementation?
>
My guess is .... 3.
<quote ISO 14882>
5.2.8 Type identification [expr.typeid]
(3) When typeid is applied to an expression
other than an lvalue of a polymorphic class type,
the result refers to a type_info object
representing the static type of the expression.
......
The expression is not evaluated.
</quote>
Any doubts ?
--ALfred
[ 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: sbnaran@localhost.localdomain (Siemel Naran)
Date: 1998/11/10 Raw View
On 08 Nov 98 22:21:24 GMT, Martin von Loewis
>What is the semantics of evaluating 'typeid(*(int*)0)'?
Author: Miniussi <miniussi@ilog.fr>
Date: 1998/11/10 Raw View
"Christopher M. Gurnee" wrote:
>
> [..] When
> applied to an lvalue of polymorphic class type, is the expression
> evaluated? More specifically, given
Seems to be the only ways to check that :
> [...] If the lvalue expression is obtained by applying the unary *
> operator to a pointer8) and the pointer is a null pointer value
> (_conv.ptr_), the typeid expression throws the bad_typeid exception
> (_lib.bad.typeid_).
Alain
---
[ 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: "Paul D. DeRocco" <pderocco@ix.netcom.com>
Date: 1998/11/10 Raw View
Christopher M. Gurnee wrote:
>
> More specifically, given
>
> class Foo {virtual ~Foo();};
>
> Foo& getFoo();
>
> void main() { cout << typeid(getFoo()).name(); }
>
> is bar called? The expression bar() is an lvalue of type Foo; in
> order
> to determine its dynamic type, it must be evaluated. I don't know if
> this is the intent, but that's the way I interpret it. This seems to
> break the rule of least surprise, evaluating the expression only under
> certain circumstances.
(I assume you half changed bar to getFoo.) Yes, it must be evaluated.
Since the compiler knows the type is polymorphic, it _must_ look at the
type of an actual object. (In most implementations, this means following
the vtbl pointer in the object.)
> Also, a completely unrelated and pretty pointless question: Is typeid
> considered an operator? sizeof is stated as one in the standard, is
> typeid?
"typeid" isn't an operator. "sizeof" is one because it doesn't
necessarily need parentheses around its operand. However, although both
sizeof and typeid can be applied to a type or to an object, they differ
in one important respect: sizeof(x), where x is a polymorphic type, does
not evaluate its argument in order to find out the true run-time size.
This allows sizeof(x) always to be a compile-time constant. In other
words, it is expected that typeid may call an actual function at
run-time, so it seems more appropriate to require functional notation
for it.
--
Ciao,
Paul
---
[ 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 ]