1 /*
2  *  Created by Phil on 15/04/2013.
3  *  Copyright 2013 Two Blue Cubes Ltd. All rights reserved.
4  *
5  *  Distributed under the Boost Software License, Version 1.0. (See accompanying
6  *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7  */
8 #ifndef TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED
9 #define TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED
10 
11 // Detect a number of compiler features - by compiler
12 // The following features are defined:
13 //
14 // CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported?
15 // CATCH_CONFIG_WINDOWS_SEH : is Windows SEH supported?
16 // CATCH_CONFIG_POSIX_SIGNALS : are POSIX signals supported?
17 // CATCH_CONFIG_DISABLE_EXCEPTIONS : Are exceptions enabled?
18 // ****************
19 // Note to maintainers: if new toggles are added please document them
20 // in configuration.md, too
21 // ****************
22 
23 // In general each macro has a _NO_<feature name> form
24 // (e.g. CATCH_CONFIG_NO_POSIX_SIGNALS) which disables the feature.
25 // Many features, at point of detection, define an _INTERNAL_ macro, so they
26 // can be combined, en-mass, with the _NO_ forms later.
27 
28 #include "catch_platform.h"
29 
30 #ifdef __cplusplus
31 
32 #  if (__cplusplus >= 201402L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201402L)
33 #    define CATCH_CPP14_OR_GREATER
34 #  endif
35 
36 #  if (__cplusplus >= 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
37 #    define CATCH_CPP17_OR_GREATER
38 #  endif
39 
40 #endif
41 
42 // We have to avoid both ICC and Clang, because they try to mask themselves
43 // as gcc, and we want only GCC in this block
44 #if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) && !defined(__CUDACC__)
45 #    define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic push" )
46 #    define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION  _Pragma( "GCC diagnostic pop" )
47 
48 #    define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__)
49 
50 #endif
51 
52 #if defined(__clang__)
53 
54 #    define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic push" )
55 #    define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION  _Pragma( "clang diagnostic pop" )
56 
57 // As of this writing, IBM XL's implementation of __builtin_constant_p has a bug
58 // which results in calls to destructors being emitted for each temporary,
59 // without a matching initialization. In practice, this can result in something
60 // like `std::string::~string` being called on an uninitialized value.
61 //
62 // For example, this code will likely segfault under IBM XL:
63 // ```
64 // REQUIRE(std::string("12") + "34" == "1234")
65 // ```
66 //
67 // Therefore, `CATCH_INTERNAL_IGNORE_BUT_WARN` is not implemented.
68 #  if !defined(__ibmxl__) && !defined(__CUDACC__)
69 #    define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__) /* NOLINT(cppcoreguidelines-pro-type-vararg, hicpp-vararg) */
70 #  endif
71 
72 
73 #    define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
74          _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) \
75          _Pragma( "clang diagnostic ignored \"-Wglobal-constructors\"")
76 
77 #    define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
78          _Pragma( "clang diagnostic ignored \"-Wparentheses\"" )
79 
80 #    define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \
81          _Pragma( "clang diagnostic ignored \"-Wunused-variable\"" )
82 
83 #    define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
84          _Pragma( "clang diagnostic ignored \"-Wgnu-zero-variadic-macro-arguments\"" )
85 
86 #    define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
87          _Pragma( "clang diagnostic ignored \"-Wunused-template\"" )
88 
89 #endif // __clang__
90 
91 
92 ////////////////////////////////////////////////////////////////////////////////
93 // Assume that non-Windows platforms support posix signals by default
94 #if !defined(CATCH_PLATFORM_WINDOWS)
95     #define CATCH_INTERNAL_CONFIG_POSIX_SIGNALS
96 #endif
97 
98 ////////////////////////////////////////////////////////////////////////////////
99 // We know some environments not to support full POSIX signals
100 #if defined(__CYGWIN__) || defined(__QNX__) || defined(__EMSCRIPTEN__) || defined(__DJGPP__)
101     #define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS
102 #endif
103 
104 #ifdef __OS400__
105 #       define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS
106 #       define CATCH_CONFIG_COLOUR_NONE
107 #endif
108 
109 ////////////////////////////////////////////////////////////////////////////////
110 // Android somehow still does not support std::to_string
111 #if defined(__ANDROID__)
112 #    define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING
113 #    define CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE
114 #endif
115 
116 ////////////////////////////////////////////////////////////////////////////////
117 // Not all Windows environments support SEH properly
118 #if defined(__MINGW32__)
119 #    define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH
120 #endif
121 
122 ////////////////////////////////////////////////////////////////////////////////
123 // PS4
124 #if defined(__ORBIS__)
125 #    define CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE
126 #endif
127 
128 ////////////////////////////////////////////////////////////////////////////////
129 // Cygwin
130 #ifdef __CYGWIN__
131 
132 // Required for some versions of Cygwin to declare gettimeofday
133 // see: http://stackoverflow.com/questions/36901803/gettimeofday-not-declared-in-this-scope-cygwin
134 #   define _BSD_SOURCE
135 // some versions of cygwin (most) do not support std::to_string. Use the libstd check.
136 // https://gcc.gnu.org/onlinedocs/gcc-4.8.2/libstdc++/api/a01053_source.html line 2812-2813
137 # if !((__cplusplus >= 201103L) && defined(_GLIBCXX_USE_C99) \
138            && !defined(_GLIBCXX_HAVE_BROKEN_VSWPRINTF))
139 
140 #    define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING
141 
142 # endif
143 #endif // __CYGWIN__
144 
145 ////////////////////////////////////////////////////////////////////////////////
146 // Visual C++
147 #if defined(_MSC_VER)
148 
149 #  define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION __pragma( warning(push) )
150 #  define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION  __pragma( warning(pop) )
151 
152 
153 // Universal Windows platform does not support SEH
154 // Or console colours (or console at all...)
155 #  if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)
156 #    define CATCH_CONFIG_COLOUR_NONE
157 #  else
158 #    define CATCH_INTERNAL_CONFIG_WINDOWS_SEH
159 #  endif
160 
161 // MSVC traditional preprocessor needs some workaround for __VA_ARGS__
162 // _MSVC_TRADITIONAL == 0 means new conformant preprocessor
163 // _MSVC_TRADITIONAL == 1 means old traditional non-conformant preprocessor
164 #  if !defined(__clang__) // Handle Clang masquerading for msvc
165 #    if !defined(_MSVC_TRADITIONAL) || (defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL)
166 #      define CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
167 #    endif // MSVC_TRADITIONAL
168 #  endif // __clang__
169 
170 #endif // _MSC_VER
171 
172 #if defined(_REENTRANT) || defined(_MSC_VER)
173 // Enable async processing, as -pthread is specified or no additional linking is required
174 # define CATCH_INTERNAL_CONFIG_USE_ASYNC
175 #endif // _MSC_VER
176 
177 ////////////////////////////////////////////////////////////////////////////////
178 // Check if we are compiled with -fno-exceptions or equivalent
179 #if defined(__EXCEPTIONS) || defined(__cpp_exceptions) || defined(_CPPUNWIND)
180 #  define CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED
181 #endif
182 
183 ////////////////////////////////////////////////////////////////////////////////
184 // DJGPP
185 #ifdef __DJGPP__
186 #  define CATCH_INTERNAL_CONFIG_NO_WCHAR
187 #endif // __DJGPP__
188 
189 ////////////////////////////////////////////////////////////////////////////////
190 // Embarcadero C++Build
191 #if defined(__BORLANDC__)
192     #define CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN
193 #endif
194 
195 ////////////////////////////////////////////////////////////////////////////////
196 
197 // Use of __COUNTER__ is suppressed during code analysis in
198 // CLion/AppCode 2017.2.x and former, because __COUNTER__ is not properly
199 // handled by it.
200 // Otherwise all supported compilers support COUNTER macro,
201 // but user still might want to turn it off
202 #if ( !defined(__JETBRAINS_IDE__) || __JETBRAINS_IDE__ >= 20170300L )
203     #define CATCH_INTERNAL_CONFIG_COUNTER
204 #endif
205 
206 
207 ////////////////////////////////////////////////////////////////////////////////
208 
209 // RTX is a special version of Windows that is real time.
210 // This means that it is detected as Windows, but does not provide
211 // the same set of capabilities as real Windows does.
212 #if defined(UNDER_RTSS) || defined(RTX64_BUILD)
213     #define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH
214     #define CATCH_INTERNAL_CONFIG_NO_ASYNC
215     #define CATCH_CONFIG_COLOUR_NONE
216 #endif
217 
218 #if !defined(_GLIBCXX_USE_C99_MATH_TR1)
219 #define CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER
220 #endif
221 
222 // Various stdlib support checks that require __has_include
223 #if defined(__has_include)
224   // Check if string_view is available and usable
225   #if __has_include(<string_view>) && defined(CATCH_CPP17_OR_GREATER)
226   #    define CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW
227   #endif
228 
229   // Check if optional is available and usable
230   #  if __has_include(<optional>) && defined(CATCH_CPP17_OR_GREATER)
231   #    define CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL
232   #  endif // __has_include(<optional>) && defined(CATCH_CPP17_OR_GREATER)
233 
234   // Check if byte is available and usable
235   #  if __has_include(<cstddef>) && defined(CATCH_CPP17_OR_GREATER)
236   #    include <cstddef>
237   #    if __cpp_lib_byte > 0
238   #      define CATCH_INTERNAL_CONFIG_CPP17_BYTE
239   #    endif
240   #  endif // __has_include(<cstddef>) && defined(CATCH_CPP17_OR_GREATER)
241 
242   // Check if variant is available and usable
243   #  if __has_include(<variant>) && defined(CATCH_CPP17_OR_GREATER)
244   #    if defined(__clang__) && (__clang_major__ < 8)
245          // work around clang bug with libstdc++ https://bugs.llvm.org/show_bug.cgi?id=31852
246          // fix should be in clang 8, workaround in libstdc++ 8.2
247   #      include <ciso646>
248   #      if defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9)
249   #        define CATCH_CONFIG_NO_CPP17_VARIANT
250   #      else
251   #        define CATCH_INTERNAL_CONFIG_CPP17_VARIANT
252   #      endif // defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9)
253   #    else
254   #      define CATCH_INTERNAL_CONFIG_CPP17_VARIANT
255   #    endif // defined(__clang__) && (__clang_major__ < 8)
256   #  endif // __has_include(<variant>) && defined(CATCH_CPP17_OR_GREATER)
257 #endif // defined(__has_include)
258 
259 
260 #if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER)
261 #   define CATCH_CONFIG_COUNTER
262 #endif
263 #if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && !defined(CATCH_CONFIG_WINDOWS_SEH) && !defined(CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH)
264 #   define CATCH_CONFIG_WINDOWS_SEH
265 #endif
266 // This is set by default, because we assume that unix compilers are posix-signal-compatible by default.
267 #if defined(CATCH_INTERNAL_CONFIG_POSIX_SIGNALS) && !defined(CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_POSIX_SIGNALS)
268 #   define CATCH_CONFIG_POSIX_SIGNALS
269 #endif
270 // This is set by default, because we assume that compilers with no wchar_t support are just rare exceptions.
271 #if !defined(CATCH_INTERNAL_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_WCHAR)
272 #   define CATCH_CONFIG_WCHAR
273 #endif
274 
275 #if !defined(CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_CPP11_TO_STRING)
276 #    define CATCH_CONFIG_CPP11_TO_STRING
277 #endif
278 
279 #if defined(CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_NO_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_CPP17_OPTIONAL)
280 #  define CATCH_CONFIG_CPP17_OPTIONAL
281 #endif
282 
283 #if defined(CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_NO_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_CPP17_STRING_VIEW)
284 #  define CATCH_CONFIG_CPP17_STRING_VIEW
285 #endif
286 
287 #if defined(CATCH_INTERNAL_CONFIG_CPP17_VARIANT) && !defined(CATCH_CONFIG_NO_CPP17_VARIANT) && !defined(CATCH_CONFIG_CPP17_VARIANT)
288 #  define CATCH_CONFIG_CPP17_VARIANT
289 #endif
290 
291 #if defined(CATCH_INTERNAL_CONFIG_CPP17_BYTE) && !defined(CATCH_CONFIG_NO_CPP17_BYTE) && !defined(CATCH_CONFIG_CPP17_BYTE)
292 #  define CATCH_CONFIG_CPP17_BYTE
293 #endif
294 
295 
296 #if defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT)
297 #  define CATCH_INTERNAL_CONFIG_NEW_CAPTURE
298 #endif
299 
300 #if defined(CATCH_INTERNAL_CONFIG_NEW_CAPTURE) && !defined(CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE) && !defined(CATCH_CONFIG_NO_NEW_CAPTURE) && !defined(CATCH_CONFIG_NEW_CAPTURE)
301 #  define CATCH_CONFIG_NEW_CAPTURE
302 #endif
303 
304 #if !defined(CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED) && !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
305 #  define CATCH_CONFIG_DISABLE_EXCEPTIONS
306 #endif
307 
308 #if defined(CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_NO_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_POLYFILL_ISNAN)
309 #  define CATCH_CONFIG_POLYFILL_ISNAN
310 #endif
311 
312 #if defined(CATCH_INTERNAL_CONFIG_USE_ASYNC)  && !defined(CATCH_INTERNAL_CONFIG_NO_ASYNC) && !defined(CATCH_CONFIG_NO_USE_ASYNC) && !defined(CATCH_CONFIG_USE_ASYNC)
313 #  define CATCH_CONFIG_USE_ASYNC
314 #endif
315 
316 #if defined(CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE) && !defined(CATCH_CONFIG_NO_ANDROID_LOGWRITE) && !defined(CATCH_CONFIG_ANDROID_LOGWRITE)
317 #  define CATCH_CONFIG_ANDROID_LOGWRITE
318 #endif
319 
320 #if defined(CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_NO_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_GLOBAL_NEXTAFTER)
321 #  define CATCH_CONFIG_GLOBAL_NEXTAFTER
322 #endif
323 
324 
325 // Even if we do not think the compiler has that warning, we still have
326 // to provide a macro that can be used by the code.
327 #if !defined(CATCH_INTERNAL_START_WARNINGS_SUPPRESSION)
328 #   define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION
329 #endif
330 #if !defined(CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION)
331 #   define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
332 #endif
333 #if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS)
334 #   define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS
335 #endif
336 #if !defined(CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS)
337 #   define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS
338 #endif
339 #if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS)
340 #   define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS
341 #endif
342 #if !defined(CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS)
343 #   define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS
344 #endif
345 
346 // The goal of this macro is to avoid evaluation of the arguments, but
347 // still have the compiler warn on problems inside...
348 #if !defined(CATCH_INTERNAL_IGNORE_BUT_WARN)
349 #   define CATCH_INTERNAL_IGNORE_BUT_WARN(...)
350 #endif
351 
352 #if defined(__APPLE__) && defined(__apple_build_version__) && (__clang_major__ < 10)
353 #   undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS
354 #elif defined(__clang__) && (__clang_major__ < 5)
355 #   undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS
356 #endif
357 
358 #if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS)
359 #   define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS
360 #endif
361 
362 #if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
363 #define CATCH_TRY if ((true))
364 #define CATCH_CATCH_ALL if ((false))
365 #define CATCH_CATCH_ANON(type) if ((false))
366 #else
367 #define CATCH_TRY try
368 #define CATCH_CATCH_ALL catch (...)
369 #define CATCH_CATCH_ANON(type) catch (type)
370 #endif
371 
372 #if defined(CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_NO_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR)
373 #define CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
374 #endif
375 
376 #endif // TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED
377 
378