Coverage Report

Created: 2025-06-13 06:30

/src/wxwidgets/include/wx/debug.h
Line
Count
Source (jump to first uncovered line)
1
/////////////////////////////////////////////////////////////////////////////
2
// Name:        wx/debug.h
3
// Purpose:     Misc debug functions and macros
4
// Author:      Vadim Zeitlin
5
// Created:     29/01/98
6
// Copyright:   (c) 1998-2009 Vadim Zeitlin <vadim@wxwidgets.org>
7
// Licence:     wxWindows licence
8
/////////////////////////////////////////////////////////////////////////////
9
10
#ifndef _WX_DEBUG_H_
11
#define _WX_DEBUG_H_
12
13
#include  <assert.h>
14
15
#include <limits.h>          // for CHAR_BIT used below
16
17
#include "wx/chartype.h"     // for __TFILE__ and wxChar
18
#include "wx/cpp.h"          // for wxSTATEMENT_MACRO_BEGIN etc
19
#include "wx/dlimpexp.h"     // for WXDLLIMPEXP_FWD_BASE
20
21
class WXDLLIMPEXP_FWD_BASE wxString;
22
class WXDLLIMPEXP_FWD_BASE wxCStrData;
23
24
// ----------------------------------------------------------------------------
25
// Defines controlling the debugging macros
26
// ----------------------------------------------------------------------------
27
28
/*
29
    wxWidgets can be built with several different levels of debug support
30
    specified by the value of wxDEBUG_LEVEL constant:
31
32
    0:  No assertion macros at all, this should only be used when optimizing
33
        for resource-constrained systems (typically embedded ones).
34
    1:  Default level, most of the assertions are enabled.
35
    2:  Maximal (at least for now): asserts which are "expensive"
36
        (performance-wise) or only make sense for finding errors in wxWidgets
37
        itself, as opposed to bugs in applications using it, are also enabled.
38
 */
39
40
// unless wxDEBUG_LEVEL is predefined (by configure or via wx/setup.h under
41
// Windows), use the default
42
#if !defined(wxDEBUG_LEVEL)
43
0
    #define wxDEBUG_LEVEL 1
44
#endif // !defined(wxDEBUG_LEVEL)
45
46
/*
47
    __WXDEBUG__ is defined when wxDEBUG_LEVEL != 0. This is done mostly for
48
    compatibility but it also provides a simpler way to check if asserts and
49
    debug logging is enabled at all.
50
 */
51
#if wxDEBUG_LEVEL > 0
52
    #ifndef __WXDEBUG__
53
        #define __WXDEBUG__
54
    #endif
55
#else
56
    #undef __WXDEBUG__
57
#endif
58
59
// Finally there is also a very old WXDEBUG macro not used anywhere at all, it
60
// is only defined for compatibility.
61
#ifdef __WXDEBUG__
62
    #if !defined(WXDEBUG) || !WXDEBUG
63
        #undef WXDEBUG
64
        #define WXDEBUG 1
65
    #endif // !WXDEBUG
66
#endif // __WXDEBUG__
67
68
// ----------------------------------------------------------------------------
69
// Handling assertion failures
70
// ----------------------------------------------------------------------------
71
72
/*
73
    Type for the function called in case of assert failure, see
74
    wxSetAssertHandler().
75
 */
76
typedef void (*wxAssertHandler_t)(const wxString& file,
77
                                  int line,
78
                                  const wxString& func,
79
                                  const wxString& cond,
80
                                  const wxString& msg);
81
82
#if wxDEBUG_LEVEL
83
84
// the global assert handler function, if it is null asserts don't check their
85
// conditions
86
extern WXDLLIMPEXP_DATA_BASE(wxAssertHandler_t) wxTheAssertHandler;
87
88
/*
89
    Sets the function to be called in case of assertion failure.
90
91
    The default assert handler forwards to wxApp::OnAssertFailure() whose
92
    default behaviour is, in turn, to show the standard assertion failure
93
    dialog if a wxApp object exists or shows the same dialog itself directly
94
    otherwise.
95
96
    While usually it is enough -- and more convenient -- to just override
97
    OnAssertFailure(), to handle all assertion failures, including those
98
    occurring even before wxApp object creation or after its destruction you
99
    need to provide your assertion handler function.
100
101
    This function also provides a simple way to disable all asserts: simply
102
    pass null pointer to it. Doing this will result in not even evaluating
103
    assert conditions at all, avoiding almost all run-time cost of asserts.
104
105
    Notice that this function is not MT-safe, so you should call it before
106
    starting any other threads.
107
108
    The return value of this function is the previous assertion handler. It can
109
    be called after any pre-processing by your handler and can also be restored
110
    later if you uninstall your handler.
111
 */
112
inline wxAssertHandler_t wxSetAssertHandler(wxAssertHandler_t handler)
113
2
{
114
2
    const wxAssertHandler_t old = wxTheAssertHandler;
115
2
    wxTheAssertHandler = handler;
116
2
    return old;
117
2
}
118
119
/*
120
    Reset the default assert handler.
121
122
    This may be used to enable asserts, which are disabled by default in this
123
    case, for programs built in release build (NDEBUG defined).
124
 */
125
extern void WXDLLIMPEXP_BASE wxSetDefaultAssertHandler();
126
127
#else // !wxDEBUG_LEVEL
128
129
// provide empty stubs in case assertions are completely disabled
130
//
131
// NB: can't use WXUNUSED() here as we're included from wx/defs.h before it is
132
//     defined
133
inline wxAssertHandler_t wxSetAssertHandler(wxAssertHandler_t /* handler */)
134
{
135
    return nullptr;
136
}
137
138
inline void wxSetDefaultAssertHandler() { }
139
140
#endif // wxDEBUG_LEVEL/!wxDEBUG_LEVEL
141
142
// simply a synonym for wxSetAssertHandler(nullptr)
143
0
inline void wxDisableAsserts() { wxSetAssertHandler(nullptr); }
144
145
/*
146
    A macro which disables asserts for applications compiled in release build.
147
148
    By default, wxIMPLEMENT_APP (or rather wxIMPLEMENT_WXWIN_MAIN) disable the
149
    asserts in the applications compiled in the release build by calling this.
150
    It does nothing if NDEBUG is not defined.
151
 */
152
#ifdef NDEBUG
153
    #define wxDISABLE_ASSERTS_IN_RELEASE_BUILD() wxDisableAsserts()
154
#else
155
    #define wxDISABLE_ASSERTS_IN_RELEASE_BUILD()
156
#endif
157
158
#if wxDEBUG_LEVEL
159
160
/*
161
    wxOnAssert() is used by the debugging macros defined below. Different
162
    overloads are needed because these macros can be used with or without wxT().
163
164
    All of them are implemented in src/common/appcmn.cpp and unconditionally
165
    call wxTheAssertHandler so the caller must check that it is non-null
166
    (assert macros do it).
167
 */
168
169
// these overloads are the ones typically used by debugging macros: we have to
170
// provide wxChar* msg version because it's common to use wxT() in the macros
171
// and finally, we can't use const wx(char)* msg = nullptr, because that would
172
// be ambiguous
173
//
174
// also notice that these functions can't be inline as wxString is not defined
175
// yet (and can't be as wxString code itself may use assertions)
176
extern WXDLLIMPEXP_BASE void wxOnAssert(const char *file,
177
                                        int line,
178
                                        const char *func,
179
                                        const char *cond);
180
181
extern WXDLLIMPEXP_BASE void wxOnAssert(const char *file,
182
                                        int line,
183
                                        const char *func,
184
                                        const char *cond,
185
                                        const char *msg);
186
187
extern WXDLLIMPEXP_BASE void wxOnAssert(const char *file,
188
                                        int line,
189
                                        const char *func,
190
                                        const char *cond,
191
                                        const wxChar *msg) ;
192
193
// these overloads work when msg passed to debug macro is a string and we
194
// also have to provide wxCStrData overload to resolve ambiguity which would
195
// otherwise arise from wxASSERT( s.c_str() )
196
extern WXDLLIMPEXP_BASE void wxOnAssert(const wxString& file,
197
                                        int line,
198
                                        const wxString& func,
199
                                        const wxString& cond,
200
                                        const wxString& msg);
201
202
extern WXDLLIMPEXP_BASE void wxOnAssert(const wxString& file,
203
                                        int line,
204
                                        const wxString& func,
205
                                        const wxString& cond);
206
207
extern WXDLLIMPEXP_BASE void wxOnAssert(const char *file,
208
                                        int line,
209
                                        const char *func,
210
                                        const char *cond,
211
                                        const wxCStrData& msg);
212
213
extern WXDLLIMPEXP_BASE void wxOnAssert(const char *file,
214
                                        int line,
215
                                        const char *func,
216
                                        const char *cond,
217
                                        const wxString& msg);
218
219
#endif // wxDEBUG_LEVEL
220
221
222
// ----------------------------------------------------------------------------
223
// Debugging macros
224
// ----------------------------------------------------------------------------
225
226
/*
227
    Assertion macros: check if the condition is true and call assert handler
228
    (which will by default notify the user about failure) if it isn't.
229
230
    wxASSERT and wxFAIL macros as well as wxTrap() function do nothing at all
231
    if wxDEBUG_LEVEL is 0 however they do check their conditions at default
232
    debug level 1, unlike the previous wxWidgets versions.
233
234
    wxASSERT_LEVEL_2 is meant to be used for "expensive" asserts which should
235
    normally be disabled because they have a big impact on performance and so
236
    this macro only does anything if wxDEBUG_LEVEL >= 2.
237
 */
238
#if wxDEBUG_LEVEL
239
    // wxTrap() can be used to break into the debugger unconditionally
240
    // (assuming the program is running under debugger, of course).
241
    //
242
    // If possible, we prefer to define it as a macro rather than as a function
243
    // to open the debugger at the position where we trapped and not inside the
244
    // trap function itself which is not very useful.
245
    #ifdef __VISUALC__
246
        #define wxTrap() __debugbreak()
247
    #elif defined(__GNUC__)
248
        #if defined(__i386) || defined(__x86_64)
249
0
            #define wxTrap() asm volatile ("int $3")
250
        #endif
251
    #endif
252
253
    #ifndef wxTrap
254
        // For all the other cases, use a generic function.
255
        extern WXDLLIMPEXP_BASE void wxTrap();
256
    #endif
257
258
    // Global flag used to indicate that assert macros should call wxTrap(): it
259
    // is set by the default assert handler if the user answers yes to the
260
    // question of whether to trap.
261
    extern WXDLLIMPEXP_DATA_BASE(bool) wxTrapInAssert;
262
263
    // This macro checks if the condition is true and calls the assert handler
264
    // with the provided message if it isn't and finally traps if the special
265
    // flag indicating that it should do it was set by the handler.
266
    //
267
    // Notice that we don't use the handler return value for compatibility
268
    // reasons (if we changed its return type, we'd need to change wxApp::
269
    // OnAssertFailure() too which would break user code overriding it), hence
270
    // the need for the ugly global flag.
271
    #define wxASSERT_MSG_AT(cond, msg, file, line, func)                      \
272
72.2k
        wxSTATEMENT_MACRO_BEGIN                                               \
273
72.2k
            if ( cond )                                                       \
274
72.2k
            {                                                                 \
275
72.2k
            }                                                                 \
276
72.2k
            else if ( wxTheAssertHandler &&                                   \
277
0
                    (wxOnAssert(file, line, func, #cond, msg),                \
278
0
                     wxTrapInAssert) )                                        \
279
0
            {                                                                 \
280
0
                wxTrapInAssert = false;                                       \
281
0
                wxTrap();                                                     \
282
0
            }                                                                 \
283
72.2k
        wxSTATEMENT_MACRO_END
284
285
    // A version asserting at the current location.
286
    #define wxASSERT_MSG(cond, msg) \
287
72.2k
        wxASSERT_MSG_AT(cond, msg, __FILE__, __LINE__, __func__)
288
289
    // a version without any additional message, don't use unless condition
290
    // itself is fully self-explanatory
291
2.82k
    #define wxASSERT(cond) wxASSERT_MSG(cond, (const char*)nullptr)
292
293
    // wxFAIL is a special form of assert: it always triggers (and so is
294
    // usually used in normally unreachable code)
295
    #define wxFAIL_COND_MSG_AT(cond, msg, file, line, func)                   \
296
0
        wxSTATEMENT_MACRO_BEGIN                                               \
297
0
            if ( wxTheAssertHandler &&                                        \
298
0
                    (wxOnAssert(file, line, func, cond, msg),                 \
299
0
                     wxTrapInAssert) )                                        \
300
0
            {                                                                 \
301
0
                wxTrapInAssert = false;                                       \
302
0
                wxTrap();                                                     \
303
0
            }                                                                 \
304
0
        wxSTATEMENT_MACRO_END
305
306
    #define wxFAIL_MSG_AT(msg, file, line, func) \
307
        wxFAIL_COND_MSG_AT("Assert failure", msg, file, line, func)
308
309
    #define wxFAIL_COND_MSG(cond, msg) \
310
0
        wxFAIL_COND_MSG_AT(cond, msg, __FILE__, __LINE__, __func__)
311
312
0
    #define wxFAIL_MSG(msg) wxFAIL_COND_MSG("Assert failure", msg)
313
0
    #define wxFAIL wxFAIL_MSG((const char*)nullptr)
314
#else // !wxDEBUG_LEVEL
315
    #define wxTrap()
316
317
    #define wxASSERT(cond)
318
    #define wxASSERT_MSG(cond, msg)
319
    #define wxFAIL
320
    #define wxFAIL_MSG(msg)
321
    #define wxFAIL_COND_MSG(cond, msg)
322
    #define wxFAIL_MSG_AT(msg, file, line, func)
323
    #define wxFAIL_COND_MSG_AT(cond, msg, file, line, func)
324
#endif  // wxDEBUG_LEVEL
325
326
#if wxDEBUG_LEVEL >= 2
327
    #define wxASSERT_LEVEL_2_MSG(cond, msg) wxASSERT_MSG(cond, msg)
328
    #define wxASSERT_LEVEL_2(cond) wxASSERT(cond)
329
#else // wxDEBUG_LEVEL < 2
330
    #define wxASSERT_LEVEL_2_MSG(cond, msg)
331
    #define wxASSERT_LEVEL_2(cond)
332
#endif
333
334
// This is simply a wrapper for the standard abort() which is not available
335
// under all platforms.
336
//
337
// It isn't really debug-related but there doesn't seem to be any better place
338
// for it, so declare it here and define it in appbase.cpp, together with
339
// wxTrap().
340
extern void WXDLLIMPEXP_BASE wxAbort();
341
342
/*
343
    wxCHECK macros always check their conditions, setting debug level to 0 only
344
    makes them silent in case of failure, otherwise -- including at default
345
    debug level 1 -- they call the assert handler if the condition is false
346
347
    They are supposed to be used only in invalid situation: for example, an
348
    invalid parameter (e.g. a null pointer) is passed to a function. Instead of
349
    dereferencing it and causing core dump the function might use
350
351
        wxCHECK_RET( p != nullptr, "pointer can't be null" )
352
*/
353
354
// the generic macro: takes the condition to check, the statement to be executed
355
// in case the condition is false and the message to pass to the assert handler
356
#define wxCHECK2_MSG(cond, op, msg)                                       \
357
1.34M
    if ( cond )                                                           \
358
1.34M
    {}                                                                    \
359
1.34M
    else                                                                  \
360
1.34M
    {                                                                     \
361
0
        wxFAIL_COND_MSG(#cond, msg);                                      \
362
0
        op;                                                               \
363
0
    }                                                                     \
364
1.34M
    struct wxMAKE_UNIQUE_NAME(wxDummyCheckStruct) /* to force a semicolon */
365
366
// check which returns with the specified return code if the condition fails
367
385k
#define wxCHECK_MSG(cond, rc, msg)   wxCHECK2_MSG(cond, return rc, msg)
368
369
// check that expression is true, "return" if not (also FAILs in debug mode)
370
18.7k
#define wxCHECK(cond, rc)            wxCHECK_MSG(cond, rc, (const char*)nullptr)
371
372
// check that expression is true, perform op if not
373
#define wxCHECK2(cond, op)           wxCHECK2_MSG(cond, op, (const char*)nullptr)
374
375
// special form of wxCHECK2: as wxCHECK, but for use in void functions
376
//
377
// NB: there is only one form (with msg parameter) and it's intentional:
378
//     there is no other way to tell the caller what exactly went wrong
379
//     from the void function (of course, the function shouldn't be void
380
//     to begin with...)
381
963k
#define wxCHECK_RET(cond, msg)       wxCHECK2_MSG(cond, return, msg)
382
383
384
// ----------------------------------------------------------------------------
385
// Compile time asserts
386
//
387
// Unlike the normal assert and related macros above which are checked during
388
// the program run-time the macros below will result in a compilation error if
389
// the condition they check is false. This is usually used to check the
390
// expressions containing sizeof()s which cannot be tested with the
391
// preprocessor. If you can use the #if's, do use them as you can give a more
392
// detailed error message then.
393
// ----------------------------------------------------------------------------
394
395
/*
396
  How this works (you don't have to understand it to be able to use the
397
  macros): we rely on the fact that it is invalid to define a named bit field
398
  in a struct of width 0. All the rest are just the hacks to minimize the
399
  possibility of the compiler warnings when compiling this macro: in
400
  particular, this is why we define a struct and not an object (which would
401
  result in a warning about unused variable) and a named struct (otherwise we'd
402
  get a warning about an unnamed struct not used to define an object!).
403
 */
404
405
#define wxMAKE_UNIQUE_ASSERT_NAME           wxMAKE_UNIQUE_NAME(wxAssert_)
406
407
/*
408
  The second argument of this macro must be a valid C++ identifier and not a
409
  string. I.e. you should use it like this:
410
411
    wxCOMPILE_TIME_ASSERT( sizeof(int) >= 2, YourIntsAreTooSmall );
412
413
 It may be used both within a function and in the global scope.
414
*/
415
#if defined( __VMS )
416
namespace wxdebug{
417
418
// HP aCC cannot deal with missing names for template value parameters
419
template <bool x> struct STATIC_ASSERTION_FAILURE;
420
421
template <> struct STATIC_ASSERTION_FAILURE<true> { enum { value = 1 }; };
422
423
// HP aCC cannot deal with missing names for template value parameters
424
template<int x> struct static_assert_test{};
425
426
}
427
    #define WX_JOIN( X, Y ) X##Y
428
    #define WX_STATIC_ASSERT_BOOL_CAST(x) (bool)(x)
429
    #define wxCOMPILE_TIME_ASSERT(expr, msg) \
430
       typedef ::wxdebug::static_assert_test<\
431
          sizeof(::wxdebug::STATIC_ASSERTION_FAILURE< WX_STATIC_ASSERT_BOOL_CAST( expr ) >)>\
432
            WX_JOIN(wx_static_assert_typedef_, __LINE__)
433
#else
434
    #define wxCOMPILE_TIME_ASSERT(expr, msg) \
435
0
        struct wxMAKE_UNIQUE_ASSERT_NAME { unsigned int msg: expr; }
436
#endif
437
438
/*
439
   When using VC++ 6 with "Edit and Continue" on, the compiler completely
440
   mishandles __LINE__ and so wxCOMPILE_TIME_ASSERT() doesn't work, provide a
441
   way to make "unique" assert names by specifying a unique prefix explicitly
442
 */
443
#define wxMAKE_UNIQUE_ASSERT_NAME2(text) wxCONCAT(wxAssert_, text)
444
445
#define wxCOMPILE_TIME_ASSERT2(expr, msg, text) \
446
    struct wxMAKE_UNIQUE_ASSERT_NAME2(text) { unsigned int msg: expr; }
447
448
// helpers for wxCOMPILE_TIME_ASSERT below, for private use only
449
#define wxMAKE_BITSIZE_MSG(type, size) type ## SmallerThan ## size ## Bits
450
451
// a special case of compile time assert: check that the size of the given type
452
// is at least the given number of bits
453
#define wxASSERT_MIN_BITSIZE(type, size) \
454
    wxCOMPILE_TIME_ASSERT(sizeof(type) * CHAR_BIT >= size, \
455
                          wxMAKE_BITSIZE_MSG(type, size))
456
457
458
// ----------------------------------------------------------------------------
459
// other miscellaneous debugger-related functions
460
// ----------------------------------------------------------------------------
461
462
/*
463
    Return true if we're running under debugger.
464
465
    Currently only really works under Win32 and just returns false elsewhere.
466
 */
467
#if defined(__WIN32__)
468
    extern bool WXDLLIMPEXP_BASE wxIsDebuggerRunning();
469
#else // !Mac
470
0
    inline bool wxIsDebuggerRunning() { return false; }
471
#endif // Mac/!Mac
472
473
// An assert helper used to avoid warning when testing constant expressions,
474
// i.e. wxASSERT( sizeof(int) == 4 ) can generate a compiler warning about
475
// expression being always true, but not using
476
// wxASSERT( wxAssertIsEqual(sizeof(int), 4) )
477
//
478
// NB: this is made obsolete by wxCOMPILE_TIME_ASSERT() and should no
479
//     longer be used.
480
extern bool WXDLLIMPEXP_BASE wxAssertIsEqual(int x, int y);
481
482
// Use of wxFalse instead of false suppresses compiler warnings about testing
483
// constant expression
484
extern WXDLLIMPEXP_DATA_BASE(const bool) wxFalse;
485
486
#define wxAssertFailure wxFalse
487
488
// This is similar to WXUNUSED() and useful for parameters which are only used
489
// in assertions.
490
#if wxDEBUG_LEVEL
491
    #define WXUNUSED_UNLESS_DEBUG(param)  param
492
#else
493
    #define WXUNUSED_UNLESS_DEBUG(param)  WXUNUSED(param)
494
#endif
495
496
497
#endif // _WX_DEBUG_H_