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