1*b0d29bc4SBrooks Davis // Copyright 2010 The Kyua Authors. 2*b0d29bc4SBrooks Davis // All rights reserved. 3*b0d29bc4SBrooks Davis // 4*b0d29bc4SBrooks Davis // Redistribution and use in source and binary forms, with or without 5*b0d29bc4SBrooks Davis // modification, are permitted provided that the following conditions are 6*b0d29bc4SBrooks Davis // met: 7*b0d29bc4SBrooks Davis // 8*b0d29bc4SBrooks Davis // * Redistributions of source code must retain the above copyright 9*b0d29bc4SBrooks Davis // notice, this list of conditions and the following disclaimer. 10*b0d29bc4SBrooks Davis // * Redistributions in binary form must reproduce the above copyright 11*b0d29bc4SBrooks Davis // notice, this list of conditions and the following disclaimer in the 12*b0d29bc4SBrooks Davis // documentation and/or other materials provided with the distribution. 13*b0d29bc4SBrooks Davis // * Neither the name of Google Inc. nor the names of its contributors 14*b0d29bc4SBrooks Davis // may be used to endorse or promote products derived from this software 15*b0d29bc4SBrooks Davis // without specific prior written permission. 16*b0d29bc4SBrooks Davis // 17*b0d29bc4SBrooks Davis // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18*b0d29bc4SBrooks Davis // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19*b0d29bc4SBrooks Davis // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20*b0d29bc4SBrooks Davis // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21*b0d29bc4SBrooks Davis // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22*b0d29bc4SBrooks Davis // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23*b0d29bc4SBrooks Davis // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24*b0d29bc4SBrooks Davis // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25*b0d29bc4SBrooks Davis // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26*b0d29bc4SBrooks Davis // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27*b0d29bc4SBrooks Davis // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28*b0d29bc4SBrooks Davis 29*b0d29bc4SBrooks Davis /// \file utils/sanity.hpp 30*b0d29bc4SBrooks Davis /// 31*b0d29bc4SBrooks Davis /// Set of macros that replace the standard assert macro with more semantical 32*b0d29bc4SBrooks Davis /// expressivity and meaningful diagnostics. Code should never use assert 33*b0d29bc4SBrooks Davis /// directly. 34*b0d29bc4SBrooks Davis /// 35*b0d29bc4SBrooks Davis /// In general, the checks performed by the macros in this code are only 36*b0d29bc4SBrooks Davis /// executed if the code is built with debugging support (that is, if the NDEBUG 37*b0d29bc4SBrooks Davis /// macro is NOT defined). 38*b0d29bc4SBrooks Davis 39*b0d29bc4SBrooks Davis #if !defined(UTILS_SANITY_HPP) 40*b0d29bc4SBrooks Davis #define UTILS_SANITY_HPP 41*b0d29bc4SBrooks Davis 42*b0d29bc4SBrooks Davis #include "utils/sanity_fwd.hpp" 43*b0d29bc4SBrooks Davis 44*b0d29bc4SBrooks Davis #include <cstddef> 45*b0d29bc4SBrooks Davis #include <string> 46*b0d29bc4SBrooks Davis 47*b0d29bc4SBrooks Davis #include "utils/defs.hpp" 48*b0d29bc4SBrooks Davis 49*b0d29bc4SBrooks Davis namespace utils { 50*b0d29bc4SBrooks Davis 51*b0d29bc4SBrooks Davis 52*b0d29bc4SBrooks Davis void sanity_failure(const assert_type, const char*, const size_t, 53*b0d29bc4SBrooks Davis const std::string&) UTILS_NORETURN; 54*b0d29bc4SBrooks Davis 55*b0d29bc4SBrooks Davis 56*b0d29bc4SBrooks Davis void install_crash_handlers(const std::string&); 57*b0d29bc4SBrooks Davis 58*b0d29bc4SBrooks Davis 59*b0d29bc4SBrooks Davis } // namespace utils 60*b0d29bc4SBrooks Davis 61*b0d29bc4SBrooks Davis 62*b0d29bc4SBrooks Davis /// \def _UTILS_ASSERT(type, expr, message) 63*b0d29bc4SBrooks Davis /// \brief Performs an assertion check. 64*b0d29bc4SBrooks Davis /// 65*b0d29bc4SBrooks Davis /// This macro is internal and should not be used directly. 66*b0d29bc4SBrooks Davis /// 67*b0d29bc4SBrooks Davis /// Ensures that the given expression expr is true and, if not, terminates 68*b0d29bc4SBrooks Davis /// execution by calling utils::sanity_failure(). The check is only performed 69*b0d29bc4SBrooks Davis /// in debug builds. 70*b0d29bc4SBrooks Davis /// 71*b0d29bc4SBrooks Davis /// \param type The assertion type as defined by assert_type. 72*b0d29bc4SBrooks Davis /// \param expr A boolean expression. 73*b0d29bc4SBrooks Davis /// \param message A string describing the nature of the error. 74*b0d29bc4SBrooks Davis #if !defined(NDEBUG) 75*b0d29bc4SBrooks Davis # define _UTILS_ASSERT(type, expr, message) \ 76*b0d29bc4SBrooks Davis do { \ 77*b0d29bc4SBrooks Davis if (!(expr)) \ 78*b0d29bc4SBrooks Davis utils::sanity_failure(type, __FILE__, __LINE__, message); \ 79*b0d29bc4SBrooks Davis } while (0) 80*b0d29bc4SBrooks Davis #else // defined(NDEBUG) 81*b0d29bc4SBrooks Davis # define _UTILS_ASSERT(type, expr, message) do {} while (0) 82*b0d29bc4SBrooks Davis #endif // !defined(NDEBUG) 83*b0d29bc4SBrooks Davis 84*b0d29bc4SBrooks Davis 85*b0d29bc4SBrooks Davis /// Ensures that an invariant holds. 86*b0d29bc4SBrooks Davis /// 87*b0d29bc4SBrooks Davis /// If the invariant does not hold, execution is immediately terminated. The 88*b0d29bc4SBrooks Davis /// check is only performed in debug builds. 89*b0d29bc4SBrooks Davis /// 90*b0d29bc4SBrooks Davis /// The error message printed by this macro is a textual representation of the 91*b0d29bc4SBrooks Davis /// boolean condition. If you want to provide a custom error message, use 92*b0d29bc4SBrooks Davis /// INV_MSG instead. 93*b0d29bc4SBrooks Davis /// 94*b0d29bc4SBrooks Davis /// \param expr A boolean expression describing the invariant. 95*b0d29bc4SBrooks Davis #define INV(expr) _UTILS_ASSERT(utils::invariant, expr, #expr) 96*b0d29bc4SBrooks Davis 97*b0d29bc4SBrooks Davis 98*b0d29bc4SBrooks Davis /// Ensures that an invariant holds using a custom error message. 99*b0d29bc4SBrooks Davis /// 100*b0d29bc4SBrooks Davis /// If the invariant does not hold, execution is immediately terminated. The 101*b0d29bc4SBrooks Davis /// check is only performed in debug builds. 102*b0d29bc4SBrooks Davis /// 103*b0d29bc4SBrooks Davis /// \param expr A boolean expression describing the invariant. 104*b0d29bc4SBrooks Davis /// \param msg The error message to print if the condition is false. 105*b0d29bc4SBrooks Davis #define INV_MSG(expr, msg) _UTILS_ASSERT(utils::invariant, expr, msg) 106*b0d29bc4SBrooks Davis 107*b0d29bc4SBrooks Davis 108*b0d29bc4SBrooks Davis /// Ensures that a precondition holds. 109*b0d29bc4SBrooks Davis /// 110*b0d29bc4SBrooks Davis /// If the precondition does not hold, execution is immediately terminated. The 111*b0d29bc4SBrooks Davis /// check is only performed in debug builds. 112*b0d29bc4SBrooks Davis /// 113*b0d29bc4SBrooks Davis /// The error message printed by this macro is a textual representation of the 114*b0d29bc4SBrooks Davis /// boolean condition. If you want to provide a custom error message, use 115*b0d29bc4SBrooks Davis /// PRE_MSG instead. 116*b0d29bc4SBrooks Davis /// 117*b0d29bc4SBrooks Davis /// \param expr A boolean expression describing the precondition. 118*b0d29bc4SBrooks Davis #define PRE(expr) _UTILS_ASSERT(utils::precondition, expr, #expr) 119*b0d29bc4SBrooks Davis 120*b0d29bc4SBrooks Davis 121*b0d29bc4SBrooks Davis /// Ensures that a precondition holds using a custom error message. 122*b0d29bc4SBrooks Davis /// 123*b0d29bc4SBrooks Davis /// If the precondition does not hold, execution is immediately terminated. The 124*b0d29bc4SBrooks Davis /// check is only performed in debug builds. 125*b0d29bc4SBrooks Davis /// 126*b0d29bc4SBrooks Davis /// \param expr A boolean expression describing the precondition. 127*b0d29bc4SBrooks Davis /// \param msg The error message to print if the condition is false. 128*b0d29bc4SBrooks Davis #define PRE_MSG(expr, msg) _UTILS_ASSERT(utils::precondition, expr, msg) 129*b0d29bc4SBrooks Davis 130*b0d29bc4SBrooks Davis 131*b0d29bc4SBrooks Davis /// Ensures that an postcondition holds. 132*b0d29bc4SBrooks Davis /// 133*b0d29bc4SBrooks Davis /// If the postcondition does not hold, execution is immediately terminated. 134*b0d29bc4SBrooks Davis /// The check is only performed in debug builds. 135*b0d29bc4SBrooks Davis /// 136*b0d29bc4SBrooks Davis /// The error message printed by this macro is a textual representation of the 137*b0d29bc4SBrooks Davis /// boolean condition. If you want to provide a custom error message, use 138*b0d29bc4SBrooks Davis /// POST_MSG instead. 139*b0d29bc4SBrooks Davis /// 140*b0d29bc4SBrooks Davis /// \param expr A boolean expression describing the postcondition. 141*b0d29bc4SBrooks Davis #define POST(expr) _UTILS_ASSERT(utils::postcondition, expr, #expr) 142*b0d29bc4SBrooks Davis 143*b0d29bc4SBrooks Davis 144*b0d29bc4SBrooks Davis /// Ensures that a postcondition holds using a custom error message. 145*b0d29bc4SBrooks Davis /// 146*b0d29bc4SBrooks Davis /// If the postcondition does not hold, execution is immediately terminated. 147*b0d29bc4SBrooks Davis /// The check is only performed in debug builds. 148*b0d29bc4SBrooks Davis /// 149*b0d29bc4SBrooks Davis /// \param expr A boolean expression describing the postcondition. 150*b0d29bc4SBrooks Davis /// \param msg The error message to print if the condition is false. 151*b0d29bc4SBrooks Davis #define POST_MSG(expr, msg) _UTILS_ASSERT(utils::postcondition, expr, msg) 152*b0d29bc4SBrooks Davis 153*b0d29bc4SBrooks Davis 154*b0d29bc4SBrooks Davis /// Ensures that a code path is not reached. 155*b0d29bc4SBrooks Davis /// 156*b0d29bc4SBrooks Davis /// If the code path in which this macro is located is reached, execution is 157*b0d29bc4SBrooks Davis /// immediately terminated. Given that such a condition is critical for the 158*b0d29bc4SBrooks Davis /// execution of the program (and to prevent build failures due to some code 159*b0d29bc4SBrooks Davis /// paths not initializing variables, for example), this condition is fatal both 160*b0d29bc4SBrooks Davis /// in debug and production builds. 161*b0d29bc4SBrooks Davis /// 162*b0d29bc4SBrooks Davis /// The error message printed by this macro is a textual representation of the 163*b0d29bc4SBrooks Davis /// boolean condition. If you want to provide a custom error message, use 164*b0d29bc4SBrooks Davis /// POST_MSG instead. 165*b0d29bc4SBrooks Davis #define UNREACHABLE UNREACHABLE_MSG("") 166*b0d29bc4SBrooks Davis 167*b0d29bc4SBrooks Davis 168*b0d29bc4SBrooks Davis /// Ensures that a code path is not reached using a custom error message. 169*b0d29bc4SBrooks Davis /// 170*b0d29bc4SBrooks Davis /// If the code path in which this macro is located is reached, execution is 171*b0d29bc4SBrooks Davis /// immediately terminated. Given that such a condition is critical for the 172*b0d29bc4SBrooks Davis /// execution of the program (and to prevent build failures due to some code 173*b0d29bc4SBrooks Davis /// paths not initializing variables, for example), this condition is fatal both 174*b0d29bc4SBrooks Davis /// in debug and production builds. 175*b0d29bc4SBrooks Davis /// 176*b0d29bc4SBrooks Davis /// \param msg The error message to print if the condition is false. 177*b0d29bc4SBrooks Davis #define UNREACHABLE_MSG(msg) \ 178*b0d29bc4SBrooks Davis do { \ 179*b0d29bc4SBrooks Davis utils::sanity_failure(utils::unreachable, __FILE__, __LINE__, msg); \ 180*b0d29bc4SBrooks Davis } while (0) 181*b0d29bc4SBrooks Davis 182*b0d29bc4SBrooks Davis 183*b0d29bc4SBrooks Davis #endif // !defined(UTILS_SANITY_HPP) 184