You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@stdcxx.apache.org by se...@apache.org on 2006/05/23 00:56:12 UTC
svn commit: r408779 - /incubator/stdcxx/trunk/tests/support/18.exception.cpp
Author: sebor
Date: Mon May 22 15:56:12 2006
New Revision: 408779
URL: http://svn.apache.org/viewvc?rev=408779&view=rev
Log:
2006-05-22 Martin Sebor <se...@roguewave.com>
STDCXX-4
* 18.exception.cpp: Converted to new test driver.
Added:
incubator/stdcxx/trunk/tests/support/18.exception.cpp (with props)
Added: incubator/stdcxx/trunk/tests/support/18.exception.cpp
URL: http://svn.apache.org/viewvc/incubator/stdcxx/trunk/tests/support/18.exception.cpp?rev=408779&view=auto
==============================================================================
--- incubator/stdcxx/trunk/tests/support/18.exception.cpp (added)
+++ incubator/stdcxx/trunk/tests/support/18.exception.cpp Mon May 22 15:56:12 2006
@@ -0,0 +1,1030 @@
+/***************************************************************************
+ *
+ * exception.cpp - test exercising [lib.support.exception]
+ *
+ * $Id$
+ *
+ ***************************************************************************
+ *
+ * Copyright 2006 The Apache Software Foundation or its licensors,
+ * as applicable.
+ *
+ * Copyright 2001-2006 Rogue Wave Software.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ **************************************************************************/
+
+#ifdef __SUNPRO_CC
+ // working around a SunPro/SunOS 5.8 bug (PR #26255)
+# include <time.h>
+#endif // __SUNPRO_CC
+
+#include <exception> // for bad_exception, exception
+#include <ios> // for ios_base::failure
+#include <new> // for bad_alloc
+#include <stdexcept> // for exception classes
+#include <typeinfo> // for bad_cast, bad_typeid
+
+#include <csetjmp> // for jmp_buf, longjmp(), setjmp()
+#include <csignal> // for signal(), SIGABRT
+#include <cstdio> // for sprintf()
+#include <cstring> // for strcmp(), strlen()
+
+#include <rw/_error.h> // for _RWSTD_ERROR_XXX constants
+
+
+#ifndef _RWSTD_NO_SETRLIMIT
+# include <sys/resource.h> // for setrlimit()
+#endif // _RWSTD_NO_SETRLIMIT
+
+#include <driver.h>
+
+/**************************************************************************/
+
+// check header <exception> synopsis
+void test_synopsis ()
+{
+ // verify that classes are declared
+ std::exception *pex = (std::exception*)0;
+
+ // verify that bad_exception publicly derives from exception
+ pex = (std::bad_exception*)0;
+ _RWSTD_UNUSED (pex);
+
+ // check handler types
+ void (*phandler)() = (std::unexpected_handler)0;
+ phandler = (std::terminate_handler)0;
+
+ // check unexpected and terminate
+ phandler = &std::unexpected;
+ phandler = &std::terminate;
+ _RWSTD_UNUSED (phandler);
+
+ // check set_{unexpected,terminate}
+ std::unexpected_handler (*pset)(std::unexpected_handler) _PTR_THROWS (());
+
+ pset = &std::set_unexpected;
+ pset = &std::set_terminate;
+ _RWSTD_UNUSED (pset);
+
+ // check uncaught_exception()
+ // see http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/lwg-defects.html#70
+ // for exception specification details
+ bool (*pue)() _PTR_THROWS (()) = &std::uncaught_exception;
+ _RWSTD_UNUSED (pue);
+}
+
+/**************************************************************************/
+
+
+// defined at global scope rather than as locals
+// to work around an MSVC 6.0 bug (see PR #26305)
+static bool dtor_virtual = false;
+static bool what_virtual = false;
+
+// check the signatures of class exception and bad_exception members
+void test_signatures ()
+{
+// verify that a member function is accessible and has the appropriate
+// signature, including return type and exception specification
+#define MEMFUN(result, T, name, arg_list) do { \
+ result (T::*pf) arg_list _PTR_THROWS (()) = &T::name; \
+ _RWSTD_UNUSED (pf); \
+ } while (0)
+
+ rw_info (0, 0, __LINE__, "std::exception member function signatures");
+
+ // verify 18.6.1 [lib.exception]
+
+ // verify that a public default and copy ctors exist
+ std::exception e1;
+ std::exception e2 (e1);
+
+ MEMFUN (std::exception&, std::exception, operator=,
+ (const std::exception&));
+ MEMFUN (const char*, std::exception, what, () const);
+
+ struct test_exception_virtuals: std::exception {
+
+ ~test_exception_virtuals () _THROWS (()) {
+ dtor_virtual = true;
+ }
+ const char* what () const _THROWS (()) {
+ what_virtual = true;
+
+ // working around an MSVC 6.0 bug (PR #26330)
+ typedef std::exception Base;
+ return Base::what ();
+ }
+ };
+
+ std::exception *pe = new test_exception_virtuals;
+
+ // verify that destructor and what() are virtual
+ pe->what ();
+ rw_assert (what_virtual, 0, __LINE__,
+ "std::exception::what() not virtual");
+
+ delete pe;
+ rw_assert (dtor_virtual, 0, __LINE__,
+ "std::exception::~exception() not virtual");
+
+
+ rw_info (0, 0, __LINE__, "std::bad_exception member function signatures");
+
+ // verify 18.6.2.1 [lib.bad.exception]
+ // verify that a public default and copy ctors exist
+ std::bad_exception be1;
+ std::bad_exception be2 (be1);
+
+ MEMFUN (std::bad_exception&, std::bad_exception, operator=,
+ (const std::bad_exception&));
+ MEMFUN (const char*, std::bad_exception, what, () const);
+
+ dtor_virtual = false;
+ what_virtual = false;
+
+ struct test_bad_exception_virtuals: std::bad_exception {
+
+ ~test_bad_exception_virtuals () _THROWS (()) {
+ dtor_virtual = true;
+ }
+ const char* what () const _THROWS (()) {
+ what_virtual = true;
+
+ // working around an MSVC 6.0 bug (PR #26330)
+ typedef std::bad_exception Base;
+ return Base::what ();
+ }
+ };
+
+ pe = new test_bad_exception_virtuals;
+
+ // verify that destructor and what() are virtual
+ pe->what ();
+ rw_assert (what_virtual, 0, __LINE__,
+ "std::bad_exception::what() not virtual");
+
+ delete pe;
+ rw_assert (dtor_virtual, 0, __LINE__,
+ "std::bad_exception::~bad_exception() not virtual");
+}
+
+/**************************************************************************/
+
+// test globals (to make the accessible in signal and other handlers)
+std::unexpected_handler puh; // previous unexpected_handler
+std::terminate_handler pth; // previous terminate_handler
+int expect_abort; // SIGABRT expected if 1
+int expect_terminate; // terminate expected if 1
+int expect_unexpected; // unexpected expected if 1
+int expect_throw_proc; // throw_proc expected if 1
+std::jmp_buf env;
+
+/**************************************************************************/
+
+// called in response to abort() (called from std::terminate())
+extern "C" {
+
+static void
+SIGABRT_handler (int signo)
+{
+ rw_assert (1 == expect_abort && SIGABRT == signo, 0, __LINE__,
+ "SIGABRT unexpected");
+
+ // reestablish handler
+ std::signal (SIGABRT, SIGABRT_handler);
+
+ expect_abort = -1;
+
+ std::longjmp (env, 1);
+}
+
+} // extern "C"
+
+/**************************************************************************/
+
+static void
+test_terminate_handler ()
+{
+ rw_assert (1 == expect_terminate, 0, __LINE__,
+ "std::terminate() unexpected");
+
+ expect_terminate = -1;
+
+ // establish a handler for SIGABRT (raised from abort())
+ std::signal (SIGABRT, SIGABRT_handler);
+
+ // invoke default terminate handler
+ pth ();
+
+ // shouldn't be reached
+ rw_assert (false, 0, __LINE__,
+ "std::terminate() not called or returned");
+
+ std::longjmp (env, -1);
+}
+
+/**************************************************************************/
+
+static void
+test_unexpected_handler ()
+{
+ rw_assert (1 == expect_unexpected, 0, __LINE__,
+ "std::unexpected() unexpected");
+
+ expect_unexpected = -1;
+
+ // establish a handler for SIGABRT (raised from abort())
+ std::signal (SIGABRT, SIGABRT_handler);
+
+ expect_abort = 1;
+ expect_terminate = 1;
+
+ // throw an exception outside of any try block
+ // useless conditional used to prevent warnings
+ if (expect_abort)
+ throw 1;
+
+ // shouldn't be reached
+ rw_assert (false, 0, __LINE__,
+ "std::terminate() not called or returned");
+
+ std::longjmp (env, -1);
+}
+
+/**************************************************************************/
+
+// test the effects of 18.6
+static void
+test_effects ()
+{
+ // verify 18.6.1, p8: whhat() returns an implementation-defined NTBS
+ std::exception e1;
+ const char *what = e1.what ();
+ rw_assert (what && 1 <= 1 + std::strlen (what), 0, __LINE__,
+ "std::exception::what() != 0");
+
+ std::exception e2 (e1);
+ what = e2.what ();
+ rw_assert (what && 1 <= 1 + std::strlen (what), 0, __LINE__,
+ "std::exception::what() != 0");
+
+ // verify 18.6.2.1, p5: what() returns an implementation-defined NTBS
+ std::bad_exception e3;
+ what = e3.what ();
+ rw_assert (what && 1 <= 1 + std::strlen (what), 0, __LINE__,
+ "std::bad_exception::what() != 0");
+
+ std::exception e4 (e3);
+ what = e4.what ();
+ rw_assert (what && 1 <= 1 + std::strlen (what), 0, __LINE__,
+ "std::bad_exception::what()");
+
+#if !defined (_RWSTD_NO_EXCEPTIONS) \
+ && !defined (_RWSTD_NO_EXCEPTION_SPECIFICATION)
+
+ struct S {
+ static void foo () throw (double) {
+ throw 1;
+ }
+ };
+
+ rw_info (0, 0, __LINE__, "std::set_unexpected()");
+ rw_info (0, 0, __LINE__, "std::set_terminate()");
+
+ // determine the address of the default
+ // handlers and replace them with our own
+ puh = std::set_unexpected (test_unexpected_handler);
+ pth = std::set_terminate (test_terminate_handler);
+
+ // invoke a function that throws an exception
+ // that is not in its exception specification
+ expect_unexpected = 1;
+
+ try {
+ S::foo ();
+ }
+ catch (...) {
+ rw_assert (0, 0, __LINE__, "incompatible exception propagated");
+ }
+
+ std::longjmp (env, -1);
+
+#else
+
+ // prevent failures due to functionality not implemented in compiler
+ expect_abort = -1;
+ expect_terminate = -1;
+ expect_unexpected = -1;
+
+#endif // _RWSTD_NO_EXCEPTIONS && ...
+}
+
+/**************************************************************************/
+
+struct UncaughtExceptionCheck {
+ bool *presult_;
+
+ ~UncaughtExceptionCheck () {
+ *presult_ = std::uncaught_exception ();
+ }
+};
+
+static void
+test_uncaught_exception ()
+{
+ rw_info (0, 0, __LINE__, "std::uncaught_exception()");
+
+ bool expect;
+ bool uncaught = std::uncaught_exception ();
+
+#if !defined (_RWSTD_NO_STD_UNCAUGHT_EXCEPTION) \
+ || !defined (_RWSTD_NO_GLOBAL_UNCAUGHT_EXCEPTION)
+
+ expect = false;
+
+#else
+
+# ifndef _RWSTD_NO_EXCEPTIONS
+
+ expect = true;
+
+# else // if defined (_RWSTD_NO_EXCEPTIONS)
+
+ expect = false;
+
+# endif // _RWSTD_NO_EXCEPTIONS)
+
+#endif
+
+ rw_assert (uncaught == expect, 0, __LINE__,
+ "std::uncaught_exception() == %d, got %d", expect, uncaught);
+
+#ifndef _RWSTD_NO_EXCEPTIONS
+
+ expect = true;
+
+ try {
+ UncaughtExceptionCheck chk;
+
+ chk.presult_ = &uncaught;
+
+ throw 0;
+ }
+ catch (...) {
+ }
+
+#else // if defined (_RWSTD_NO_EXCEPTIONS)
+
+ expect = false;
+
+ {
+ UncaughtExceptionCheck chk;
+
+ chk.presult_ = &uncaught;
+ }
+
+#endif // _RWSTD_NO_EXCEPTIONS
+
+ rw_assert (uncaught == expect, 0, __LINE__,
+ "std::uncaught_exception() == %d, got %d", expect, uncaught);
+}
+
+/**************************************************************************/
+
+// original throw proc
+void (*const pthrow_proc_save)(int, char*) = _RW::__rw_throw_proc;
+
+// replaces the original throw proc
+static void
+test_throw_proc (int id, char *s)
+{
+ rw_assert (id == expect_throw_proc, 0, __LINE__,
+ "throw_proc expected %d, got %d (\"%s\")",
+ expect_throw_proc, id, s);
+
+ // do not delete[] s if returning to the lib
+ // must delete only if rethrowing or jumping from here
+ _RWSTD_UNUSED (s);
+
+ // signal that we were successfully called and with what value
+ expect_throw_proc = -id;
+}
+
+/**************************************************************************/
+
+// exercise __rw::__rw_throw() and __rw::__rw_throw_proc()
+static void
+test_rwthrow ()
+{
+#ifndef _RWSTD_NO_EXCEPTIONS
+
+ rw_info (0, 0, __LINE__, "__rw::__rw_throw()");
+
+ // exception format strings
+ static const char* strings[] = { _RWSTD_ERROR_STRINGS };
+
+ // exception id's: strings [i + 1] corresponds to expect [i]
+ static const int expect[] = {
+ _RWSTD_ERROR_FIRST + 1, // _RWSTD_ERROR_EXCEPTION
+ _RWSTD_ERROR_FIRST + 2, // _RWSTD_ERROR_BAD_EXCEPTION
+ _RWSTD_ERROR_FIRST + 3, // _RWSTD_ERROR_BAD_ALLOC
+ _RWSTD_ERROR_FIRST + 4, // _RWSTD_ERROR_BAD_CAST
+ _RWSTD_ERROR_LOGIC_ERROR,
+ _RWSTD_ERROR_DOMAIN_ERROR,
+ _RWSTD_ERROR_INVALID_ARGUMENT,
+ _RWSTD_ERROR_LENGTH_ERROR,
+ _RWSTD_ERROR_OUT_OF_RANGE,
+ _RWSTD_ERROR_RUNTIME_ERROR,
+ _RWSTD_ERROR_RANGE_ERROR,
+ _RWSTD_ERROR_OVERFLOW_ERROR,
+ _RWSTD_ERROR_UNDERFLOW_ERROR,
+
+ _RWSTD_ERROR_FAILBIT_SET,
+ _RWSTD_ERROR_BADBIT_SET,
+ _RWSTD_ERROR_EOFBIT_SET,
+ _RWSTD_ERROR_IOSTATE_BIT_SET
+ };
+
+ const char* const ex_names[] = {
+ "std::exception",
+ "std::bad_exception",
+ "std::bad_alloc",
+ "std::bad_cast",
+ "std::logic_error",
+ "std::domain_error",
+ "std::invalid_argument",
+ "std::length_error",
+ "std::out_of_range",
+ "std::runtime_error",
+ "std::range_error",
+ "std::overflow_error",
+ "std::underflow_error",
+
+ "std::ios_base::failbit_set",
+ "std::ios_base::badbit_set",
+ "std::ios_base::eofbit_set",
+ "std::ios_base::failure"
+ };
+
+ const char empty[] = "";
+
+ // raise each exception by its id, check that
+ // an exception object of the correct type is thrown
+ for (unsigned i = 0; i != sizeof expect / sizeof *expect; ++i) {
+
+ rw_info (0, 0, __LINE__, "%s", ex_names [i]);
+
+ int caught = -1;
+
+ // set up a new throw proc (prevent exceptions)
+ _RW::__rw_throw_proc = test_throw_proc;
+
+ // no exception should be thrown at this point
+ expect_throw_proc = expect [i];
+
+ const char format[] = _RWSTD_FILE_LINE;
+ const char func[] = "void test_rwthrow (Test&)";
+
+ _RW::__rw_throw (expect [i], format, func, empty, empty, empty);
+
+ rw_assert (expect [i] == -expect_throw_proc, 0, __LINE__,
+ "%d. throw_proc (%d, ...) not called", i, expect [i]);
+
+ try {
+ // reestablish original throw proc
+ _RW::__rw_throw_proc = pthrow_proc_save;
+
+ // expect an exception
+ _RW::__rw_throw (expect [i], format, func, empty, empty, empty);
+
+ rw_assert (false, 0, __LINE__,
+ "%d. __rw::__rw_throw(%d, ...) returned",
+ i, expect [i]);
+ }
+ catch (std::domain_error &ex) {
+ rw_assert (!!ex.what (), 0, __LINE__,
+ "domain_error::what() != 0");
+ caught = _RWSTD_ERROR_DOMAIN_ERROR;
+ }
+ catch (std::invalid_argument &ex) {
+ rw_assert (!!ex.what (), 0, __LINE__,
+ "invalid_argument::what() != 0");
+ caught = _RWSTD_ERROR_INVALID_ARGUMENT;
+ }
+ catch (std::length_error &ex) {
+ rw_assert (!!ex.what (), 0, __LINE__,
+ "length_error::what() != 0");
+ caught = _RWSTD_ERROR_LENGTH_ERROR;
+ }
+ catch (std::out_of_range &ex) {
+ rw_assert (!!ex.what (), 0, __LINE__,
+ "out_of_range::what() != 0");
+ caught = _RWSTD_ERROR_OUT_OF_RANGE;
+ }
+ catch (std::range_error &ex) {
+ rw_assert (!!ex.what (), 0, __LINE__,
+ "range_error::what() != 0");
+ caught = _RWSTD_ERROR_RANGE_ERROR;
+ }
+ catch (std::overflow_error &ex) {
+ rw_assert (!!ex.what (), 0, __LINE__,
+ "overflow_error::what() != 0");
+ caught = _RWSTD_ERROR_OVERFLOW_ERROR;
+ }
+ catch (std::underflow_error &ex) {
+ rw_assert (!!ex.what (), 0, __LINE__,
+ "underflow_error::what() != 0");
+ caught = _RWSTD_ERROR_UNDERFLOW_ERROR;
+ }
+ catch (std::logic_error &ex) {
+ rw_assert (!!ex.what (), 0, __LINE__,
+ "logic_error::what() != 0");
+ caught = _RWSTD_ERROR_LOGIC_ERROR;
+ }
+ catch (std::runtime_error &ex) {
+ rw_assert (!!ex.what (), 0, __LINE__,
+ "runtime_error::what() != 0");
+ caught = _RWSTD_ERROR_RUNTIME_ERROR;
+ }
+ catch (std::bad_alloc &ex) {
+ rw_assert (!!ex.what (), 0, __LINE__,
+ "bad_alloc::what() != 0");
+ caught = _RWSTD_ERROR_FIRST + 3; // _RWSTD_BAD_ALLOC
+ }
+ catch (std::bad_exception &ex) {
+ rw_assert (!!ex.what (), 0, __LINE__,
+ "bad_exception::what() != 0");
+ caught = _RWSTD_ERROR_FIRST + 2; // _RWSTD_ERROR_BAD_EXCEPTION
+ }
+ catch (std::bad_cast &ex) {
+ rw_assert (!!ex.what (), 0, __LINE__,
+ "bad_cast::what() != 0");
+ caught = _RWSTD_ERROR_FIRST + 4; // _RWSTD_ERROR_BAD_CAST;
+ }
+
+#ifdef _RWSTD_ERROR_BAD_TYPEID
+
+ catch (std::bad_typeid &ex) {
+ rw_assert (!!ex.what (), 0, __LINE__,
+ "bad_typeid::what() != 0");
+ caught = _RWSTD_ERROR_BAD_TYPEID;
+ }
+
+#endif // _RWSTD_ERROR_BAD_TYPEID;
+
+#ifndef _RWSTD_NO_EXT_FAILURE
+
+ catch (std::ios_base::failbit_set &ex) {
+ rw_assert (!!ex.what (), 0, __LINE__,
+ "ios_base::failbit_set::what() != 0");
+ caught = _RWSTD_ERROR_FAILBIT_SET;
+ }
+ catch (std::ios_base::badbit_set &ex) {
+ rw_assert (!!ex.what (), 0, __LINE__,
+ "ios_base::badbit_set::what() != 0");
+ caught = _RWSTD_ERROR_BADBIT_SET;
+ }
+ catch (std::ios_base::eofbit_set &ex) {
+ rw_assert (!!ex.what (), 0, __LINE__,
+ "ios_base::eofbit_set::what() != 0");
+ caught = _RWSTD_ERROR_EOFBIT_SET;
+ }
+
+#endif // _RWSTD_NO_EXT_FAILURE
+
+ catch (std::ios_base::failure &ex) {
+ rw_assert (!!ex.what (), 0, __LINE__,
+ "ios_base::failure::what() != 0");
+ caught = _RWSTD_ERROR_IOSTATE_BIT_SET;
+ }
+ catch (std::exception &ex) {
+ rw_assert (!!ex.what (), 0, __LINE__,
+ "exception::what() != 0");
+ caught = _RWSTD_ERROR_FIRST + 1; // _RWSTD_ERROR_EXCEPTION
+ }
+ catch (...) {
+ caught = -1;
+ }
+
+ rw_assert (expect [i] == caught, 0, __LINE__,
+ "%d. expected %d, caught %d", i, expect [i], caught);
+ }
+
+
+ // reestablish original throw proc
+ _RW::__rw_throw_proc = pthrow_proc_save;
+
+ char str [1024];
+ char result [2 * sizeof str];
+
+ rw_info (0, 0, __LINE__,
+ "exercising throwing standard exception objects "
+ "constructed with string arguments up to %zu "
+ "characters long (not including context info)",
+ sizeof str);
+
+ // exercise the ability or __rw_throw() to correctly format
+ // strings of arbitrary length, also verify that format string
+ // macros are used to format the what() strings as expected
+ for (unsigned j = 0; j != sizeof str - 1; ++j) {
+
+ // exclude exception, bad_alloc, bad_cast, and bad_exception
+ // they are typically generated by the compiler and their
+ // what() strings are implementation-specific
+ unsigned en = j % ((sizeof expect / sizeof *expect) - 5);
+
+ // null-terminate str
+ str [j] = '\0';
+
+ std::sprintf (result, strings [en + 5], __FILE__, str,
+ empty, empty, empty);
+
+ try {
+ // expect an exception
+ _RW::__rw_throw (expect [en + 4], __FILE__, str,
+ empty, empty, empty);
+
+ rw_assert (false, 0, __LINE__,
+ "%d. __rw::__rw_throw (%d, ...) returned",
+ j, expect [en + 4]);
+ }
+ catch (std::exception &e) {
+ rw_assert (e.what () && 0 == std::strcmp (e.what (), result),
+ 0, __LINE__,
+ "%u. \"%s\" != \"%s\" [%u]",
+ j, e.what (), result, en + 3);
+ }
+
+ // append a decimal digit
+ str [j] = '0' + j % 10;
+ }
+
+#endif // _RWSTD_NO_EXCEPTIONS
+}
+
+/**************************************************************************/
+
+static void
+throwing_unexpected_handler ()
+{
+ // throw an exception that can't otherwise be possibly thrown
+ // to induce std::bad_exception to be rethrown by the langauage
+ // runtime library
+
+ struct PrivateStruct { };
+
+ // prevent assertions from the installed SIGABRT handler
+ // and terminate_handler in case they are invoked as a
+ // result of throwing the exception below
+ expect_terminate = 1;
+ expect_abort = 1;
+
+ throw PrivateStruct ();
+}
+
+/**************************************************************************/
+
+enum RuntimeExceptionId {
+ E_bad_alloc, E_bad_cast, E_bad_exception, E_bad_typeid, E_error
+};
+
+// induce the language runtime into throwing an exception
+// returns e if exception cannot bee thrown
+static RuntimeExceptionId
+induce_exception (RuntimeExceptionId reid, const char *name)
+{
+ const char *why = 0;
+
+ switch (reid) {
+
+ case E_bad_alloc: { ////////////////////////////////////////////
+
+#ifndef _RWSTD_NO_NEW_THROWS
+
+# ifndef _RWSTD_NO_SETRLIMIT
+
+# if !defined (__HP_aCC)
+
+ // work around an HP aCC 5.xx (IPF) bug (PR #29014)
+
+ // retrieve the current resource limits
+ struct rlimit rl = { 0, 0 };
+ if (getrlimit (RLIMIT_DATA, &rl))
+ return E_error;
+
+ // set the soft limit, leave hard limit unchanged
+ rl.rlim_cur = 0;
+ if (setrlimit (RLIMIT_DATA, &rl))
+ return E_error;
+
+ try {
+
+# endif // __HP_aCC
+# endif // _RWSTD_NO_SETRLIMIT
+
+ // try to allocate a huge amount of memory to induce bad_alloc
+ ::operator new (~0UL - 4096UL);
+
+# ifndef _RWSTD_NO_SETRLIMIT
+# if !defined (__HP_aCC)
+
+ }
+ catch (...) {
+
+ // reset the soft limit back to the value of the hard limit
+ rl.rlim_cur = rl.rlim_max;
+ setrlimit (RLIMIT_DATA, &rl);
+
+ // rethrow bad_alloc
+ throw;
+ }
+
+# endif // __HP_aCC
+
+ return E_error;
+
+# endif // _RWSTD_NO_SETRLIMIT
+
+#else // if defined (_RWSTD_NO_NEW_THROWS)
+
+ why = "_RWSTD_NO_NEW_THROWS is #defined";
+
+ break; // unable to induce bad_alloc
+
+#endif // NO_NEW_THROWS
+
+ }
+
+ case E_bad_cast: { /////////////////////////////////////////////
+
+#ifndef _RWSTD_NO_DYNAMIC_CAST
+
+ struct A { virtual ~A () { } };
+ struct B: A { } b;
+ struct C: A { };
+
+ A &a = b;
+
+ // induce bad_cast
+ dynamic_cast<C&>(a);
+
+ return E_error;
+
+#else // if defined (_RWSTD_NO_DYNAMIC_CAST)
+
+ why = "_RWSTD_NO_DYNAMIC_CAST is #defined";
+
+ break; // unable to induce bad_cast
+
+#endif // _RWSTD_NO_DYNAMIC_CAST
+ }
+
+ case E_bad_exception: { ////////////////////////////////////////
+
+#ifndef _RWSTD_NO_EXCEPTION_SPECIFICATION
+
+ std::set_unexpected (throwing_unexpected_handler);
+
+ struct S {
+ // induce bad_exception
+ S () throw (std::bad_exception) { throw 0; }
+ } s;
+
+ _RWSTD_UNUSED (s);
+ return E_error;
+
+#else // if defined (_RWSTD_NO_EXCEPTION_SPECIFICATION)
+
+ why = "_RWSTD_NO_EXCEPTION_SPECIFICATION is #defined";
+
+ break; // unable to induce bad_exception
+
+#endif // _RWSTD_NO_EXCEPTION_SPECIFICATION
+
+ }
+
+ case E_bad_typeid: { ///////////////////////////////////////////
+
+#if !defined (_RWSTD_NO_GLOBAL_BAD_TYPEID) \
+ || !defined (_RWSTD_NO_STD_BAD_TYPEID)
+
+ struct S { virtual ~S () { } } *s = 0;
+
+ // induce bad_typeid
+ typeid (*s);
+
+ return E_error;
+
+#else // if _RWSTD_NO_GLOBAL_BAD_TYPEID && _RWSTD_NO_STD_BAD_TYPEID
+
+ why = "both _RWSTD_NO_GLOBAL_BAD_TYPEID and _RWSTD_NO_STD_BAD_TYPEID "
+ "are #defined";
+
+ break; // unable to induce bad_typeid
+
+#endif // NO_BAD_TYPEID
+
+ }
+
+ default:
+ break;
+ }
+
+ rw_warn (0, 0, __LINE__, "unable to induce std::%s: %s\n", name, why);
+
+ return reid;
+}
+
+/**************************************************************************/
+
+static const RuntimeExceptionId
+rt_exceptions[] = {
+ E_bad_alloc, E_bad_cast, E_bad_exception, E_bad_typeid,
+ E_error
+};
+
+static const char* const
+rt_exception_names[] = {
+ "bad_alloc", "bad_cast", "bad_exception", "bad_typeid"
+};
+
+static int
+opt_no_rt_exception [E_error];
+
+
+static void
+test_runtime ()
+{
+#ifndef _RWSTD_NO_EXCEPTIONS
+
+ rw_info (0, 0, __LINE__, "runtime support for exceptions");
+
+
+ // using static to avoid gcc 3.x warning: variable
+ // might be clobbered by `longjmp' or `vfork'
+
+ for (static unsigned i = 0; E_error != rt_exceptions [i]; ++i) {
+
+ const RuntimeExceptionId ex_id = rt_exceptions [i];
+ const char* const ex_name = rt_exception_names [i];
+
+ rw_info (0, 0, __LINE__, "std::%s", ex_name);
+
+ if (0 == rw_note (0 == opt_no_rt_exception [i],
+ 0, __LINE__,
+ "std::%s test disabled", ex_name))
+ continue;
+
+ static int ex0;
+ static int ex1;
+
+ ex0 = ex1 = 0;
+
+ try {
+ try {
+ // jump back here if the induced exception causes
+ // a call to terminate() and/or raises SIGABRT
+ if (0 == setjmp (env)) {
+
+ // try to induce the standard exception
+ if (ex_id == induce_exception (ex_id, ex_name)) {
+ ex0 = -1;
+ ex1 = -1;
+ }
+ }
+ else {
+ rw_assert (false, 0, __LINE__,
+ "inducing std::%s caused a call "
+ "to std::terminate()", ex_name);
+ // prevent additional assertions
+ ex0 = -1;
+ }
+ }
+ catch (std::exception&) {
+ // so far so good, rethrow and try to catch again
+ ex0 = 0;
+ throw;
+ }
+ catch (...) {
+ // failure to catch a standard exception using std::exception
+ // most likely indication of class exception having been
+ // defined in a different namespace by the C++ Standard
+ // library than by the language support library (compiler
+ // runtime)
+ ex0 = -2;
+ throw;
+ }
+ }
+ catch (std::bad_alloc&) { ex1 = E_bad_alloc; }
+ catch (std::bad_cast&) { ex1 = E_bad_cast; }
+ catch (std::bad_exception&) { ex1 = E_bad_exception; }
+ catch (std::bad_typeid&) { ex1 = E_bad_typeid; }
+ catch (...) { ex1 = -2; }
+
+ rw_assert (-1 == ex0 || 0 == ex0, 0, __LINE__,
+ "std::%s thrown, std::exception not caught",
+ ex_name);
+
+ rw_assert (-1 == ex1 || rt_exceptions [i] == ex1, 0, __LINE__,
+ "std::%s thrown, unknown exception caught",
+ ex_name);
+ }
+
+#endif // _RWSTD_NO_EXCEPTIONS
+}
+
+/**************************************************************************/
+
+static int opt_no_synopsis; // for --no-synopis
+static int opt_no_signatures; // for --no-signatures
+static int opt_no_uncaught; // for --no-uncaught_exception
+static int opt_no_effects; // for --no-effects
+static int opt_no_rw_throw; // for --no-rw_throw
+static int opt_no_runtime; // for --no-runtime
+
+static int
+run_test (int, char**)
+{
+ // check header <exception> synopsis
+ rw_info (0, 0, __LINE__, "header <exception> synopsis");
+
+ test_synopsis ();
+
+ // check the signatures of class exception and bad_exception members
+ test_signatures ();
+
+ // exercise std::uncaught_exception() before running any other tests
+ // since some of them might affect the correct behavior of the function
+ // (if they violate such constraints as returning from a call to
+ // std::terminate())
+ test_uncaught_exception ();
+
+ if (0 == setjmp (env)) {
+ // test the effects of 18.6
+ test_effects ();
+ }
+
+ // verify that test worked as expected (each handler sets
+ // its own expect_xxx variable to -1 after it's been called)
+ rw_error (-1 == expect_abort, 0, __LINE__,
+ "abort() was called unexpectedly");
+
+ rw_error (-1 == expect_terminate, 0, __LINE__,
+ "terminate() was called unexpectedly");
+
+ rw_error (-1 == expect_unexpected, 0, __LINE__,
+ "unexpected() was called unexpectedly");
+
+ // exercise __rw::__rw_throw() and __rw::__rw_throw_proc()
+ test_rwthrow ();
+
+ // exercise the cooperation between the C++ standard library and
+ // the runtime support library when throwing standard exceptions
+ test_runtime ();
+
+ return 0;
+}
+
+/**************************************************************************/
+
+int main (int argc, char *argv[])
+{
+ return rw_test (argc, argv, __FILE__,
+ "lib.support.exception",
+ 0 /* no comment */,
+ run_test,
+ "|-no-synopis# "
+ "|-no-signatures# "
+ "|-no-uncaught_exception# "
+ "|-no-effects# "
+ "|-no-rw_throw# "
+ "|-no-runtime# "
+ "|-no-bad_alloc# "
+ "|-no-bad_cast# "
+ "|-bad_exception# "
+ "|-bad_typeid#",
+ &opt_no_synopsis,
+ &opt_no_signatures,
+ &opt_no_uncaught,
+ &opt_no_effects,
+ &opt_no_rw_throw,
+ &opt_no_runtime,
+ opt_no_rt_exception + E_bad_alloc,
+ opt_no_rt_exception + E_bad_cast,
+ opt_no_rt_exception + E_bad_exception,
+ opt_no_rt_exception + E_bad_typeid,
+ 0 /* sentinel */);
+}
Propchange: incubator/stdcxx/trunk/tests/support/18.exception.cpp
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: incubator/stdcxx/trunk/tests/support/18.exception.cpp
------------------------------------------------------------------------------
svn:keywords = Id