aboutsummaryrefslogtreecommitdiffstats
path: root/util/system/yassert.h
blob: c6c8b8349b0f7b320f3ce6875c2b843f155b34f0 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#pragma once

#include "defaults.h"
#include "src_root.h"
#include "backtrace.h"

#if defined(_MSC_VER)
    #include <new>
    #if defined(_DEBUG)
        #if defined(_CRTDBG_MAP_ALLOC)
            #include <cstdlib>  /* definitions for malloc/calloc */
            #include <malloc.h> /* must be before their redefinitions as _*_dbg() */
        #endif
        #include <crtdbg.h>
    #else
    #endif
    #include <cassert>
#elif defined(__GNUC__)
    #ifdef _sun_
        #include <alloca.h>
    #endif
    #include <cassert>
#endif

#if !defined(_MSC_VER)
    #if defined(__has_builtin) && __has_builtin(__debugbreak)
    // Do nothing, use __debugbreak builtin
    #elif defined(__has_builtin) && __has_builtin(__builtin_debugtrap)
inline void __debugbreak() {
    __builtin_debugtrap();
}
    #else
inline void __debugbreak() {
        #if defined(__x86_64__) || defined(__i386__)
    __asm__ volatile("int $3\n");
        #else
    assert(0);
        #endif
}
    #endif

inline bool YaIsDebuggerPresent() {
    return false;
}
#else
// __debugbreak is intrinsic in MSVC

extern "C" {
    __declspec(dllimport) int __stdcall IsDebuggerPresent();
}

inline bool YaIsDebuggerPresent() {
    return IsDebuggerPresent() != 0;
}
#endif

inline void YaDebugBreak() {
    __debugbreak();
}

#undef Y_ASSERT

#if !defined(NDEBUG) && !defined(__GCCXML__)
    #define Y_ASSERT(a)                                         \
        do {                                                    \
            try {                                               \
                if (Y_UNLIKELY(!(a))) {                         \
                    if (YaIsDebuggerPresent())                  \
                        __debugbreak();                         \
                    else {                                      \
                        PrintBackTrace();                       \
                        /* NOLINTNEXTLINE */                    \
                        assert(false && (a));                   \
                    }                                           \
                }                                               \
            } catch (...) {                                     \
                if (YaIsDebuggerPresent())                      \
                    __debugbreak();                             \
                else {                                          \
                    PrintBackTrace();                           \
                    /* NOLINTNEXTLINE */                        \
                    assert(false && "Exception during assert"); \
                }                                               \
            }                                                   \
        } while (false)
#else
    #define Y_ASSERT(a)                            \
        do {                                       \
            if (false) {                           \
                auto __xxx = static_cast<bool>(a); \
                Y_UNUSED(__xxx);                   \
            }                                      \
        } while (false)
#endif

namespace NPrivate {
    /// method should not be used directly
    [[noreturn]] void Panic(const TStaticBuf& file, int line, const char* function, const char* expr, const char* format, ...) noexcept Y_PRINTF_FORMAT(5, 6);
}

/// Assert that does not depend on NDEBUG macro and outputs message like printf
#define Y_VERIFY(expr, ...)                                                                          \
    do {                                                                                             \
        if (Y_UNLIKELY(!(expr))) {                                                                   \
            ::NPrivate::Panic(__SOURCE_FILE_IMPL__, __LINE__, __FUNCTION__, #expr, " " __VA_ARGS__); \
        }                                                                                            \
    } while (false)

#define Y_FAIL(...)                                                                                \
    do {                                                                                           \
        ::NPrivate::Panic(__SOURCE_FILE_IMPL__, __LINE__, __FUNCTION__, nullptr, " " __VA_ARGS__); \
    } while (false)

#ifndef NDEBUG
    /// Assert that depend on NDEBUG macro and outputs message like printf
    #define Y_VERIFY_DEBUG(expr, ...)                                                                    \
        do {                                                                                             \
            if (Y_UNLIKELY(!(expr))) {                                                                   \
                ::NPrivate::Panic(__SOURCE_FILE_IMPL__, __LINE__, __FUNCTION__, #expr, " " __VA_ARGS__); \
            }                                                                                            \
        } while (false)
#else
    #define Y_VERIFY_DEBUG(expr, ...)                 \
        do {                                          \
            if (false) {                              \
                bool __xxx = static_cast<bool>(expr); \
                Y_UNUSED(__xxx);                      \
            }                                         \
        } while (false)
#endif