Line data Source code
1 1 : // Distributed under the MIT License.
2 : // See LICENSE.txt for details.
3 :
4 : /// \file
5 : /// Defines macro ASSERT.
6 :
7 : #pragma once
8 :
9 : #include <iomanip>
10 : #include <sstream>
11 : #include <string>
12 :
13 : #include "Utilities/ErrorHandling/AbortWithErrorMessage.hpp"
14 : #include "Utilities/ErrorHandling/FloatingPointExceptions.hpp"
15 :
16 : /*!
17 : * \ingroup ErrorHandlingGroup
18 : * \brief Assert that an expression should be true.
19 : *
20 : * If the preprocessor macro SPECTRE_DEBUG is defined and the expression is
21 : * false, an error message is printed to the standard error stream, and the
22 : * program aborts. ASSERT should be used to catch coding errors as it does
23 : * nothing in production code.
24 : * \param a the expression that must be true
25 : * \param m the error message as an ostream
26 : */
27 : #ifdef SPECTRE_DEBUG
28 : // isocpp.org recommends using an `if (true)` instead of a `do
29 : // while(false)` for macros because the latter can mess with inlining
30 : // in some (old?) compilers:
31 : // https://isocpp.org/wiki/faq/misc-technical-issues#macros-with-multi-stmts
32 : // https://isocpp.org/wiki/faq/misc-technical-issues#macros-with-if
33 : // However, Intel's reachability analyzer (as of version 16.0.3
34 : // 20160415) can't figure out that the else branch and everything
35 : // after it is unreachable, causing warnings (and possibly suboptimal
36 : // code generation).
37 : #define ASSERT(a, m) \
38 : do { \
39 : if (!(a)) { /* NOLINT(readability-simplify-boolean-expr) */ \
40 : const ScopedFpeState disable_fpes_ASSERT(false); \
41 : std::ostringstream avoid_name_collisions_ASSERT; \
42 : /* clang-tidy: macro arg in parentheses */ \
43 : avoid_name_collisions_ASSERT << std::setprecision(18) << std::scientific \
44 : << m; /* NOLINT */ \
45 : abort_with_error_message(#a, __FILE__, __LINE__, \
46 : static_cast<const char*>(__PRETTY_FUNCTION__), \
47 : avoid_name_collisions_ASSERT.str()); \
48 : } \
49 : } while (false)
50 : #else
51 1 : #define ASSERT(a, m) \
52 : do { \
53 : if (false) { \
54 : static_cast<void>(a); \
55 : const ScopedFpeState disable_fpes_ASSERT(false); \
56 : std::ostringstream avoid_name_collisions_ASSERT; \
57 : /* clang-tidy: macro arg in parentheses */ \
58 : avoid_name_collisions_ASSERT << std::setprecision(18) << std::scientific \
59 : << m; /* NOLINT */ \
60 : static_cast<void>(avoid_name_collisions_ASSERT); \
61 : } \
62 : } while (false)
63 : #endif
|