SpECTRE Documentation Coverage Report
Current view: top level - Utilities/ErrorHandling - Assert.hpp Coverage Total Hit
Commit: a37d7b3c1803b88b537d2aef1c27ca5e6b499398 Lines: 33.3 % 6 2
Test Date: 2026-11-12 04:47:19
Legend: Lines:     hit not hit

            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              : #include "Utilities/Kokkos/KokkosMacros.hpp"
      16              : 
      17              : /*!
      18              :  * \ingroup ErrorHandlingGroup
      19              :  * \brief Assert that an expression should be true.
      20              :  *
      21              :  * If the preprocessor macro SPECTRE_DEBUG is defined and the expression is
      22              :  * false, an error message is printed to the standard error stream, and the
      23              :  * program aborts. ASSERT should be used to catch coding errors as it does
      24              :  * nothing in production code.
      25              :  *
      26              :  * ASSERT can also be used in functions that run on a GPU (`KOKKOS_FUNCTION`s).
      27              :  * On the GPU the error message can't be printed, so a failed assertion only
      28              :  * reports the expression, file and line.
      29              :  *
      30              :  * \param a the expression that must be true
      31              :  * \param m the error message as an ostream
      32              :  */
      33              : #ifdef SPECTRE_DEBUG
      34              : // isocpp.org recommends using an `if (true)` instead of a `do
      35              : // while(false)` for macros because the latter can mess with inlining
      36              : // in some (old?) compilers:
      37              : // https://isocpp.org/wiki/faq/misc-technical-issues#macros-with-multi-stmts
      38              : // https://isocpp.org/wiki/faq/misc-technical-issues#macros-with-if
      39              : // However, Intel's reachability analyzer (as of version 16.0.3
      40              : // 20160415) can't figure out that the else branch and everything
      41              : // after it is unreachable, causing warnings (and possibly suboptimal
      42              : // code generation).
      43              : #define SPECTRE_ASSERT_ON_HOST(a, m)                                           \
      44              :   do {                                                                         \
      45              :     if (!(a)) { /* NOLINT(readability-simplify-boolean-expr) */                \
      46              :       const ScopedFpeState disable_fpes_ASSERT(false);                         \
      47              :       std::ostringstream avoid_name_collisions_ASSERT;                         \
      48              :       /* clang-tidy: macro arg in parentheses */                               \
      49              :       avoid_name_collisions_ASSERT << std::setprecision(18) << std::scientific \
      50              :                                    << m; /* NOLINT */                          \
      51              :       abort_with_error_message(#a, __FILE__, __LINE__,                         \
      52              :                                static_cast<const char*>(__PRETTY_FUNCTION__),  \
      53              :                                avoid_name_collisions_ASSERT.str());            \
      54              :     }                                                                          \
      55              :   } while (false)
      56              : #else
      57            1 : #define SPECTRE_ASSERT_ON_HOST(a, m)                                           \
      58              :   do {                                                                         \
      59              :     if (false) {                                                               \
      60              :       static_cast<void>(a);                                                    \
      61              :       const ScopedFpeState disable_fpes_ASSERT(false);                         \
      62              :       std::ostringstream avoid_name_collisions_ASSERT;                         \
      63              :       /* clang-tidy: macro arg in parentheses */                               \
      64              :       avoid_name_collisions_ASSERT << std::setprecision(18) << std::scientific \
      65              :                                    << m; /* NOLINT */                          \
      66              :       static_cast<void>(avoid_name_collisions_ASSERT);                         \
      67              :     }                                                                          \
      68              :   } while (false)
      69              : #endif
      70              : 
      71              : #ifdef SPECTRE_KOKKOS
      72              : // In code that is compiled for a GPU, the message can't be streamed and
      73              : // printed, so only the expression, file and line are reported there. Kokkos
      74              : // compiles only one of the branches for the host and the GPU, respectively.
      75            0 : #define SPECTRE_ASSERT_STRINGIFY_IMPL(x) #x
      76            0 : #define SPECTRE_ASSERT_STRINGIFY(x) SPECTRE_ASSERT_STRINGIFY_IMPL(x)
      77            0 : #define SPECTRE_ASSERT_DEVICE_MESSAGE(a) \
      78              :   "ASSERT failed on the device: " a "\nat " __FILE__                  \
      79              :   ":" SPECTRE_ASSERT_STRINGIFY(__LINE__) "\nRun on the host for the " \
      80              :                                          "full error message.\n"
      81              : #ifdef SPECTRE_DEBUG
      82              : #define ASSERT(a, m)                                                           \
      83              :   do {                                                                         \
      84              :     KOKKOS_IF_ON_HOST((SPECTRE_ASSERT_ON_HOST(a, m);))                         \
      85              :     KOKKOS_IF_ON_DEVICE(                                                       \
      86              :         (if (not(a)) { ::Kokkos::abort(SPECTRE_ASSERT_DEVICE_MESSAGE(#a)); })) \
      87              :   } while (false)
      88              : #else
      89            0 : #define ASSERT(a, m)                                   \
      90              :   do {                                                 \
      91              :     KOKKOS_IF_ON_HOST((SPECTRE_ASSERT_ON_HOST(a, m);)) \
      92              :   } while (false)
      93              : #endif
      94              : #else
      95              : #define ASSERT(a, m) SPECTRE_ASSERT_ON_HOST(a, m)
      96              : #endif
        

Generated by: LCOV version 2.0-1