Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
18.limits.traps.cpp
Go to the documentation of this file.
1
29#include <limits>
30
31#include <csignal> // for SIGFPE, signal
32
33#include <rw_any.h> // for rw_any_t
34#include <rw_cmdopt.h> // for rw_enabled()
35#include <rw_driver.h> // for rw_test(), ...
36
37
39#ifdef _RWSTD_OS_LINUX
40
41 // use siglongjmp() and sigsetjmp() on Linux to avoid
42 // http://sourceware.org/bugzilla/show_bug.cgi?id=2351
43# include <setjmp.h> // for siglongjmp, sigsetjmp
44
45jmp_buf jmp_env;
46
47extern "C" {
48
49void handle_fpe (int)
50{
51 siglongjmp (jmp_env, 1);
52}
53
54} // extern "C"
55
56# define RW_SIGSETJMP(env, signo) sigsetjmp (env, signo)
57#else // if !defined (_RWSTD_OS_LINUX)
58
59# include <csetjmp> // for longjmp, setjmp
60
61std::jmp_buf jmp_env;
62
63extern "C" {
64
65void handle_fpe (int)
66{
67 std::longjmp (jmp_env, 1);
68}
69
70} // extern "C"
71# define RW_SIGSETJMP(env, ignore) setjmp (env)
72#endif // _RWSTD_OS_LINUX
73
74
75
77#ifdef _MSC_VER
78 // silence useless MSVC warnings:
79 // 4800: 'int' : forcing value to bool 'true' or 'false'
80 // 4804: '/' : unsafe use of type 'bool' in operation
81# pragma warning (disable: 4800 4804)
82
83 // use Structured Exception Handling to detect arithmetic exceptions
84# define TRY __try
85# define EXCEPT(arg) __except (arg)
86#else
87# define TRY if (1)
88# define EXCEPT(ignore) else if (0)
89#endif // _MSC_VER
90
91
92template <class numT>
93inline void
94try_trap (const volatile numT &one, const volatile numT &zero,
95 numT &result, bool &trapped)
96{
97 TRY {
98 result = one / zero;
99 }
100 EXCEPT (1) {
101 // Windows SEH hackery
102 trapped = true;
103 }
104}
105
106
107template <class numT>
108numT test_traps (numT, int lineno, bool)
109{
110 static const char* const tname = rw_any_t (numT ()).type_name ();
111
112 if (!rw_enabled (tname)) {
113 rw_note (0, 0, 0, "numeric_limits<%s>::traps test disabled", tname);
114 return numT ();
115 }
116
117 const bool traps = std::numeric_limits<numT>::traps;
118
119 rw_info (0, 0, 0, "std::numeric_limits<%s>::traps = %b", tname, traps);
120
121#ifdef SIGFPE
122 std::signal (SIGFPE, handle_fpe);
123#else // if !defined (SIGFPE)
124 if (!rw_warn (!traps, 0, lineno,
125 "SIGFPE not #defined and numeric_limits<%s>::traps == %b, "
126 "cannot test", tname, traps)) {
127 return numT ();
128 }
129#endif // SIGFPE
130
131 numT result = numT ();
132
133 // set the environment
134 const int jumped = RW_SIGSETJMP (jmp_env, SIGFPE);
135
136 volatile numT zero = numT (jumped);
137 volatile numT one = numT (1);
138
139 bool trapped = false;
140
141 if (jumped) {
142 // setjmp() call above returned from the SIGFPE handler
143 // as a result of a floating point exception triggered
144 // by the division by zero in the else block below
145 result = zero / one;
146
147 trapped = true;
148 }
149 else {
150 // setjmp() call above returned after setting up the jump
151 // environment; see of division by zero traps (if so, it
152 // will generate a SIGFPE which will be caught by the
153 // signal hanlder above and execution will resume by
154 // returning from setjmp() above again, but this time
155 // with a non-zero value
156 try_trap (one, zero, result, trapped);
157 }
158
159 rw_assert (trapped == traps, 0, lineno,
160 "numeric_limits<%s>::traps == %b, got %b",
161 tname, trapped, traps);
162
163 return result;
164}
165
166
168static int
169run_test (int, char*[])
170{
171#define TEST(T, floating) test_traps ((T)0, __LINE__, floating)
172
173#ifndef _RWSTD_NO_NATIVE_BOOL
174 TEST (bool, false);
175#endif // _RWSTD_NO_NATIVE_BOOL
176
177 TEST (char, false);
178 TEST (signed char, false);
179 TEST (unsigned char, false);
180
181 TEST (short, false);
182 TEST (unsigned short, false);
183 TEST (int, false);
184 TEST (unsigned int, false);
185 TEST (long, false);
186 TEST (unsigned long, false);
187
188#ifndef _RWSTD_NO_LONG_LONG
189 TEST (_RWSTD_LONG_LONG, false);
190 TEST (unsigned _RWSTD_LONG_LONG, false);
191#endif // _RWSTD_NO_LONG_LONG
192
193#ifndef _RWSTD_NO_NATIVE_WCHAR_T
194 TEST (wchar_t, false);
195#endif // _RWSTD_NO_NATIVE_WCHAR_T
196
197 TEST (float, true);
198 TEST (double, true);
199
200#ifndef _RWSTD_NO_LONG_DOUBLE
201 TEST (long double, true);
202#endif // _RWSTD_NO_LONG_DOUBLE
203
204 return 0;
205}
206
207
209int main (int argc, char *argv[])
210{
211 return rw_test (argc, argv, __FILE__,
212 "lib.numeric.limits.members",
213 "traps data member",
214 run_test,
215 0, 0);
216}
#define lineno
Definition 17.names.cpp:491
#define RW_SIGSETJMP(env, ignore)
#define TEST(T, floating)
#define EXCEPT(ignore)
void handle_fpe(int)
std::jmp_buf jmp_env
numT test_traps(numT, int lineno, bool)
#define TRY
void try_trap(const volatile numT &one, const volatile numT &zero, numT &result, bool &trapped)
volatile int result
void run_test(const ForwardIterator &dummy, T *, Predicate *pred)
#define main
volatile int one
Definition LIMITS.cpp:61
volatile int zero
Definition LIMITS.cpp:60
#define _RWSTD_LONG_LONG
#define SIGFPE
const char * type_name() const
Definition any.cpp:310
_TEST_EXPORT int rw_enabled(const char *name)
_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_warn(int, const char *, int, const char *,...)
Definition driver.cpp:1647