first commit
This commit is contained in:
155
extern/stdcxx/4.2.1/tests/diagnostics/19.cerrno.cpp
vendored
Normal file
155
extern/stdcxx/4.2.1/tests/diagnostics/19.cerrno.cpp
vendored
Normal file
@@ -0,0 +1,155 @@
|
||||
/***************************************************************************
|
||||
*
|
||||
* 19.cerrno.cpp - test exercising the lib.errno
|
||||
*
|
||||
* $Id: 19.cerrno.cpp 550991 2007-06-26 23:58:07Z sebor $
|
||||
*
|
||||
***************************************************************************
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed
|
||||
* with this work for additional information regarding copyright
|
||||
* ownership. The ASF licenses this file to you 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.
|
||||
*
|
||||
* Copyright 1994-2006 Rogue Wave Software.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
// include only <cerrno> here to prevent namespace pollution
|
||||
#include <cerrno>
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
const char* const errors[] = {
|
||||
|
||||
#ifndef errno
|
||||
"errno",
|
||||
#endif // errno
|
||||
|
||||
#ifndef EDOM
|
||||
"EDOM not defined",
|
||||
#elif EDOM <= 0
|
||||
"EDOM not positive",
|
||||
#endif // EDOM
|
||||
|
||||
#ifndef EILSEQ
|
||||
"EILSEQ", // lwg issue 288
|
||||
#elif EILSEQ <= 0
|
||||
"EILSEQ not positive",
|
||||
#elif EILSEQ == EDOM
|
||||
"EILSEQ not distinct from EDOM",
|
||||
#endif // EILSEQ
|
||||
|
||||
#ifndef ERANGE
|
||||
"ERANGE not defined",
|
||||
#elif ERANGE <= 0
|
||||
"ERANGE not positive",
|
||||
#elif ERANGE == EDOM
|
||||
"ERANGE not distinct from EDOM",
|
||||
#elif ERANGE == EILSEQ
|
||||
"ERANGE not distinct from EILSEQ",
|
||||
#endif // ERANGE
|
||||
|
||||
0
|
||||
};
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
// include all other headers here
|
||||
#include <any.h> // for rw_any_t
|
||||
#include <driver.h> // for rw_test(), ...
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
template <class T> void set_errno_value (T, int) { /* empty */ }
|
||||
void set_errno_value (int &errno_ref, int val) { errno_ref = val; }
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
static int
|
||||
errno_at_startup;
|
||||
|
||||
static int
|
||||
run_test (int, char**)
|
||||
{
|
||||
rw_info (0, 0, 0, "exercising the contents of the <cerrno> header");
|
||||
|
||||
for (unsigned i = 0; errors [i]; ++i) {
|
||||
rw_assert (0 == errors [i], 0, 0,
|
||||
"macro %s", errors [i]);
|
||||
}
|
||||
|
||||
// get the type of errno
|
||||
const char* const errno_type = rw_any_t (errno).type_name ();
|
||||
|
||||
// 7.5, p2 of C99: the type of errno must be int
|
||||
rw_assert ( 'i' == errno_type [0]
|
||||
&& 'n' == errno_type [1]
|
||||
&& 't' == errno_type [2]
|
||||
&& '\0' == errno_type [3],
|
||||
0, 0,
|
||||
"the type of errno is int, got %s", errno_type);
|
||||
|
||||
// 7.5, p3 of C99: errno must be 0 at program startup
|
||||
rw_assert (0 == errno_at_startup, 0, 0,
|
||||
"errno == 0 at program startup, got %d", errno_at_startup);
|
||||
|
||||
#ifndef EDOM
|
||||
# define EDOM 33 /* Solaris value */
|
||||
#endif // EDOM
|
||||
|
||||
// 7.5, p2 of C99: errno must be a modifiable lvalue
|
||||
set_errno_value (errno, int (EDOM));
|
||||
|
||||
rw_assert (EDOM == errno, 0, 0,
|
||||
"errno == %d (%{#*m}, got %d (%{#m}) "
|
||||
"(errno not a modifiable lvalue?)",
|
||||
EDOM, EDOM, errno, errno);
|
||||
|
||||
#ifndef ERANGE
|
||||
# define ERANGE 34 /* Solaris value */
|
||||
#endif // ERANGE
|
||||
|
||||
set_errno_value (errno, int (ERANGE));
|
||||
|
||||
rw_assert (ERANGE == errno, 0, 0,
|
||||
"errno == %d (%{#*m}, got %d (%{#m}) "
|
||||
"(errno not a modifiable lvalue?)",
|
||||
ERANGE, ERANGE, errno, errno);
|
||||
|
||||
#ifndef EILSEQ
|
||||
# define EILSEQ 84 /* Solaris value */
|
||||
#endif // EILSEQ
|
||||
|
||||
set_errno_value (errno, int (EILSEQ));
|
||||
|
||||
rw_assert (EILSEQ == errno, 0, 0,
|
||||
"errno == %d (%{#*m}, got %d (%{#m}) "
|
||||
"(errno not a modifiable lvalue?)",
|
||||
EILSEQ, EILSEQ, errno, errno);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
errno_at_startup = errno;
|
||||
|
||||
return rw_test (argc, argv, __FILE__,
|
||||
"lib.errno",
|
||||
0 /* no comment */, run_test,
|
||||
0 /* no command line options */, 0);
|
||||
}
|
||||
362
extern/stdcxx/4.2.1/tests/diagnostics/19.exceptions.mt.cpp
vendored
Normal file
362
extern/stdcxx/4.2.1/tests/diagnostics/19.exceptions.mt.cpp
vendored
Normal file
@@ -0,0 +1,362 @@
|
||||
/***************************************************************************
|
||||
*
|
||||
* 19.exceptions.mt.cpp - test exercising the thread safety
|
||||
* of C++ Standard Library exception classes
|
||||
*
|
||||
* $Id: 19.exceptions.mt.cpp 425530 2006-07-25 21:39:50Z sebor $
|
||||
*
|
||||
***************************************************************************
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed
|
||||
* with this work for additional information regarding copyright
|
||||
* ownership. The ASF licenses this file to you 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.
|
||||
*
|
||||
* Copyright 2005-2006 Rogue Wave Software.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
#include <stdexcept> // for exceptions
|
||||
#include <string> // for string
|
||||
|
||||
#include <cassert> // for assert
|
||||
#include <cstdio> // for printf()
|
||||
|
||||
#include <cmdopt.h>
|
||||
#include <driver.h>
|
||||
#include <rw_alarm.h> // for rw_alarm()
|
||||
#include <rw_thread.h> // for rw_thread_pool()
|
||||
#include <valcmp.h>
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef NTHREADS
|
||||
# ifndef _RWSTD_REENTRANT
|
||||
# define MAX_THREADS 0
|
||||
# define NTHREADS 0
|
||||
# else
|
||||
# define MAX_THREADS 32
|
||||
# define NTHREADS 4
|
||||
# endif // _RWSTD_REENTRANT
|
||||
#endif // NTHREADS
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
/* extern */ int rw_opt_nloops = 256 * 1024;
|
||||
/* extern */ int rw_opt_nthreads = NTHREADS;
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
volatile int alarm_expired;
|
||||
|
||||
extern "C" {
|
||||
|
||||
static void handle_alarm (int)
|
||||
{
|
||||
alarm_expired = 1;
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
|
||||
// string to intialize exceptions from
|
||||
static const char what_buf [] = {
|
||||
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"0123456789ABCDEF"
|
||||
};
|
||||
|
||||
|
||||
enum {
|
||||
exception_tag,
|
||||
logic_error_tag,
|
||||
domain_error_tag,
|
||||
invalid_argument_tag,
|
||||
length_error_tag,
|
||||
out_of_range_tag,
|
||||
runtime_error_tag,
|
||||
range_error_tag,
|
||||
overflow_error_tag,
|
||||
underflow_error_tag,
|
||||
Derived_tag
|
||||
};
|
||||
|
||||
|
||||
struct DerivedException: std::invalid_argument
|
||||
{
|
||||
DerivedException (const char *str)
|
||||
: std::invalid_argument (str) { }
|
||||
};
|
||||
|
||||
|
||||
static void
|
||||
throw_exception (unsigned which, const char *what)
|
||||
{
|
||||
switch (which) {
|
||||
case exception_tag: throw std::exception ();
|
||||
case logic_error_tag: throw std::logic_error (what);
|
||||
case domain_error_tag: throw std::domain_error (what);
|
||||
case invalid_argument_tag: throw std::invalid_argument (what);
|
||||
case length_error_tag: throw std::length_error (what);
|
||||
case out_of_range_tag: throw std::out_of_range (what);
|
||||
case runtime_error_tag: throw std::runtime_error (what);
|
||||
case range_error_tag: throw std::range_error (what);
|
||||
case overflow_error_tag: throw std::overflow_error (what);
|
||||
case underflow_error_tag: throw std::underflow_error (what);
|
||||
case Derived_tag: throw DerivedException (what);
|
||||
|
||||
default: _RWSTD_ASSERT (!"logic error: bad exception tag");
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
extern "C" void*
|
||||
test_single_exception (void *arg)
|
||||
{
|
||||
const rw_thread_t* const tid = (rw_thread_t*)arg;
|
||||
|
||||
std::printf ("thread procedure %ld starting...\n", tid->threadno);
|
||||
|
||||
for (unsigned i = 0; i < unsigned (rw_opt_nloops); ++i) {
|
||||
|
||||
if (alarm_expired)
|
||||
break;
|
||||
|
||||
const std::size_t what_len = std::size_t (i % 1024);
|
||||
|
||||
const char* const what = what_buf + sizeof what_buf - what_len - 1;
|
||||
|
||||
const unsigned thrown = i % 11;
|
||||
|
||||
unsigned caught = _RWSTD_UINT_MAX;
|
||||
|
||||
try {
|
||||
// construct and throw an exception object of one
|
||||
// of the predefined standard exception classes
|
||||
// initialized with a distinct what string
|
||||
throw_exception (thrown, what);
|
||||
}
|
||||
catch (DerivedException ex) {
|
||||
// catch the exception object by value and verify
|
||||
// that the pointer returned by what() compares
|
||||
// equal to the string the thrown object was
|
||||
// constructed with
|
||||
caught = Derived_tag;
|
||||
assert (0 == rw_strncmp (ex.what (), what));
|
||||
}
|
||||
catch (std::domain_error ex) {
|
||||
caught = domain_error_tag;
|
||||
assert (0 == rw_strncmp (ex.what (), what));
|
||||
}
|
||||
catch (std::invalid_argument ex) {
|
||||
caught = invalid_argument_tag;
|
||||
assert (0 == rw_strncmp (ex.what (), what));
|
||||
}
|
||||
catch (std::length_error ex) {
|
||||
caught = length_error_tag;
|
||||
assert (0 == rw_strncmp (ex.what (), what));
|
||||
}
|
||||
catch (std::out_of_range ex) {
|
||||
caught = out_of_range_tag;
|
||||
assert (0 == rw_strncmp (ex.what (), what));
|
||||
}
|
||||
catch (std::range_error ex) {
|
||||
caught = range_error_tag;
|
||||
assert (0 == rw_strncmp (ex.what (), what));
|
||||
}
|
||||
catch (std::overflow_error ex) {
|
||||
caught = overflow_error_tag;
|
||||
assert (0 == rw_strncmp (ex.what (), what));
|
||||
}
|
||||
catch (std::underflow_error ex) {
|
||||
caught = underflow_error_tag;
|
||||
assert (0 == rw_strncmp (ex.what (), what));
|
||||
}
|
||||
catch (std::logic_error ex) {
|
||||
caught = logic_error_tag;
|
||||
assert (0 == rw_strncmp (ex.what (), what));
|
||||
}
|
||||
catch (std::runtime_error ex) {
|
||||
caught = runtime_error_tag;
|
||||
assert (0 == rw_strncmp (ex.what (), what));
|
||||
}
|
||||
catch (std::exception ex) {
|
||||
caught = exception_tag;
|
||||
rw_strncmp (ex.what (), what);
|
||||
}
|
||||
|
||||
// verify that an object of the thrown type was caught
|
||||
assert (caught == thrown);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
static void
|
||||
test_multi (unsigned i, unsigned nactive)
|
||||
{
|
||||
const std::size_t what_len = (i + nactive) % sizeof what_buf;
|
||||
|
||||
const char* const what = what_buf + sizeof what_buf - what_len - 1;
|
||||
|
||||
const unsigned thrown = (i + nactive) % 10 + 1;
|
||||
|
||||
try {
|
||||
// construct and throw an exception object of a distinct type
|
||||
// with a distinct what string at each level of recursion
|
||||
throw_exception (thrown, what);
|
||||
}
|
||||
catch (std::exception &ex) {
|
||||
|
||||
// recursively throw another exception while the caught
|
||||
// exception object is still active
|
||||
if (nactive)
|
||||
test_multi (i, nactive - 1);
|
||||
|
||||
// verify that the caught object's what string matches
|
||||
// the string the object was originally constructed with
|
||||
assert (0 == rw_strncmp (ex.what (), what));
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void*
|
||||
test_multi_exceptions (void *arg)
|
||||
{
|
||||
const rw_thread_t* const tid = (rw_thread_t*)arg;
|
||||
|
||||
std::printf ("thread procedure %ld starting...\n", tid->threadno);
|
||||
|
||||
for (unsigned i = 0; i < unsigned (rw_opt_nloops); ++i) {
|
||||
|
||||
if (alarm_expired)
|
||||
break;
|
||||
|
||||
// exercise up to 4 simultaneously active exceptions
|
||||
test_multi (i, i % 4);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
static int
|
||||
run_test (int, char**)
|
||||
{
|
||||
// get the current alarm (if any) set for the test
|
||||
// on the command line without resetting it
|
||||
const unsigned max_sec = rw_alarm (0, rw_sig_hold);
|
||||
|
||||
// compute a shorter timeout for each of the two subtests
|
||||
const unsigned nsec = 3 < max_sec ? max_sec / 2 : 0;
|
||||
|
||||
rw_info (0, 0, 0,
|
||||
"single active exception per thread"
|
||||
"%{?}; timeout in %u seconds%{;}",
|
||||
0 != max_sec, nsec ? nsec : max_sec);
|
||||
|
||||
// set a shorter alarm if possible
|
||||
if (nsec) {
|
||||
alarm_expired = 0;
|
||||
rw_alarm (nsec, handle_alarm);
|
||||
}
|
||||
|
||||
const std::size_t nthreads = std::size_t (rw_opt_nthreads);
|
||||
|
||||
#if 0 < NTHREADS
|
||||
|
||||
rw_fatal (0 == rw_thread_pool (0, nthreads, 0, test_single_exception, 0),
|
||||
0, __LINE__, "rw_thread_pool() failed");
|
||||
|
||||
#else // if !(0 < NTHREADS)
|
||||
|
||||
rw_thread_t tid = rw_thread_t ();
|
||||
|
||||
test_single_exception (&tid);
|
||||
|
||||
#endif // NTHREADS
|
||||
|
||||
rw_info (0, 0, 0,
|
||||
"multiple active exceptions per thread"
|
||||
"%{?}; timeout in %u seconds%{;}",
|
||||
0 != max_sec, nsec ? nsec : max_sec);
|
||||
|
||||
// set another shorter alarm if possible
|
||||
if (nsec) {
|
||||
alarm_expired = 0;
|
||||
rw_alarm (nsec, handle_alarm);
|
||||
}
|
||||
|
||||
#if 0 < NTHREADS
|
||||
|
||||
rw_fatal (0 == rw_thread_pool (0, nthreads, 0, test_multi_exceptions, 0),
|
||||
0, __LINE__, "rw_thread_pool() failed");
|
||||
|
||||
#else // if !(0 < NTHREADS)
|
||||
|
||||
test_multi_exceptions (&tid);
|
||||
|
||||
#endif // NTHREADS
|
||||
|
||||
// restore the original alarm to go off approximately
|
||||
// when the original alar would have if it hadn't been
|
||||
// replaced above
|
||||
if (nsec)
|
||||
rw_alarm (2 * nsec, rw_sig_restore);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
return rw_test (argc, argv, __FILE__,
|
||||
"lib.std.exceptions",
|
||||
"thread safety", run_test,
|
||||
"|-nloops#0 " // must be non-negative
|
||||
"|-nthreads#0-*", // must be in [0, MAX_THREADS]
|
||||
&rw_opt_nloops,
|
||||
int (MAX_THREADS),
|
||||
&rw_opt_nthreads);
|
||||
}
|
||||
475
extern/stdcxx/4.2.1/tests/diagnostics/19.std.exceptions.cpp
vendored
Normal file
475
extern/stdcxx/4.2.1/tests/diagnostics/19.std.exceptions.cpp
vendored
Normal file
@@ -0,0 +1,475 @@
|
||||
/***************************************************************************
|
||||
*
|
||||
* 19.std.exceptions.cpp - test exercising [lib.std.exceptions]
|
||||
*
|
||||
* $Id: 19.std.exceptions.cpp 648752 2008-04-16 17:01:56Z faridz $
|
||||
*
|
||||
***************************************************************************
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed
|
||||
* with this work for additional information regarding copyright
|
||||
* ownership. The ASF licenses this file to you 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.
|
||||
*
|
||||
* Copyright 2001-2008 Rogue Wave Software.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
template <class Exception>
|
||||
int test_ex_spec (Exception*, const char *str)
|
||||
{
|
||||
#ifndef _RWSTD_NO_EXCEPTIONS
|
||||
|
||||
try {
|
||||
// also tests that exception objects can be constructed
|
||||
// from a const char* argument w/o <string> having been
|
||||
// explicitly #included first
|
||||
Exception e (str);
|
||||
(void)&e;
|
||||
}
|
||||
catch (...) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
#else // if defined (_RWSTD_NO_EXCEPTIONS);
|
||||
|
||||
_RWSTD_UNUSED (str);
|
||||
|
||||
#endif // _RWSTD_NO_EXCEPTIONS
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
#include <string>
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
// helpers to verify that each exception's ctor is explicit
|
||||
// not defined since they must not be referenced if test is successful
|
||||
void is_explicit (const std::logic_error&);
|
||||
void is_explicit (const std::domain_error&);
|
||||
void is_explicit (const std::invalid_argument&);
|
||||
void is_explicit (const std::length_error&);
|
||||
void is_explicit (const std::out_of_range&);
|
||||
void is_explicit (const std::runtime_error&);
|
||||
void is_explicit (const std::range_error&);
|
||||
void is_explicit (const std::overflow_error&);
|
||||
void is_explicit (const std::underflow_error&);
|
||||
|
||||
struct bogus_exception
|
||||
{
|
||||
// also verifies that std::string is declared
|
||||
bogus_exception (const std::string&) { }
|
||||
bogus_exception (const char*) { }
|
||||
};
|
||||
|
||||
// calls to the overoaded is_explicit (std::string ()) must resolve
|
||||
// to this function since there must be no implicit conversion from
|
||||
// std::string to any of the exception classes
|
||||
void is_explicit (const bogus_exception&) { }
|
||||
|
||||
// exercise the ability to construct exception objects w/o
|
||||
// explicitly #including <string> first; std::string must still
|
||||
// be declared (but not necessarily defined)
|
||||
|
||||
#if !defined (_RWSTD_NO_NAMESPACE) && !defined (_RWSTD_NO_HONOR_STD)
|
||||
// declare a global function with the same name as exception
|
||||
# define TEST_NAMESPACE_DEF(T) void T ()
|
||||
#else
|
||||
# define TEST_NAMESPACE_DEF(ignore) (void)0
|
||||
#endif // !_RWSTD_NO_NAMESPACE && !_RWSTD_NO_HONOR_STD
|
||||
|
||||
|
||||
#ifndef _RWSTD_NO_PTR_EXCEPTION_SPEC
|
||||
# define _PTR_THROWS(spec) _THROWS (spec)
|
||||
#else // if defined (_RWSTD_NO_PTR_EXCEPTION_SPEC)
|
||||
// throw specs on pointers to functions not implemented...
|
||||
# define _PTR_THROWS(ignore)
|
||||
#endif // _RWSTD_NO_PTR_EXCEPTION_SPEC
|
||||
|
||||
|
||||
// verify that each name is declared in namespace std
|
||||
// w/o polluting the global namespace
|
||||
#define TEST_DEF(T) \
|
||||
typedef std::T T ## _type; \
|
||||
TEST_NAMESPACE_DEF (T); \
|
||||
/* construct an object */ \
|
||||
std::T obj_ ## T ("std::" _RWSTD_STR (T)); \
|
||||
/* assign the address of object to std::exception* */ \
|
||||
e = &obj_ ## T; \
|
||||
/* verify that assignment can't throw */ \
|
||||
std::T& (std::T::*p_assign_ ## T)(const std::T&) \
|
||||
_PTR_THROWS(()) = &std::T::operator=; \
|
||||
_RWSTD_UNUSED (p_assign_ ## T); \
|
||||
/* verify that what() can't throw */ \
|
||||
const char* (std::T::*p_what_ ## T)() const \
|
||||
_PTR_THROWS(()) = &std::T::what; \
|
||||
_RWSTD_UNUSED (p_what_ ## T); \
|
||||
/* verify ctor postcondition */ \
|
||||
result = result << 1 | cmp (obj_ ## T.what (), \
|
||||
"std::" _RWSTD_STR (T))
|
||||
|
||||
|
||||
int cmp (const char *s1, const char *s2)
|
||||
{
|
||||
for (; *s1 && *s1 == *s2; ++s1, ++s2);
|
||||
return *s2 - *s1;
|
||||
}
|
||||
|
||||
|
||||
// returns 0 on success; on failure returns a bitmap with one bit set
|
||||
// for every exception that failed its ctor postcondition
|
||||
static int test_exception_defs ()
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
// used below to verify public inheritance from std::exception
|
||||
std::exception *e = 0;
|
||||
|
||||
TEST_DEF (logic_error);
|
||||
TEST_DEF (domain_error);
|
||||
TEST_DEF (invalid_argument);
|
||||
TEST_DEF (length_error);
|
||||
TEST_DEF (out_of_range);
|
||||
TEST_DEF (runtime_error);
|
||||
TEST_DEF (range_error);
|
||||
TEST_DEF (overflow_error);
|
||||
TEST_DEF (underflow_error);
|
||||
|
||||
_RWSTD_UNUSED (e);
|
||||
|
||||
#ifndef _RWSTD_NO_EXPLICIT
|
||||
|
||||
// verify that each exceptions converting ctor is explicit
|
||||
// use a pointer since std::string need not be a complete class
|
||||
const char s[40] = "";
|
||||
const std::string *ps = _RWSTD_REINTERPRET_CAST (const std::string*, s);
|
||||
is_explicit (*ps);
|
||||
|
||||
// verify that each exceptions converting ctor from const char*
|
||||
// (if one exists) is also explicit
|
||||
is_explicit (s);
|
||||
|
||||
#endif // _RWSTD_NO_EXPLICIT
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#undef _PTR_THROWS
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
#include <rw_new.h>
|
||||
#include <driver.h>
|
||||
#include <cstddef>
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
template <class Exception>
|
||||
int test_throw (Exception*, const char *str)
|
||||
{
|
||||
#ifndef _RWSTD_NO_EXCEPTIONS
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
try {
|
||||
throw Exception (str);
|
||||
}
|
||||
catch (const Exception &e) {
|
||||
// caught by const reference
|
||||
rw_assert (e.what () && !cmp (e.what (), str),
|
||||
0, __LINE__,
|
||||
"caught by const reference; %s::what() == %#s",
|
||||
str, str);
|
||||
}
|
||||
catch (...) {
|
||||
rw_assert (false, 0, __LINE__,
|
||||
"threw %s, caught an unknown exception", str);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
try {
|
||||
throw Exception (str);
|
||||
}
|
||||
catch (Exception e) {
|
||||
// caught by value
|
||||
rw_assert (e.what () && !cmp (e.what (), str),
|
||||
0, __LINE__,
|
||||
"caught by value; %s::what() == %#s",
|
||||
str, str);
|
||||
}
|
||||
catch (...) {
|
||||
rw_assert (false, 0, __LINE__,
|
||||
"threw %s, caught an unknown exception", str);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
const Exception ex (str);
|
||||
|
||||
try {
|
||||
throw ex;
|
||||
}
|
||||
catch (Exception e) {
|
||||
// caught copy by value
|
||||
rw_assert (e.what () && !cmp (e.what (), str),
|
||||
0, __LINE__,
|
||||
"caught copy by value; %s::what() == %#s",
|
||||
str, str);
|
||||
}
|
||||
catch (...) {
|
||||
rw_assert (false, 0, __LINE__,
|
||||
"threw %s, caught an unknown exception", str);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
try {
|
||||
throw ex;
|
||||
}
|
||||
catch (std::exception &e) {
|
||||
// caught by non-const reference to a base class
|
||||
rw_assert (e.what () && !cmp (e.what (), str),
|
||||
0, __LINE__,
|
||||
"caught by non-const reference to base; %s::what() == %#s",
|
||||
str, str);
|
||||
}
|
||||
catch (...) {
|
||||
rw_assert (false, 0, __LINE__,
|
||||
"threw %s, caught an unknown exception", str);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
try {
|
||||
try {
|
||||
throw Exception (str);
|
||||
}
|
||||
catch (...) {
|
||||
// rethrown
|
||||
throw;
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
// rethrown object caught by value
|
||||
rw_assert (e.what () && !cmp (e.what (), str),
|
||||
0, __LINE__,
|
||||
"caught rethrown by value; %s::what() == %#s", str, str);
|
||||
}
|
||||
catch (...) {
|
||||
rw_assert (false, 0, __LINE__,
|
||||
"threw %s, caught an unknown exception", str);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
try {
|
||||
try {
|
||||
throw Exception (str);
|
||||
}
|
||||
catch (Exception e) {
|
||||
rw_assert (e.what () && !cmp (e.what (), str),
|
||||
0, __LINE__,
|
||||
"caught by value; %s::what() == %#s",
|
||||
str, str);
|
||||
|
||||
// rethrown by value
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
// rethrown object caught by value
|
||||
rw_assert (e.what () && !cmp (e.what (), str),
|
||||
0, __LINE__,
|
||||
"caught rethrown copy by value; %s::what() == %#s",
|
||||
str, str);
|
||||
}
|
||||
catch (...) {
|
||||
rw_assert (false, 0, __LINE__,
|
||||
"threw %s, caught an unknown exception", str);
|
||||
}
|
||||
|
||||
#else // if defined (_RWSTD_NO_EXCEPTIONS);
|
||||
|
||||
_RWSTD_UNUSED (t);
|
||||
_RWSTD_UNUSED (str);
|
||||
|
||||
#endif // _RWSTD_NO_EXCEPTIONS
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
static int
|
||||
run_test (int, char* [])
|
||||
{
|
||||
// verify that exception's (and its derivatives') ctor is explicit
|
||||
is_explicit (std::string ());
|
||||
|
||||
const char* const names[] = {
|
||||
"logic_error", "domain_error", "invalid_argument", "length_error",
|
||||
"out_of_range", "runtime_error", "range_error", "overflow_error",
|
||||
"underflow_error"
|
||||
};
|
||||
|
||||
// if set, each bit corresponds to a failed exception assertion
|
||||
const int failures = test_exception_defs ();
|
||||
|
||||
for (unsigned i = 0; i != sizeof names / sizeof *names; ++i) {
|
||||
rw_assert (!(failures & (1 << i)), 0, __LINE__,
|
||||
"std::%s::%s (const std::string&) postcondition",
|
||||
names [i]);
|
||||
}
|
||||
|
||||
|
||||
// have replacement operator new throw an exception
|
||||
rwt_free_store* const pst = rwt_get_free_store (0);
|
||||
*pst->throw_at_calls_ [0] = pst->new_calls_ [0] + 1;
|
||||
|
||||
// create a very long string to guarantee that exception ctors
|
||||
// try to dynamically allocate storage even if it otherwise
|
||||
// use some clever scheme to avoid doing so
|
||||
char long_str [0x10000];
|
||||
for (unsigned i = 0; i != sizeof long_str - 1; ++i)
|
||||
long_str [i] = '*';
|
||||
|
||||
long_str [sizeof long_str - 1] = '\0';
|
||||
|
||||
int new_throws = 0;
|
||||
|
||||
_TRY {
|
||||
// see if replacement operator new throws an exception
|
||||
// when called directly from the program
|
||||
void *p = ::operator new (sizeof long_str);
|
||||
::operator delete (p);
|
||||
new_throws = 0;
|
||||
|
||||
#ifdef _RWSTD_NO_REPLACEABLE_NEW_DELETE
|
||||
|
||||
// MSVC and VAC++ don't reliably replace operators
|
||||
// new and delete across shared librray boundaries
|
||||
|
||||
rw_warn (false, 0, __LINE__,
|
||||
"replacement ::operator new(std::size_t = %u) failed "
|
||||
"to throw when called directly from a program: this "
|
||||
"is an expected failure on this platform",
|
||||
sizeof long_str);
|
||||
|
||||
#else // if !defined (_RWSTD_NO_REPLACEABLE_NEW_DELETE)
|
||||
|
||||
rw_assert (false, 0, __LINE__,
|
||||
"replacement ::operator new(std::size_t = %u) "
|
||||
"unexpectdly failed to throw when called directly "
|
||||
"from a program",
|
||||
sizeof long_str);
|
||||
|
||||
#endif // _RWSTD_NO_REPLACEABLE_NEW_DELETE
|
||||
|
||||
}
|
||||
_CATCH (...) {
|
||||
new_throws = 1;
|
||||
}
|
||||
|
||||
*pst->throw_at_calls_ [0] = pst->new_calls_ [0] + 1;
|
||||
|
||||
_TRY {
|
||||
// see if replacement operator new throws an exception
|
||||
// when called indirectly, i.e., from the library binary
|
||||
void* const p = _RW::__rw_allocate (sizeof long_str, 0);
|
||||
_RW::__rw_deallocate (p, 0);
|
||||
new_throws = 0;
|
||||
|
||||
#ifdef _RWSTD_NO_REPLACEABLE_NEW_DELETE
|
||||
|
||||
// MSVC and VAC++ don't reliably replace operators
|
||||
// new and delete across shared librray boundaries
|
||||
|
||||
rw_warn (false, 0, __LINE__,
|
||||
"replacement ::operator new(std::size_t = %u) failed "
|
||||
"to throw when called from the library: this is an "
|
||||
"expected failure on this platform",
|
||||
sizeof long_str);
|
||||
|
||||
#else // if !defined (_RWSTD_NO_REPLACEABLE_NEW_DELETE)
|
||||
|
||||
rw_assert (false, 0, __LINE__,
|
||||
"replacement ::operator new(std::size_t = %u) "
|
||||
"unexpectdly failed to throw when called from "
|
||||
"the library",
|
||||
sizeof long_str);
|
||||
|
||||
#endif // _RWSTD_NO_REPLACEABLE_NEW_DELETE
|
||||
|
||||
}
|
||||
_CATCH (...) {
|
||||
new_throws = 1;
|
||||
}
|
||||
|
||||
// exercise exception specification on class ctors
|
||||
// and the ability to throw and catch exception objects
|
||||
#define TEST_EX_SPEC(T) do { \
|
||||
/* do not induce an exception from replacement operator new */ \
|
||||
*pst->throw_at_calls_ [0] = std::size_t (-1); \
|
||||
*pst->throw_at_calls_ [1] = std::size_t (-1); \
|
||||
/* verify that exception objects can be thrown, caught, and rethrown */\
|
||||
test_throw ((std:: T*)0, "std::" #T); \
|
||||
/* induce an exception from replacement operator new */ \
|
||||
*pst->throw_at_calls_ [0] = pst->new_calls_ [0] + 1; \
|
||||
*pst->throw_at_calls_ [1] = pst->new_calls_ [1] + 1; \
|
||||
/* verify that each exception ctor propagates the exception thrown */ \
|
||||
/* from operator new(); failure wil cause a call to terminate() */ \
|
||||
/* tests are expected to silently fail if (0 == new_throws) holds */ \
|
||||
const int threw = test_ex_spec ((std::T*)0, long_str); \
|
||||
rw_assert (threw == new_throws, 0, __LINE__, \
|
||||
"attempthing to construct a std::" #T " %s an exception", \
|
||||
new_throws ? "failed to rethrow" : "unexpectedly threw"); \
|
||||
} while (0)
|
||||
|
||||
TEST_EX_SPEC (logic_error);
|
||||
TEST_EX_SPEC (domain_error);
|
||||
TEST_EX_SPEC (invalid_argument);
|
||||
TEST_EX_SPEC (length_error);
|
||||
TEST_EX_SPEC (out_of_range);
|
||||
TEST_EX_SPEC (runtime_error);
|
||||
TEST_EX_SPEC (range_error);
|
||||
TEST_EX_SPEC (overflow_error);
|
||||
TEST_EX_SPEC (underflow_error);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
int main (int argc, char* argv [])
|
||||
{
|
||||
return rw_test (argc, argv, __FILE__,
|
||||
"lib.std.exceptions",
|
||||
0 /* no comment */,
|
||||
run_test,
|
||||
"",
|
||||
(void*)0);
|
||||
}
|
||||
Reference in New Issue
Block a user