Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
18.exception.cpp
Go to the documentation of this file.
1
29#ifdef __SUNPRO_CC
30 // working around a SunPro/SunOS 5.8 bug (PR #26255)
31# include <time.h>
32#endif // __SUNPRO_CC
33
34#include <exception> // for bad_exception, exception
35#include <ios> // for ios_base::failure
36#include <new> // for bad_alloc
37#include <stdexcept> // for exception classes
38#include <typeinfo> // for bad_cast, bad_typeid
39
40#include <csignal> // for signal(), SIGABRT
41#include <cstdio> // for size_t, sprintf()
42#include <cstring> // for strcmp(), strlen()
43
44#include <rw/_error.h> // for _RWSTD_ERROR_XXX constants
45
46
47#ifndef _RWSTD_NO_SETRLIMIT
48# include <sys/resource.h> // for setrlimit()
49#endif // _RWSTD_NO_SETRLIMIT
50
51#include <rw_driver.h>
52
53
54#ifdef _RWSTD_OS_LINUX
55 // use siglongjmp() and sigsetjmp() on Linux to avoid
56 // http://sourceware.org/bugzilla/show_bug.cgi?id=2351
57
58# ifndef _RWSTD_NO_PURE_C_HEADERS
59# include <csetjmp> // for jmp_buf
60
61// when using "pure C headers" on Linux (i.e., with EDG eccp)
62// declare POSIX functions that aren't otherwise required or
63// expected to be declared by strictly conforming standard
64// C/C++ headers
65
66extern "C" {
67
68typedef std::jmp_buf sigjmp_buf;
69
70// Linux/glibc-specific:
71int __sigsetjmp (sigjmp_buf, int);
72
73# define sigsetjmp(env, savemask) __sigsetjmp (env, savemask)
74
75void siglongjmp (sigjmp_buf, int);
76
77} // extern "C"
78
79# define RW_JMP_BUF std::jmp_buf
80# define RW_SETJMP(env) sigsetjmp (env, 0)
81# define RW_LONGJMP(env, val) siglongjmp (env, val)
82
83# else // if defined _RWSTD_NO_PURE_C_HEADERS
84# include <setjmp.h> // for siglongjmp(), sigsetjmp()
85
86# define RW_JMP_BUF jmp_buf
87# define RW_SETJMP(env) sigsetjmp (env, 0)
88# define RW_LONGJMP(env, val) siglongjmp (env, val)
89# endif // _RWSTD_NO_PURE_C_HEADERS
90
91#else // if !defined (_RWSTD_OS_LINUX)
92# include <csetjmp> // for longjmp(), setjmp()
93
94# define RW_JMP_BUF std::jmp_buf
95# ifdef setjmp
96# define RW_SETJMP(env) setjmp (env)
97# else
98# define RW_SETJMP(env) std::setjmp (env)
99# endif
100# define RW_LONGJMP(env, val) std::longjmp (env, val)
101#endif // _RWSTD_OS_LINUX
102
103
105// check header <exception> synopsis
106static void
107test_synopsis ()
108{
109 // check header <exception> synopsis
110 rw_info (0, 0, __LINE__, "header <exception> synopsis");
111
112 // verify that classes are declared
114
115 // verify that bad_exception publicly derives from exception
116 pex = (std::bad_exception*)0;
117 _RWSTD_UNUSED (pex);
118
119 // check handler types
120 void (*phandler)() = (std::unexpected_handler)0;
121 phandler = (std::terminate_handler)0;
122
123 // check unexpected and terminate
124 phandler = &std::unexpected;
125 phandler = &std::terminate;
126 _RWSTD_UNUSED (phandler);
127
128 // check set_{unexpected,terminate}
129 std::unexpected_handler (*pset)(std::unexpected_handler) _PTR_THROWS (());
130
131 pset = &std::set_unexpected;
132 pset = &std::set_terminate;
133 _RWSTD_UNUSED (pset);
134
135 // check uncaught_exception()
136 // see http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/lwg-defects.html#70
137 // for exception specification details
138 bool (*pue)() _PTR_THROWS (()) = &std::uncaught_exception;
139 _RWSTD_UNUSED (pue);
140}
141
142
145// defined at global scope rather than as locals
146// to work around an MSVC 6.0 bug (see PR #26305)
147static bool dtor_virtual = false;
148static bool what_virtual = false;
149
150// check the signatures of class exception and bad_exception members
151static void
153{
154// verify that a member function is accessible and has the appropriate
155// signature, including return type and exception specification
156#define MEMFUN(result, T, name, arg_list) do { \
157 result (T::*pf) arg_list _PTR_THROWS (()) = &T::name; \
158 _RWSTD_UNUSED (pf); \
159 } while (0)
160
161 rw_info (0, 0, __LINE__, "std::exception member function signatures");
162
163 // verify 18.6.1 [lib.exception]
164
165 // verify that a public default and copy ctors exist
168
170 (const std::exception&));
171 MEMFUN (const char*, std::exception, what, () const);
172
173 struct test_exception_virtuals: std::exception {
174
175 ~test_exception_virtuals () _THROWS (()) {
176 dtor_virtual = true;
177 }
178 const char* what () const _THROWS (()) {
179 what_virtual = true;
180
181 // working around an MSVC 6.0 bug (PR #26330)
182 typedef std::exception Base;
183 return Base::what ();
184 }
185 };
186
187 std::exception *pe = new test_exception_virtuals;
188
189 // verify that destructor and what() are virtual
190 pe->what ();
191 rw_assert (what_virtual, 0, __LINE__,
192 "std::exception::what() not virtual");
193
194 delete pe;
195 rw_assert (dtor_virtual, 0, __LINE__,
196 "std::exception::~exception() not virtual");
197
198
199 rw_info (0, 0, __LINE__, "std::bad_exception member function signatures");
200
201 // verify 18.6.2.1 [lib.bad.exception]
202 // verify that a public default and copy ctors exist
204 std::bad_exception be2 (be1);
205
207 (const std::bad_exception&));
208 MEMFUN (const char*, std::bad_exception, what, () const);
209
210 dtor_virtual = false;
211 what_virtual = false;
212
213 struct test_bad_exception_virtuals: std::bad_exception {
214
215 ~test_bad_exception_virtuals () _THROWS (()) {
216 dtor_virtual = true;
217 }
218 const char* what () const _THROWS (()) {
219 what_virtual = true;
220
221 // working around an MSVC 6.0 bug (PR #26330)
222 typedef std::bad_exception Base;
223 return Base::what ();
224 }
225 };
226
227 pe = new test_bad_exception_virtuals;
228
229 // verify that destructor and what() are virtual
230 pe->what ();
231 rw_assert (what_virtual, 0, __LINE__,
232 "std::bad_exception::what() not virtual");
233
234 delete pe;
235 rw_assert (dtor_virtual, 0, __LINE__,
236 "std::bad_exception::~bad_exception() not virtual");
237}
238
239
241// test globals (to make the accessible in signal and other handlers)
242std::unexpected_handler puh; // previous unexpected_handler
243std::terminate_handler pth; // previous terminate_handler
244int expect_abort; // SIGABRT expected if 1
245int expect_terminate; // terminate expected if 1
246int expect_unexpected; // unexpected expected if 1
247int expect_throw_proc; // throw_proc expected if 1
249
250
252// called in response to abort() (called from std::terminate())
253extern "C" {
254
255static void
256SIGABRT_handler (int signo)
257{
258 rw_assert (1 == expect_abort && SIGABRT == signo, 0, __LINE__,
259 "SIGABRT unexpected");
260
261 // reestablish handler
262 std::signal (SIGABRT, SIGABRT_handler);
263
264 expect_abort = -1;
265
266 RW_LONGJMP (jmpenv, 1);
267}
268
269} // extern "C"
270
271
273static void
274test_terminate_handler ()
275{
276 rw_assert (1 == expect_terminate, 0, __LINE__,
277 "std::terminate() unexpected");
278
279 expect_terminate = -1;
280
281 // establish a handler for SIGABRT (raised from abort())
282 std::signal (SIGABRT, SIGABRT_handler);
283
284 // invoke default terminate handler
285 pth ();
286
287 // shouldn't be reached
288 rw_assert (false, 0, __LINE__,
289 "std::terminate() not called or returned");
290
291 RW_LONGJMP (jmpenv, -1);
292}
293
294
296static void
297test_unexpected_handler ()
298{
299 rw_assert (1 == expect_unexpected, 0, __LINE__,
300 "std::unexpected() unexpected");
301
303
304 // establish a handler for SIGABRT (raised from abort())
305 std::signal (SIGABRT, SIGABRT_handler);
306
307 expect_abort = 1;
309
310 // throw an exception outside of any try block
311 // useless conditional used to prevent warnings
312 if (expect_abort)
313 throw 1;
314
315 // shouldn't be reached
316 rw_assert (false, 0, __LINE__,
317 "std::terminate() not called or returned");
318
319 RW_LONGJMP (jmpenv, -1);
320}
321
322
324// test the effects of 18.6
325static void
326test_effects ()
327{
328 // verify 18.6.1, p8: what() returns an implementation-defined NTBS
330 const char *what = e1.what ();
331 rw_assert (what && 1 <= 1 + std::strlen (what), 0, __LINE__,
332 "std::exception::what() != 0");
333
335 what = e2.what ();
336 rw_assert (what && 1 <= 1 + std::strlen (what), 0, __LINE__,
337 "std::exception::what() != 0");
338
339 // verify 18.6.2.1, p5: what() returns an implementation-defined NTBS
341 what = e3.what ();
342 rw_assert (what && 1 <= 1 + std::strlen (what), 0, __LINE__,
343 "std::bad_exception::what() != 0");
344
345 std::exception e4 (e3);
346 what = e4.what ();
347 rw_assert (what && 1 <= 1 + std::strlen (what), 0, __LINE__,
348 "std::bad_exception::what()");
349
350#if !defined (_RWSTD_NO_EXCEPTIONS) \
351 && !defined (_RWSTD_NO_EXCEPTION_SPECIFICATION)
352
353 struct S {
354 static void foo () throw (double) {
355 throw 1;
356 }
357 };
358
359 rw_info (0, 0, __LINE__, "std::set_unexpected()");
360 rw_info (0, 0, __LINE__, "std::set_terminate()");
361
362 // determine the address of the default
363 // handlers and replace them with our own
364 puh = std::set_unexpected (test_unexpected_handler);
365 pth = std::set_terminate (test_terminate_handler);
366
367 // invoke a function that throws an exception
368 // that is not in its exception specification
370
371 try {
372 S::foo ();
373 }
374 catch (...) {
375 rw_assert (0, 0, __LINE__, "incompatible exception propagated");
376 }
377
378 RW_LONGJMP (jmpenv, -1);
379
380#else
381
382 // prevent failures due to functionality not implemented in compiler
383 expect_abort = -1;
384 expect_terminate = -1;
386
387#endif // _RWSTD_NO_EXCEPTIONS && ...
388}
389
390
393 bool *presult_;
394
396 *presult_ = std::uncaught_exception ();
397 }
398};
399
400static void
401test_uncaught_exception ()
402{
403 rw_info (0, 0, __LINE__, "std::uncaught_exception()");
404
405 bool expect;
407
408#if !defined (_RWSTD_NO_STD_UNCAUGHT_EXCEPTION) \
409 || !defined (_RWSTD_NO_GLOBAL_UNCAUGHT_EXCEPTION)
410
411 expect = false;
412
413#else
414
415# ifndef _RWSTD_NO_EXCEPTIONS
416
417 expect = true;
418
419# else // if defined (_RWSTD_NO_EXCEPTIONS)
420
421 expect = false;
422
423# endif // _RWSTD_NO_EXCEPTIONS)
424
425#endif
426
427 rw_assert (uncaught == expect, 0, __LINE__,
428 "std::uncaught_exception() == %d, got %d", expect, uncaught);
429
430#ifndef _RWSTD_NO_EXCEPTIONS
431
432 expect = true;
433
434 try {
436
437 chk.presult_ = &uncaught;
438
439 // silence (bogus) EDG eccp unused variable remark 550
440 _RWSTD_UNUSED (chk);
441
442 throw 0;
443 }
444 catch (...) {
445 }
446
447#else // if defined (_RWSTD_NO_EXCEPTIONS)
448
449 expect = false;
450
451 {
453
454 chk.presult_ = &uncaught;
455 }
456
457#endif // _RWSTD_NO_EXCEPTIONS
458
459 rw_assert (uncaught == expect, 0, __LINE__,
460 "std::uncaught_exception() == %d, got %d", expect, uncaught);
461}
462
463
465// original throw proc
466static void (*const pthrow_proc_save)(int, char*) = _RW::__rw_throw_proc;
467
468// replaces the original throw proc
469static void
470test_throw_proc (int id, char *s)
471{
472 rw_assert (id == expect_throw_proc, 0, __LINE__,
473 "throw_proc expected %d, got %d (\"%s\")",
474 expect_throw_proc, id, s);
475
476 _RW::__rw_free_what_buf (s);
477
478 // signal that we were successfully called and with what value
479 expect_throw_proc = -id;
480}
481
482
484// exercise __rw::__rw_throw() and __rw::__rw_throw_proc()
485static void
486test_rw_throw ()
487{
488#ifndef _RWSTD_NO_EXCEPTIONS
489
490 rw_info (0, 0, __LINE__, "__rw::__rw_throw()");
491
492 // exception format strings
493 static const char* strings[] = { _RWSTD_ERROR_STRINGS };
494
495 // exception id's: strings [i + 1] corresponds to expect [i]
496 static const int expect[] = {
497 _RWSTD_ERROR_FIRST + 1, // _RWSTD_ERROR_EXCEPTION
498 _RWSTD_ERROR_FIRST + 2, // _RWSTD_ERROR_BAD_EXCEPTION
499 _RWSTD_ERROR_FIRST + 3, // _RWSTD_ERROR_BAD_ALLOC
500 _RWSTD_ERROR_FIRST + 4, // _RWSTD_ERROR_BAD_CAST
510
515 };
516
517 const char* const ex_names[] = {
518 "std::exception",
519 "std::bad_exception",
520 "std::bad_alloc",
521 "std::bad_cast",
522 "std::logic_error",
523 "std::domain_error",
524 "std::invalid_argument",
525 "std::length_error",
526 "std::out_of_range",
527 "std::runtime_error",
528 "std::range_error",
529 "std::overflow_error",
530 "std::underflow_error",
531
532 "std::ios_base::failbit_set",
533 "std::ios_base::badbit_set",
534 "std::ios_base::eofbit_set",
535 "std::ios_base::failure"
536 };
537
538 const char empty[] = "";
539
540 // raise each exception by its id, check that
541 // an exception object of the correct type is thrown
542 for (unsigned i = 0; i != sizeof expect / sizeof *expect; ++i) {
543
544 rw_info (0, 0, __LINE__, "%s", ex_names [i]);
545
546 int caught = -1;
547
548 // set up a new throw proc (prevent exceptions)
549 _RW::__rw_throw_proc = test_throw_proc;
550
551 // no exception should be thrown at this point
552 expect_throw_proc = expect [i];
553
554 const char format[] = _RWSTD_FILE_LINE;
555 const char func[] = "void test_rwt_hrow (Test&)";
556
557 _RW::__rw_throw (expect [i], format, func, empty, empty, empty);
558
559 rw_assert (expect [i] == -expect_throw_proc, 0, __LINE__,
560 "%d. throw_proc (%d, ...) not called", i, expect [i]);
561
562 try {
563 // reestablish original throw proc
564 _RW::__rw_throw_proc = pthrow_proc_save;
565
566 // expect an exception
567 _RW::__rw_throw (expect [i], format, func, empty, empty, empty);
568
569 rw_assert (false, 0, __LINE__,
570 "%d. __rw::__rw_throw(%d, ...) returned",
571 i, expect [i]);
572 }
573 catch (std::domain_error &ex) {
574 rw_assert (!!ex.what (), 0, __LINE__,
575 "domain_error::what() != 0");
577 }
578 catch (std::invalid_argument &ex) {
579 rw_assert (!!ex.what (), 0, __LINE__,
580 "invalid_argument::what() != 0");
582 }
583 catch (std::length_error &ex) {
584 rw_assert (!!ex.what (), 0, __LINE__,
585 "length_error::what() != 0");
587 }
588 catch (std::out_of_range &ex) {
589 rw_assert (!!ex.what (), 0, __LINE__,
590 "out_of_range::what() != 0");
592 }
593 catch (std::range_error &ex) {
594 rw_assert (!!ex.what (), 0, __LINE__,
595 "range_error::what() != 0");
597 }
598 catch (std::overflow_error &ex) {
599 rw_assert (!!ex.what (), 0, __LINE__,
600 "overflow_error::what() != 0");
602 }
603 catch (std::underflow_error &ex) {
604 rw_assert (!!ex.what (), 0, __LINE__,
605 "underflow_error::what() != 0");
607 }
608 catch (std::logic_error &ex) {
609 rw_assert (!!ex.what (), 0, __LINE__,
610 "logic_error::what() != 0");
612 }
613 catch (std::runtime_error &ex) {
614 rw_assert (!!ex.what (), 0, __LINE__,
615 "runtime_error::what() != 0");
617 }
618 catch (std::bad_alloc &ex) {
619 rw_assert (!!ex.what (), 0, __LINE__,
620 "bad_alloc::what() != 0");
621 caught = _RWSTD_ERROR_FIRST + 3; // _RWSTD_BAD_ALLOC
622 }
623 catch (std::bad_exception &ex) {
624 rw_assert (!!ex.what (), 0, __LINE__,
625 "bad_exception::what() != 0");
626 caught = _RWSTD_ERROR_FIRST + 2; // _RWSTD_ERROR_BAD_EXCEPTION
627 }
628 catch (std::bad_cast &ex) {
629 rw_assert (!!ex.what (), 0, __LINE__,
630 "bad_cast::what() != 0");
631 caught = _RWSTD_ERROR_FIRST + 4; // _RWSTD_ERROR_BAD_CAST;
632 }
633
634#ifdef _RWSTD_ERROR_BAD_TYPEID
635
636 catch (std::bad_typeid &ex) {
637 rw_assert (!!ex.what (), 0, __LINE__,
638 "bad_typeid::what() != 0");
639 caught = _RWSTD_ERROR_BAD_TYPEID;
640 }
641
642#endif // _RWSTD_ERROR_BAD_TYPEID;
643
644#ifndef _RWSTD_NO_EXT_FAILURE
645
646 catch (std::ios_base::failbit_set &ex) {
647 rw_assert (!!ex.what (), 0, __LINE__,
648 "ios_base::failbit_set::what() != 0");
650 }
651 catch (std::ios_base::badbit_set &ex) {
652 rw_assert (!!ex.what (), 0, __LINE__,
653 "ios_base::badbit_set::what() != 0");
655 }
656 catch (std::ios_base::eofbit_set &ex) {
657 rw_assert (!!ex.what (), 0, __LINE__,
658 "ios_base::eofbit_set::what() != 0");
660 }
661
662#endif // _RWSTD_NO_EXT_FAILURE
663
664 catch (std::ios_base::failure &ex) {
665 rw_assert (!!ex.what (), 0, __LINE__,
666 "ios_base::failure::what() != 0");
668 }
669 catch (std::exception &ex) {
670 rw_assert (!!ex.what (), 0, __LINE__,
671 "exception::what() != 0");
672 caught = _RWSTD_ERROR_FIRST + 1; // _RWSTD_ERROR_EXCEPTION
673 }
674 catch (...) {
675 caught = -1;
676 }
677
678 rw_assert (expect [i] == caught, 0, __LINE__,
679 "%d. expected %d, caught %d", i, expect [i], caught);
680 }
681
682
683 // reestablish original throw proc
684 _RW::__rw_throw_proc = pthrow_proc_save;
685
686 char str [1024];
687 char result [2 * sizeof str];
688
689 rw_info (0, 0, __LINE__,
690 "exercising throwing standard exception objects "
691 "constructed with string arguments up to %zu "
692 "characters long (not including context info)",
693 sizeof str);
694
695 // exercise the ability or __rw_throw() to correctly format
696 // strings of arbitrary length, also verify that format string
697 // macros are used to format the what() strings as expected
698 for (unsigned j = 0; j != sizeof str - 1; ++j) {
699
700 // exclude exception, bad_alloc, bad_cast, and bad_exception
701 // they are typically generated by the compiler and their
702 // what() strings are implementation-specific
703 size_t en = j % ((sizeof expect / sizeof *expect) - 5);
704
705 // null-terminate str
706 str [j] = '\0';
707
708 std::sprintf (result, strings [en + 5], __FILE__, str,
709 empty, empty, empty);
710
711 try {
712 // expect an exception
713 _RW::__rw_throw (expect [en + 4], __FILE__, str,
714 empty, empty, empty);
715
716 rw_assert (false, 0, __LINE__,
717 "%d. __rw::__rw_throw (%d, ...) returned",
718 j, expect [en + 4]);
719 }
720 catch (std::exception &e) {
721 rw_assert (e.what () && 0 == std::strcmp (e.what (), result),
722 0, __LINE__,
723 "%u. \"%s\" != \"%s\" [%u]",
724 j, e.what (), result, en + 3);
725 }
726
727 // append a decimal digit
728 str [j] = '0' + j % 10;
729 }
730
731#endif // _RWSTD_NO_EXCEPTIONS
732}
733
734
736static void
737throwing_unexpected_handler ()
738{
739 // throw an exception that can't otherwise be possibly thrown
740 // to induce std::bad_exception to be rethrown by the langauage
741 // runtime library
742
743 struct PrivateStruct { };
744
745 // prevent assertions from the installed SIGABRT handler
746 // and terminate_handler in case they are invoked as a
747 // result of throwing the exception below
749 expect_abort = 1;
750
751 throw PrivateStruct ();
752}
753
754
759
760
761// helper classes used by the bad_cast test
762// defined at namespace scope rather than at local scope
763// to work around an Intel C++ 10.0 ICE (see STDCXX-475)
764struct Base { virtual ~Base () { } };
765struct Derived1: Base { };
766struct Derived2: Base { };
767
768
769// induce the language runtime into throwing an exception
770// returns e if exception cannot bee thrown
772induce_exception (RuntimeExceptionId reid, const char *name)
773{
774 const char *why = 0;
775
776 switch (reid) {
777
778 case E_bad_alloc: {
779
780#ifndef _RWSTD_NO_NEW_THROWS
781
782# ifndef _RWSTD_NO_SETRLIMIT
783
784# if !defined (__HP_aCC)
785
786 // work around an HP aCC 5.xx (IPF) bug (PR #29014)
787
788 // retrieve the current resource limits
789 struct rlimit rl = { 0, 0 };
790 if (getrlimit (RLIMIT_DATA, &rl))
791 return E_error;
792
793 // set the soft limit, leave hard limit unchanged
794 rl.rlim_cur = 0;
795 rw_warn (0 == setrlimit (RLIMIT_DATA, &rl), 0, __LINE__,
796 "setrlimit (RLIMIT_DATA, ...) failed: %m");
797
798 try {
799
800# endif // __HP_aCC
801# endif // _RWSTD_NO_SETRLIMIT
802
803 // try to allocate a huge amount of memory to induce bad_alloc
804 const std::size_t huge_amount = _RWSTD_SIZE_MAX - 4096;
805
806 void * const p = ::operator new (huge_amount);
807
808 ::operator delete (p);
809
810# ifndef _RWSTD_NO_SETRLIMIT
811# if !defined (__HP_aCC)
812
813 }
814 catch (...) {
815
816 // reset the soft limit back to the value of the hard limit
817 rl.rlim_cur = rl.rlim_max;
818 rw_warn (0 == setrlimit (RLIMIT_DATA, &rl), 0, __LINE__,
819 "setrlimit (RLIMIT_DATA, ...) failed: %m");
820
821 // rethrow bad_alloc
822 throw;
823 }
824
825# endif // __HP_aCC
826
827 return E_error;
828
829# endif // _RWSTD_NO_SETRLIMIT
830
831#else // if defined (_RWSTD_NO_NEW_THROWS)
832
833 why = "_RWSTD_NO_NEW_THROWS is #defined";
834
835 break; // unable to induce bad_alloc
836
837#endif // NO_NEW_THROWS
838
839 }
840
841 case E_bad_cast: {
842
843#ifndef _RWSTD_NO_DYNAMIC_CAST
844
845 Derived1 b;
846 Base &a = b;
847
848 // induce bad_cast
849 dynamic_cast<Derived2&>(a);
850
851 return E_error;
852
853#else // if defined (_RWSTD_NO_DYNAMIC_CAST)
854
855 why = "_RWSTD_NO_DYNAMIC_CAST is #defined";
856
857 break; // unable to induce bad_cast
858
859#endif // _RWSTD_NO_DYNAMIC_CAST
860 }
861
862 case E_bad_exception: {
863
864#ifndef _RWSTD_NO_EXCEPTION_SPECIFICATION
865
866 std::set_unexpected (throwing_unexpected_handler);
867
868 struct S {
869 // induce bad_exception
870 S () throw (std::bad_exception) { throw 0; }
871 } s;
872
874 return E_error;
875
876#else // if defined (_RWSTD_NO_EXCEPTION_SPECIFICATION)
877
878 why = "_RWSTD_NO_EXCEPTION_SPECIFICATION is #defined";
879
880 break; // unable to induce bad_exception
881
882#endif // _RWSTD_NO_EXCEPTION_SPECIFICATION
883
884 }
885
886 case E_bad_typeid: {
887
888#if !defined (_RWSTD_NO_GLOBAL_BAD_TYPEID) \
889 || !defined (_RWSTD_NO_STD_BAD_TYPEID)
890
891 struct S { virtual ~S () { } } *s = 0;
892
893 // induce bad_typeid
894 typeid (*s);
895
896 return E_error;
897
898#else // if _RWSTD_NO_GLOBAL_BAD_TYPEID && _RWSTD_NO_STD_BAD_TYPEID
899
900 why = "both _RWSTD_NO_GLOBAL_BAD_TYPEID and _RWSTD_NO_STD_BAD_TYPEID "
901 "are #defined";
902
903 break; // unable to induce bad_typeid
904
905#endif // NO_BAD_TYPEID
906
907 }
908
909 default:
910 break;
911 }
912
913 rw_warn (0, 0, __LINE__, "unable to induce std::%s: %s\n", name, why);
914
915 return reid;
916}
917
918
920static const RuntimeExceptionId
921rt_exceptions[] = {
923 E_error
924};
925
926static const char* const
927rt_exception_names[] = {
928 "bad_alloc", "bad_cast", "bad_exception", "bad_typeid"
929};
930
931static int
932opt_rt_exception [E_error];
933
934
935static void
936test_runtime ()
937{
938#ifndef _RWSTD_NO_EXCEPTIONS
939
940 rw_info (0, 0, __LINE__, "runtime support for exceptions");
941
942
943 // using static to avoid gcc 3.x warning: variable
944 // might be clobbered by `longjmp' or `vfork'
945
946 for (static unsigned i = 0; E_error != rt_exceptions [i]; ++i) {
947
948 const RuntimeExceptionId ex_id = rt_exceptions [i];
949 const char* const ex_name = rt_exception_names [i];
950
951 if (0 == rw_note (0 <= opt_rt_exception [i],
952 0, __LINE__,
953 "std::%s test disabled", ex_name))
954 continue;
955
956 rw_info (0, 0, __LINE__, "std::%s", ex_name);
957
958 static int ex0;
959 static int ex1;
960
961 ex0 = ex1 = 0;
962
963 try {
964 try {
965 // jump back here if the induced exception causes
966 // a call to terminate() and/or raises SIGABRT
967 if (0 == RW_SETJMP (jmpenv)) {
968
969 // try to induce the standard exception
970 if (ex_id == induce_exception (ex_id, ex_name)) {
971 ex0 = -1;
972 ex1 = -1;
973 }
974 }
975 else {
976 rw_assert (false, 0, __LINE__,
977 "inducing std::%s caused a call "
978 "to std::terminate()", ex_name);
979 // prevent additional assertions
980 ex0 = -1;
981 }
982 }
983 catch (std::exception&) {
984 // so far so good, rethrow and try to catch again
985 ex0 = 0;
986 throw;
987 }
988 catch (...) {
989 // failure to catch a standard exception using std::exception
990 // most likely indication of class exception having been
991 // defined in a different namespace by the C++ Standard
992 // library than by the language support library (compiler
993 // runtime)
994 ex0 = -2;
995 throw;
996 }
997 }
998 catch (std::bad_alloc&) { ex1 = E_bad_alloc; }
999 catch (std::bad_cast&) { ex1 = E_bad_cast; }
1000 catch (std::bad_exception&) { ex1 = E_bad_exception; }
1001 catch (std::bad_typeid&) { ex1 = E_bad_typeid; }
1002 catch (...) { ex1 = -2; }
1003
1004 rw_assert (-1 == ex0 || 0 == ex0, 0, __LINE__,
1005 "std::%s thrown, std::exception not caught",
1006 ex_name);
1007
1008 rw_assert (-1 == ex1 || rt_exceptions [i] == ex1, 0, __LINE__,
1009 "std::%s thrown, unknown exception caught",
1010 ex_name);
1011 }
1012
1013#endif // _RWSTD_NO_EXCEPTIONS
1014}
1015
1016
1018static int opt_synopsis; // for --<toggle>-synopis
1019static int opt_signatures; // for --<toggle>-signatures
1020static int opt_uncaught; // for --<toggle>-uncaught_exception
1021static int opt_effects; // for --<toggle>-effects
1022static int opt_rw_throw; // for --<toggle>-rw_throw
1023static int opt_runtime; // for --<toggle>-runtime
1024
1025static int
1026run_test (int, char**)
1027{
1028 if (rw_note (0 <= opt_synopsis, 0, __LINE__,
1029 "test of <exception> synopsis disabled"))
1030 test_synopsis ();
1031
1032 // check the signatures of class exception and bad_exception members
1033 if (rw_note (0 <= opt_signatures, 0, __LINE__,
1034 "test of function signatures disabled"))
1035 test_signatures ();
1036
1037 // exercise std::uncaught_exception() before running any other tests
1038 // since some of them might affect the correct behavior of the function
1039 // (if they violate such constraints as returning from a call to
1040 // std::terminate())
1041 if (rw_note (0 <= opt_uncaught, 0, __LINE__,
1042 "test of uncaught_exception() disabled"))
1043 test_uncaught_exception ();
1044
1045 // exercise __rw::__rw_throw() and __rw::__rw_throw_proc()
1046 if (rw_note (0 <= opt_rw_throw, 0, __LINE__,
1047 "test of __rw_throw() disabled"))
1048 test_rw_throw ();
1049
1050 // exercise the cooperation between the C++ standard library and
1051 // the runtime support library when throwing standard exceptions
1052 if (rw_note (0 <= opt_runtime, 0, __LINE__,
1053 "test of runtime support disabled"))
1054 test_runtime ();
1055
1056 // exercise the effects last to defer potential problems
1057 // due to the tests returning (jumping) out of the handlers
1058 if (rw_note (0 <= opt_effects, 0, __LINE__,
1059 "test of effects disabled")) {
1060 // test the effects of 18.6
1061 if (0 == RW_SETJMP (jmpenv)) {
1062 test_effects ();
1063 }
1064
1065 // verify that test worked as expected (each handler sets
1066 // its own expect_xxx variable to -1 after it's been called)
1067 rw_error (-1 == expect_abort, 0, __LINE__,
1068 "abort() was called unexpectedly");
1069
1070 rw_error (-1 == expect_terminate, 0, __LINE__,
1071 "terminate() was called unexpectedly");
1072
1073 rw_error (-1 == expect_unexpected, 0, __LINE__,
1074 "unexpected() was called unexpectedly");
1075 }
1076
1077 return 0;
1078}
1079
1080
1082int main (int argc, char *argv[])
1083{
1084 return rw_test (argc, argv, __FILE__,
1085 "lib.support.exception",
1086 0 /* no comment */,
1087 run_test,
1088 "|-synopsis~ "
1089 "|-signatures~ "
1090 "|-uncaught_exception~ "
1091 "|-effects~ "
1092 "|-rw_throw~ "
1093 "|-runtime~ "
1094 "|-bad_alloc~ "
1095 "|-bad_cast~ "
1096 "|-bad_exception~ "
1097 "|-bad_typeid~",
1098 &opt_synopsis,
1099 &opt_signatures,
1100 &opt_uncaught,
1101 &opt_effects,
1102 &opt_rw_throw,
1103 &opt_runtime,
1104 opt_rt_exception + E_bad_alloc,
1105 opt_rt_exception + E_bad_cast,
1106 opt_rt_exception + E_bad_exception,
1107 opt_rt_exception + E_bad_typeid,
1108 0 /* sentinel */);
1109}
#define i
Definition 17.names.cpp:126
#define e
Definition 17.names.cpp:118
#define e1
Definition 17.names.cpp:229
#define a
Definition 17.names.cpp:109
#define j
Definition 17.names.cpp:127
#define b
Definition 17.names.cpp:110
#define s
#define p
Definition 17.names.cpp:132
#define e2
Definition 17.names.cpp:255
#define S
Definition 17.names.cpp:162
int expect_terminate
#define RW_JMP_BUF
int expect_abort
#define MEMFUN(result, T, name, arg_list)
#define RW_SETJMP(env)
int expect_unexpected
#define RW_LONGJMP(env, val)
RuntimeExceptionId
@ E_bad_cast
@ E_error
@ E_bad_typeid
@ E_bad_exception
@ E_bad_alloc
std::terminate_handler pth
int expect_throw_proc
std::unexpected_handler puh
RW_JMP_BUF jmpenv
volatile int result
#define _PTR_THROWS(spec)
void SIGABRT_handler(int)
void test_signatures(Vector *, T *, Allocator)
void run_test(const ForwardIterator &dummy, T *, Predicate *pred)
#define main
int caught
#define _THROWS()
#define foo(buf, s,...)
#define SIGABRT
#define _RWSTD_UNUSED(arg)
Definition _defs.h:972
#define _RWSTD_FILE_LINE
Definition _defs.h:1129
#define _RWSTD_ERROR_OVERFLOW_ERROR
Definition _error.h:96
#define _RWSTD_ERROR_IOSTATE_BIT_SET
Definition _error.h:102
#define _RWSTD_ERROR_RUNTIME_ERROR
Definition _error.h:94
#define _RWSTD_ERROR_STRINGS
Definition _error.h:113
#define _RWSTD_ERROR_FAILBIT_SET
Definition _error.h:99
#define _RWSTD_ERROR_FIRST
Definition _error.h:78
#define _RWSTD_ERROR_RANGE_ERROR
Definition _error.h:95
#define _RWSTD_ERROR_LOGIC_ERROR
Definition _error.h:89
#define _RWSTD_ERROR_LENGTH_ERROR
Definition _error.h:92
#define _RWSTD_ERROR_INVALID_ARGUMENT
Definition _error.h:91
#define _RWSTD_ERROR_BADBIT_SET
Definition _error.h:100
#define _RWSTD_ERROR_OUT_OF_RANGE
Definition _error.h:93
#define _RWSTD_ERROR_UNDERFLOW_ERROR
Definition _error.h:97
#define _RWSTD_ERROR_DOMAIN_ERROR
Definition _error.h:90
#define _RWSTD_ERROR_EOFBIT_SET
Definition _error.h:101
const char * name
Definition codecvt1.cpp:72
const char * str
Definition exec.cpp:170
Definition json.h:5363
terminate_handler set_terminate(terminate_handler)
unexpected_handler set_unexpected(void(*)())
bool uncaught_exception()
_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_info(int, const char *, int, const char *,...)
Definition driver.cpp:1681
_TEST_EXPORT int rw_note(int, const char *, int, const char *,...)
Definition driver.cpp:1664
_TEST_EXPORT int rw_assert(int, const char *, int, const char *,...)
Definition driver.cpp:1630
_TEST_EXPORT int rw_error(int, const char *, int, const char *,...)
Definition driver.cpp:1613
_TEST_EXPORT int rw_warn(int, const char *, int, const char *,...)
Definition driver.cpp:1647
#define bool
Definition stdbool.h:24
virtual ~Base()
T foo() const