summaryrefslogtreecommitdiffstats
path: root/src/util/assert.h
blob: 0983e03e9d0ccde0439f2e947338c836bf87f739 (plain)
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
#pragma once

#include <QtDebug>


static constexpr const char* kDebugAssertPrefix = "DEBUG ASSERT";

inline void mixxx_noop(void) {}

inline void mixxx_debug_assert(const char* assertion, const char* file, int line, const char* function) {
    qCritical("%s: \"%s\" in function %s at %s:%d", kDebugAssertPrefix, assertion, function, file, line);
}

inline bool mixxx_maybe_debug_assert_return_true(const char* assertion, const char* file, int line, const char* function) {
#ifdef MIXXX_DEBUG_ASSERTIONS_ENABLED
    mixxx_debug_assert(assertion, file, line, function);
#else
    Q_UNUSED(assertion);
    Q_UNUSED(file);
    Q_UNUSED(line);
    Q_UNUSED(function);
#endif
    return true;
}

inline void mixxx_release_assert(const char* assertion, const char* file, int line, const char* function) {
    qFatal("ASSERT: \"%s\" in function %s at %s:%d", assertion, function, file, line);
}

// These macros provide the demangled function name (including helpful template
// type information) and are supported on every version of GCC, Clang, and MSVC
// that Mixxx supports.
#if defined(_MSC_VER)
#define ASSERT_FUNCTION __FUNCSIG__
#else
#define ASSERT_FUNCTION __PRETTY_FUNCTION__
#endif

/// If cond is false, produces a fatal assertion and quits ungracefully. Think
/// very hard before using this -- this should only be for the most dire of
/// situations where we know Mixxx cannot take any action without potentially
/// corrupting user data. Handle errors gracefully whenever possible.
#define RELEASE_ASSERT(cond) ((!(cond)) ? mixxx_release_assert(#cond, __FILE__, __LINE__, ASSERT_FUNCTION) : mixxx_noop())

// Checks that cond is true in debug builds. If cond is false then prints a
// warning message to the console. If Mixxx is built with
// MIXXX_DEBUG_ASSERTIONS_FATAL then the warning message is fatal. Compiles
// to nothing in release builds.
//
// Be careful of the common mistake with assertions:
//   DEBUG_ASSERT(doSomething());
//
// In release builds, doSomething() is never called!
#ifdef MIXXX_DEBUG_ASSERTIONS_ENABLED
#define DEBUG_ASSERT(cond) ((!(cond)) ? mixxx_debug_assert(#cond, __FILE__, __LINE__, ASSERT_FUNCTION) : mixxx_noop())
#else
#define DEBUG_ASSERT(cond)
#endif

/// Same as DEBUG_ASSERT, but if MIXXX_DEBUG_ASSERTIONS_FATAL is disabled run the specified fallback function.
/// In most cases you should probably use this rather than DEBUG_ASSERT. Only use DEBUG_ASSERT if there is no appropriate fallback.
#define VERIFY_OR_DEBUG_ASSERT(cond) if ((!(cond)) && mixxx_maybe_debug_assert_return_true(#cond, __FILE__, __LINE__, ASSERT_FUNCTION))