Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
18.support.rtti.cpp
Go to the documentation of this file.
1
29#include <rw/_defs.h>
30#if defined (__IBMCPP__) && !defined (_RWSTD_NO_IMPLICIT_INCLUSION)
31// Disable implicit inclusion to work around
32// a limitation in IBM's VisualAge 5.0.2.0 (see PR#26959)
33
34# define _RWSTD_NO_IMPLICIT_INCLUSION
35#endif
36
37
40// verifies that typeid is correctly declared for MSVC (see PR #25603)
41void foo ()
42{
43 _THROW (0); // must appear before #include <typeinfo>
44}
45
46
49#include <typeinfo>
50
51#include <rw_driver.h>
52#include <rw_valcmp.h>
53
54// polymorphic classes (10.3, p1) used in tests below
55struct B { virtual ~B () { } };
56struct D1: B { };
57struct D2: B { };
58
59
61static int
62run_test (int, char* [])
63{
64 if (1) {
65 // exercise 18.5, the synopsis of <typeinfo>
66
67 std::type_info *ti = 0;
68 std::bad_cast *bc = 0;
69 std::bad_typeid *bt = 0;
70
71 _RWSTD_UNUSED (ti);
72 _RWSTD_UNUSED (bc);
73 _RWSTD_UNUSED (bt);
74 }
75
76 if (1) {
77 // exercise 18.5.1, class type_info interface
78
79 // 18.5.1, p2
80 bool (std::type_info::*p_op_eq)(const std::type_info&) const =
81 &std::type_info::operator==;
82
83 // 18.5.1, p3
84 bool (std::type_info::*p_op_neq)(const std::type_info&) const =
85 &std::type_info::operator!=;
86
87 // 18.5.1, p5
88 bool (std::type_info::*p_before)(const std::type_info&) const =
89 &std::type_info::before;
90
91 // 18.5.1, p7
92 const char* (std::type_info::*p_name)() const = &std::type_info::name;
93
94 _RWSTD_UNUSED (p_op_eq);
95 _RWSTD_UNUSED (p_op_neq);
96 _RWSTD_UNUSED (p_before);
97 _RWSTD_UNUSED (p_name);
98 }
99
100#if defined (__IBMCPP__) && !defined (__RTTI_TYPE_INFO__)
101
102 rw_warn (0, 0, __LINE__,
103 "not testing type_info; rtti is disabled");
104
105#else // !__IBMCPP__ || __RTTI_TYPE_INFO__
106
107 if (1) {
108 // exercise 18.5.1, class type_info functionality
109 D1 d1;
110 D2 d2;
111
112 const std::type_info &ti_D1 = typeid (D1);
113 const std::type_info &ti_D2 = typeid (D2);
114
115 const std::type_info &ti_d1 = typeid (d1);
116 const std::type_info &ti_d2 = typeid (d2);
117
118
119 const char *D1_name = ti_D1.name () ? ti_D1.name () : "(D1 null)";
120 const char *D2_name = ti_D2.name () ? ti_D2.name () : "(D2 null)";
121 const char *d1_name = ti_d1.name () ? ti_d1.name () : "(d1 null)";
122 const char *d2_name = ti_d2.name () ? ti_d2.name () : "(d2 null)";
123
124 // 18.5.1, p2
125 rw_assert (ti_D1 == ti_D1, 0, __LINE__,
126 "std::type_info::operator==(): \"%s\" != \"%s\"",
127 D1_name, D1_name);
128 rw_assert (ti_D1 == ti_d1, 0, __LINE__,
129 "std::type_info::operator==(): \"%s\" != \"%s\"",
130 D1_name, d1_name);
131 rw_assert (!(ti_D1 == ti_D2), 0, __LINE__,
132 "std::type_info::operator==(): \"%s\" == \"%s\"",
133 D1_name, D2_name);
134 rw_assert (ti_d1 == ti_d1, 0, __LINE__,
135 "std::type_info::operator==(): \"%s\" != \"%s\"",
136 d1_name, d1_name);
137 rw_assert (ti_d1 == ti_D1, 0, __LINE__,
138 "std::type_info::operator==(): \"%s\" != \"%s\"",
139 d1_name, D1_name);
140 rw_assert (!(ti_d1 == ti_d2), 0, __LINE__,
141 "std::type_info::operator==(): \"%s\" == \"%s\"",
142 d1_name, d2_name);
143
144 // 18.5.1, p3
145 rw_assert (ti_D1 != ti_D2, 0, __LINE__,
146 "std::type_info::operator!=(): \"%s\" == \"%s\"",
147 D1_name, D2_name);
148 rw_assert (ti_D1 != ti_d2, 0, __LINE__,
149 "std::type_info::operator!=(): \"%s\" == \"%s\"",
150 D1_name, d2_name);
151 rw_assert (!(ti_D1 != ti_D1), 0, __LINE__,
152 "std::type_info::operator!=(): \"%s\" != \"%s\"",
153 D1_name, D1_name);
154 rw_assert (ti_d1 != ti_d2, 0, __LINE__,
155 "std::type_info::operator!=(): \"%s\" == \"%s\"",
156 d1_name, d2_name);
157 rw_assert (ti_d1 != ti_D2, 0, __LINE__,
158 "std::type_info::operator!=(): \"%s\" == \"%s\"",
159 d1_name, D2_name);
160 rw_assert (!(ti_d1 != ti_d1), 0, __LINE__,
161 "std::type_info::operator!=(): \"%s\" != \"%s\"",
162 d1_name, d1_name);
163
164 // 18.5.1, p5
165 rw_assert (!ti_D1.before (ti_D1) && !ti_D2.before (ti_D2),
166 0, __LINE__, "std::type_info::before ()");
167 rw_assert (ti_D1.before (ti_D2) || ti_D2.before (ti_D1),
168 0, __LINE__, "std::type_info::before ()");
169 rw_assert (ti_d1.before (ti_d2) || ti_d2.before (ti_d1),
170 0, __LINE__, "std::type_info::before ()");
171 rw_assert (!ti_d1.before (ti_d1) && !ti_d2.before (ti_d2),
172 0, __LINE__, "std::type_info::before ()");
173
174 // 18.5.1, p7
175 rw_assert (0 == rw_strncmp (D1_name, d1_name), 0, __LINE__,
176 "std::type_info::name (): \"%s\" != \"%s\"",
177 D1_name, d1_name);
178 rw_assert (0 != rw_strncmp (D1_name, D2_name), 0, __LINE__,
179 "std::type_info::name (): \"%s\" == \"%s\"",
180 D1_name, D2_name);
181 rw_assert (0 == rw_strncmp (D2_name, d2_name), 0, __LINE__,
182 "std::type_info::name (): \"%s\" != \"%s\"",
183 D2_name, d2_name);
184 rw_assert (0 != rw_strncmp (d1_name, d2_name), 0, __LINE__,
185 "std::type_info::name (): \"%s\" == \"%s\"",
186 d1_name, d2_name);
187 }
188
189#endif // !__IBMCPP__ || __RTTI_TYPE_INFO__
190
191 if (1) {
192 // exercise 18.5.2, class bad_cast interface
193
194 // std::bad_cast must publicly derive from std::exception
195 const std::bad_cast *pbc = 0;
196 const std::exception *pe = pbc;
197
198 // 18.5.2, p2
199 std::bad_cast bc;
200
201 // 18.5.2, p4 - copy ctor
202 std::bad_cast bc2 (bc);
203
204 // 18.5.2, p4 - assignment
205 std::bad_cast& (std::bad_cast::*p_op_assign)(const std::bad_cast&)
206 _PTR_THROWS (()) = &std::bad_cast::operator=;
207
208 // 18.5.2, p5
209 const char* (std::bad_cast::*p_what)() const _PTR_THROWS (()) =
210 &std::bad_cast::what;
211
212 _RWSTD_UNUSED (pbc);
213 _RWSTD_UNUSED (pe);
214 _RWSTD_UNUSED (bc);
215 _RWSTD_UNUSED (bc2);
216 _RWSTD_UNUSED (p_op_assign);
217 _RWSTD_UNUSED (p_what);
218 }
219
220 if (1) {
221 // exercise 18.5.2, class bad_cast functionality
222
223#ifndef _RWSTD_NO_EXCEPTIONS
224# ifndef _RWSTD_NO_DYNAMIC_CAST
225
226 const char *caught = "no exception";
227
228 D1 d1;
229 B &b = d1;
230
231 try {
232 D2 &d2 = dynamic_cast<D2&>(b);
233
235 }
236 catch (const std::bad_cast &bc) {
237 caught = "std::bad_cast";
238
239 // 18.5.2, p2
240 std::bad_cast bc2;
241
242 // 18.5.2, p4 - copy ctor
243 std::bad_cast bc3 (bc);
244
245 const char* const bc_what = bc.what ();
246 const char* bc2_what = bc2.what ();
247 const char* const bc3_what = bc3.what ();
248
249 if (0 == bc2_what)
250 rw_assert (false, 0, __LINE__, "bad_cast().what() != 0");
251
252 if (0 == bc3_what)
253 rw_assert (false, 0, __LINE__,
254 "bad_cast::what() != 0 failed "
255 "for a copy of a caught exception object");
256
257 if (bc2_what && bc3_what)
258 rw_warn (0 == rw_strncmp (bc2_what, bc3_what),
259 0, __LINE__,
260 "bad_cast::bad_cast (const bad_cast&): "
261 "\"%s\" != \"%s\"", bc_what, bc3_what);
262
263 // 18.5.2, p4 - assignment
264 bc2 = bc;
265
266 bc2_what = bc2.what ();
267
268 if (0 == bc_what)
269 rw_assert (false, 0, __LINE__,
270 "bad_cast::what() != 0 failed "
271 "for a caught exception object");
272
273 if (0 == bc2_what)
274 rw_assert (false, 0, __LINE__,
275 "bad_cast::what() != 0 failed "
276 "for an assigned exception object");
277
278 if (bc_what && bc2_what)
279 rw_warn (0 == rw_strncmp (bc_what, bc2_what),
280 0, __LINE__,
281 "bad_cast::operator=(const bad_cast&): "
282 "\"%s\" != \"%s\"", bc_what, bc2_what);
283
284 // 18.5.2, p5
285 if (bc_what)
286 rw_assert (0 == rw_strncmp (bc.what (), bc.what ()),
287 0, __LINE__,
288 "bad_cast::what() const: \"%s\" != \"%s\"",
289 bc.what (), bc.what ());
290 }
291 catch (const std::exception&) {
292 caught = "std::exception";
293 }
294 catch (...) {
295 caught = "unknown exception";
296 }
297
298#if !defined (_RWSTD_NO_STD_BAD_CAST) \
299 || !defined (_RWSTD_NO_RUNTIME_IN_STD)
300
301 const char expect[] = "std::bad_cast";
302
303#else
304
305 const char expect[] = "std::bad_cast (alias for ::bad_cast)";
306
307#endif // !NO_STD_BAD_CAST || !NO_RUNTIME_IN_STD
308
309 rw_assert (0 == rw_strncmp (caught, "std::bad_cast"),
310 0, __LINE__,
311 "dynamic_cast<>() threw %s, expected %s; this suggests "
312 "that bad_cast might be defined in the wrong namespace",
313 caught, expect);
314
317
318# endif // _RWSTD_NO_DYNAMIC_CAST
319#endif // _RWSTD_NO_EXCEPTIONS
320 }
321
322 if (1) {
323 // exercise 18.5.3, class bad_typeid interface
324
325 // std::bad_cast must publicly derive from std::exception
326 const std::bad_typeid *pbt = 0;
327 const std::exception *pe = pbt;
328
329 // 18.5.2, p2
330 std::bad_typeid bt;
331
332 // 18.5.2, p4 - copy ctor
333 std::bad_typeid bt2 (bt);
334
335 // 18.5.2, p4 - assignment
336 std::bad_typeid& (std::bad_typeid::*p_op_assign)(const std::bad_typeid&)
337 _PTR_THROWS (()) = &std::bad_typeid::operator=;
338
339 // 18.5.2, p5
340 const char* (std::bad_typeid::*p_what)() const _PTR_THROWS (()) =
341 &std::bad_typeid::what;
342
343 _RWSTD_UNUSED (pbt);
344 _RWSTD_UNUSED (pe);
345 _RWSTD_UNUSED (bt);
346 _RWSTD_UNUSED (bt2);
347 _RWSTD_UNUSED (p_op_assign);
348 _RWSTD_UNUSED (p_what);
349 }
350
351 if (1) {
352 // exercise 18.5.3, class bad_typeid functionality
353
354#ifndef _RWSTD_NO_EXCEPTIONS
355
356 const char *caught = "no exception";
357
358 try {
359
360#if !defined (__GNUG__) || __GNUG__ > 2
361
362 B *b = 0;
363
364 // 5.2.8, p2 - typeid(0) throws std::bad_typeid
365 const std::type_info &ti = typeid (*b);
366
368 _RWSTD_UNUSED (ti);
369
370#else
371
372 // working around a gcc 2.x bug
373 caught = "SIGSEGV (program dumps core)";
374
375#endif // gcc < 3.0
376
377 }
378 catch (const std::bad_typeid &bt) {
379 caught = "std::bad_typeid";
380
381 // 18.5.2, p2
382 std::bad_typeid bt2;
383
384 // 18.5.2, p4 - copy ctor
385 std::bad_typeid bt3 (bt);
386
387 // verify that what() returns the same string
388 // after copy construction
389 rw_warn (0 == rw_strncmp (bt.what (), bt3.what ()),
390 0, __LINE__,
391 "std::bad_typeid::bad_typeid (const bad_typeid&): "
392 "\"%s\" != \"%s\"", bt.what (), bt3.what ());
393
394 // 18.5.2, p4 - assignment
395 bt2 = bt;
396
397 // verify that what() returns the same string
398 // after assignment
399 rw_warn (0 == rw_strncmp (bt.what (), bt2.what ()),
400 0, __LINE__,
401 "std::bad_typeid::operator=(const bad_typeid&): "
402 "\"%s\" != \"%s\"", bt.what (), bt2.what ());
403
404 // 18.5.2, p5
405 rw_assert (0 == rw_strncmp (bt.what (), bt.what ()),
406 0, __LINE__,
407 "std::bad_typeid::what() const: "
408 "\"%s\" != \"%s\"", bt.what (), bt.what ());
409 }
410 catch (const std::exception&) {
411 caught = "std::exception";
412 }
413 catch (...) {
414 caught = "unknown exception";
415 }
416
417#if !defined (_RWSTD_NO_STD_BAD_TYPEID) \
418 || !defined (_RWSTD_NO_RUNTIME_IN_STD)
419
420 const char expect[] = "std::bad_typeid";
421
422#else
423
424 const char expect[] = "std::bad_typeid (alias for ::bad_typeid)";
425
426#endif // !NO_STD_BAD_TYPEID || !NO_RUNTIME_IN_STD
427
428
429 rw_assert (0 == rw_strncmp (caught, "std::bad_typeid"),
430 0, __LINE__,
431 "typeid ((T*)0) threw %s, expected %s; this suggests "
432 "that bad_typeid might be defined in the wrong namespace",
433 caught, expect);
434
435#endif // _RWSTD_NO_EXCEPTIONS
436 }
437
438 return 0;
439}
440
441int main (int argc, char* argv [])
442{
443 return rw_test (argc, argv, __FILE__,
444 "lib.support.rtti",
445 0 /* no comment */,
446 run_test,
447 "",
448 (void*)0);
449}
#define d1
Definition 17.names.cpp:228
#define b
Definition 17.names.cpp:110
#define d2
Definition 17.names.cpp:254
void foo()
#define _PTR_THROWS(spec)
void run_test(const ForwardIterator &dummy, T *, Predicate *pred)
#define main
int caught
bad_typeid
#define _RWSTD_UNUSED(arg)
Definition _defs.h:972
#define _THROW(ex)
Definition _defs.h:852
Definition json.h:5363
_TEST_EXPORT int rw_test(int argc, char *argv[], const char *filename, const char *clause, const char *comment, int(*testfun)(int, char **), const char *optspec,...)
_TEST_EXPORT int rw_assert(int, const char *, int, const char *,...)
Definition driver.cpp:1630
_TEST_EXPORT int rw_warn(int, const char *, int, const char *,...)
Definition driver.cpp:1647
_TEST_EXPORT int rw_strncmp(const char *, const char *, _RWSTD_SIZE_T=_RWSTD_SIZE_MAX, int=CMP_NULTERM)
#define bool
Definition stdbool.h:24
virtual ~B()