X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/cf5861623960de7d066a4532ea005b6897fa82ee..438959cca892a7651634cc3a7aad4819ac49b23c:/include/wx/debug.h diff --git a/include/wx/debug.h b/include/wx/debug.h index 593af341d7..35c7ca1222 100644 --- a/include/wx/debug.h +++ b/include/wx/debug.h @@ -11,7 +11,7 @@ #ifndef _WX_DEBUG_H_ #define _WX_DEBUG_H_ -#if !defined(__WXPALMOS5__) && !defined(__WXWINCE__) +#if !defined(__WXWINCE__) #include #endif // systems without assert.h @@ -19,6 +19,7 @@ #include "wx/chartype.h" // for __TFILE__ and wxChar #include "wx/cpp.h" // for __WXFUNCTION__ +#include "wx/dlimpexp.h" // for WXDLLIMPEXP_FWD_BASE class WXDLLIMPEXP_FWD_BASE wxString; class WXDLLIMPEXP_FWD_BASE wxCStrData; @@ -37,28 +38,29 @@ class WXDLLIMPEXP_FWD_BASE wxCStrData; 2: Maximal (at least for now): asserts which are "expensive" (performance-wise) or only make sense for finding errors in wxWidgets itself, as opposed to bugs in applications using it, are also enabled. - - For compatibility reasons, currently wxDEBUG_LEVEL is defined if - __WXDEBUG__ is defined but in the near future (2.9.1) the role of the flags - will change and wxDEBUG_LEVEL will be the primary value with __WXDEBUG__ - only used for compatibility. */ -// if _DEBUG is defined (MS VC++ and others use it in debug builds), define -// __WXDEBUG__ too -#ifdef _DEBUG +// unless wxDEBUG_LEVEL is predefined (by configure or via wx/setup.h under +// Windows), use the default +#if !defined(wxDEBUG_LEVEL) + #define wxDEBUG_LEVEL 1 +#endif // !defined(wxDEBUG_LEVEL) + +/* + __WXDEBUG__ is defined when wxDEBUG_LEVEL != 0. This is done mostly for + compatibility but it also provides a simpler way to check if asserts and + debug logging is enabled at all. + */ +#if wxDEBUG_LEVEL > 0 #ifndef __WXDEBUG__ #define __WXDEBUG__ - #endif // !__WXDEBUG__ -#endif // _DEBUG - -// if NDEBUG is defined ( uses it), undef __WXDEBUG__ and WXDEBUG -#ifdef NDEBUG + #endif +#else #undef __WXDEBUG__ - #undef WXDEBUG -#endif // NDEBUG +#endif -// if __WXDEBUG__ is defined, make sure that WXDEBUG is defined and >= 1 +// Finally there is also a very old WXDEBUG macro not used anywhere at all, it +// is only defined for compatibility. #ifdef __WXDEBUG__ #if !defined(WXDEBUG) || !WXDEBUG #undef WXDEBUG @@ -66,15 +68,6 @@ class WXDLLIMPEXP_FWD_BASE wxCStrData; #endif // !WXDEBUG #endif // __WXDEBUG__ -// temporarily define wxDEBUG_LEVEL as function of __WXDEBUG__ -#if !defined(wxDEBUG_LEVEL) - #ifdef __WXDEBUG__ - #define wxDEBUG_LEVEL 1 - #else - #define wxDEBUG_LEVEL 0 - #endif -#endif // !defined(wxDEBUG_LEVEL) - // ---------------------------------------------------------------------------- // Handling assertion failures // ---------------------------------------------------------------------------- @@ -126,6 +119,14 @@ inline wxAssertHandler_t wxSetAssertHandler(wxAssertHandler_t handler) return old; } +/* + Reset the default assert handler. + + This may be used to enable asserts, which are disabled by default in this + case, for programs built in release build (NDEBUG defined). + */ +extern void WXDLLIMPEXP_BASE wxSetDefaultAssertHandler(); + #else // !wxDEBUG_LEVEL // provide empty stubs in case assertions are completely disabled @@ -137,16 +138,31 @@ inline wxAssertHandler_t wxSetAssertHandler(wxAssertHandler_t /* handler */) return NULL; } +inline void wxSetDefaultAssertHandler() { } + #endif // wxDEBUG_LEVEL/!wxDEBUG_LEVEL // simply a synonym for wxSetAssertHandler(NULL) inline void wxDisableAsserts() { wxSetAssertHandler(NULL); } +/* + A macro which disables asserts for applications compiled in release build. + + By default, wxIMPLEMENT_APP (or rather wxIMPLEMENT_WXWIN_MAIN) disable the + asserts in the applications compiled in the release build by calling this. + It does nothing if NDEBUG is not defined. + */ +#ifdef NDEBUG + #define wxDISABLE_ASSERTS_IN_RELEASE_BUILD() wxDisableAsserts() +#else + #define wxDISABLE_ASSERTS_IN_RELEASE_BUILD() +#endif + #if wxDEBUG_LEVEL /* wxOnAssert() is used by the debugging macros defined below. Different - overloads are needed because these macros can be used with or without _T(). + overloads are needed because these macros can be used with or without wxT(). All of them are implemented in src/common/appcmn.cpp and unconditionally call wxTheAssertHandler so the caller must check that it is non-NULL @@ -156,34 +172,34 @@ inline void wxDisableAsserts() { wxSetAssertHandler(NULL); } #if wxUSE_UNICODE // these overloads are the ones typically used by debugging macros: we have to -// provide wxChar* msg version because it's common to use _T() in the macros +// provide wxChar* msg version because it's common to use wxT() in the macros // and finally, we can't use const wx(char)* msg = NULL, because that would // be ambiguous // // also notice that these functions can't be inline as wxString is not defined // yet (and can't be as wxString code itself may use assertions) -extern void WXDLLIMPEXP_BASE wxOnAssert(const char *file, +extern WXDLLIMPEXP_BASE void wxOnAssert(const char *file, int line, const char *func, const char *cond); -extern void WXDLLIMPEXP_BASE wxOnAssert(const char *file, +extern WXDLLIMPEXP_BASE void wxOnAssert(const char *file, int line, const char *func, const char *cond, const char *msg); -extern void WXDLLIMPEXP_BASE wxOnAssert(const char *file, +extern WXDLLIMPEXP_BASE void wxOnAssert(const char *file, int line, const char *func, const char *cond, - const wxChar *msg); + const wxChar *msg) ; #endif /* wxUSE_UNICODE */ // this version is for compatibility with wx 2.8 Unicode build only, we don't // use it ourselves any more except in ANSI-only build in which case it is all // we need -extern void WXDLLIMPEXP_BASE wxOnAssert(const wxChar *file, +extern WXDLLIMPEXP_BASE void wxOnAssert(const wxChar *file, int line, const char *func, const wxChar *cond, @@ -192,24 +208,24 @@ extern void WXDLLIMPEXP_BASE wxOnAssert(const wxChar *file, // these overloads work when msg passed to debug macro is a string and we // also have to provide wxCStrData overload to resolve ambiguity which would // otherwise arise from wxASSERT( s.c_str() ) -extern void WXDLLIMPEXP_BASE wxOnAssert(const wxString& file, +extern WXDLLIMPEXP_BASE void wxOnAssert(const wxString& file, int line, const wxString& func, const wxString& cond, const wxString& msg); -extern void WXDLLIMPEXP_BASE wxOnAssert(const wxString& file, +extern WXDLLIMPEXP_BASE void wxOnAssert(const wxString& file, int line, const wxString& func, const wxString& cond); -extern void WXDLLIMPEXP_BASE wxOnAssert(const char *file, +extern WXDLLIMPEXP_BASE void wxOnAssert(const char *file, int line, const char *func, const char *cond, const wxCStrData& msg); -extern void WXDLLIMPEXP_BASE wxOnAssert(const char *file, +extern WXDLLIMPEXP_BASE void wxOnAssert(const char *file, int line, const char *func, const char *cond, @@ -235,22 +251,41 @@ extern void WXDLLIMPEXP_BASE wxOnAssert(const char *file, this macro only does anything if wxDEBUG_LEVEL >= 2. */ #if wxDEBUG_LEVEL - // call this function to break into the debugger unconditionally (assuming - // the program is running under debugger, of course) - extern void WXDLLIMPEXP_BASE wxTrap(); + // wxTrap() can be used to break into the debugger unconditionally + // (assuming the program is running under debugger, of course). + // + // If possible, we prefer to define it as a macro rather than as a function + // to open the debugger at the position where we trapped and not inside the + // trap function itself which is not very useful. + #if wxCHECK_VISUALC_VERSION(7) + #define wxTrap() __debugbreak() + #else + extern WXDLLIMPEXP_BASE void wxTrap(); + #endif // Win VisualC - // assert checks if the condition is true and calls the assert handler with - // the provided message if it isn't + // Global flag used to indicate that assert macros should call wxTrap(): it + // is set by the default assert handler if the user answers yes to the + // question of whether to trap. + extern WXDLLIMPEXP_DATA_BASE(bool) wxTrapInAssert; + + // This macro checks if the condition is true and calls the assert handler + // with the provided message if it isn't and finally traps if the special + // flag indicating that it should do it was set by the handler. // - // NB: the macro is defined like this to ensure that nested if/else - // statements containing it are compiled in the same way whether it is - // defined as empty or not; also notice that we can't use ";" instead - // of "{}" as some compilers warn about "possible unwanted ;" then + // Notice that we don't use the handler return value for compatibility + // reasons (if we changed its return type, we'd need to change wxApp:: + // OnAssertFailure() too which would break user code overriding it), hence + // the need for the ugly global flag. #define wxASSERT_MSG(cond, msg) \ - if ( !wxTheAssertHandler || (cond) ) \ - {} \ - else \ - wxOnAssert(__FILE__, __LINE__, __WXFUNCTION__, #cond, msg) + wxSTATEMENT_MACRO_BEGIN \ + if ( wxTheAssertHandler && !(cond) && \ + (wxOnAssert(__FILE__, __LINE__, __WXFUNCTION__, \ + #cond, msg), wxTrapInAssert) ) \ + { \ + wxTrapInAssert = false; \ + wxTrap(); \ + } \ + wxSTATEMENT_MACRO_END // a version without any additional message, don't use unless condition // itself is fully self-explanatory @@ -258,11 +293,17 @@ extern void WXDLLIMPEXP_BASE wxOnAssert(const char *file, // wxFAIL is a special form of assert: it always triggers (and so is // usually used in normally unreachable code) - #define wxFAIL_COND_MSG(cond, msg) \ - if ( !wxTheAssertHandler ) \ - {} \ - else \ - wxOnAssert(__FILE__, __LINE__, __WXFUNCTION__, cond, msg) + #define wxFAIL_COND_MSG(cond, msg) \ + wxSTATEMENT_MACRO_BEGIN \ + if ( wxTheAssertHandler && \ + (wxOnAssert(__FILE__, __LINE__, __WXFUNCTION__, \ + cond, msg), wxTrapInAssert) ) \ + { \ + wxTrapInAssert = false; \ + wxTrap(); \ + } \ + wxSTATEMENT_MACRO_END + #define wxFAIL_MSG(msg) wxFAIL_COND_MSG("Assert failure", msg) #define wxFAIL wxFAIL_MSG((const char*)NULL) #else // !wxDEBUG_LEVEL @@ -283,6 +324,13 @@ extern void WXDLLIMPEXP_BASE wxOnAssert(const char *file, #define wxASSERT_LEVEL_2(cond) #endif +// This is simply a wrapper for the standard abort() which is not available +// under all platforms. +// +// It isn't really debug-related but there doesn't seem to be any better place +// for it, so declare it here and define it in appbase.cpp, together with +// wxTrap(). +extern void WXDLLIMPEXP_BASE wxAbort(); /* wxCHECK macros always check their conditions, setting debug level to 0 only @@ -296,7 +344,7 @@ extern void WXDLLIMPEXP_BASE wxOnAssert(const char *file, wxCHECK_RET( p != NULL, "pointer can't be NULL" ) */ -// the generic macro: takes the condition to check, the statement to be execute +// the generic macro: takes the condition to check, the statement to be executed // in case the condition is false and the message to pass to the assert handler #define wxCHECK2_MSG(cond, op, msg) \ if ( cond ) \ @@ -364,6 +412,24 @@ extern void WXDLLIMPEXP_BASE wxOnAssert(const char *file, unsigned int msg: expr; \ wxMAKE_UNIQUE_ASSERT_NAME() { wxUnusedVar(msg); } \ } +#elif defined( __VMS ) +namespace wxdebug{ + +// HP aCC cannot deal with missing names for template value parameters +template struct STATIC_ASSERTION_FAILURE; + +template <> struct STATIC_ASSERTION_FAILURE { enum { value = 1 }; }; + +// HP aCC cannot deal with missing names for template value parameters +template struct static_assert_test{}; + +} + #define WX_JOIN( X, Y ) X##Y + #define WX_STATIC_ASSERT_BOOL_CAST(x) (bool)(x) + #define wxCOMPILE_TIME_ASSERT(expr, msg) \ + typedef ::wxdebug::static_assert_test<\ + sizeof(::wxdebug::STATIC_ASSERTION_FAILURE< WX_STATIC_ASSERT_BOOL_CAST( expr ) >)>\ + WX_JOIN(wx_static_assert_typedef_, __LINE__) #else #define wxCOMPILE_TIME_ASSERT(expr, msg) \ struct wxMAKE_UNIQUE_ASSERT_NAME { unsigned int msg: expr; } @@ -396,10 +462,9 @@ extern void WXDLLIMPEXP_BASE wxOnAssert(const char *file, /* Return true if we're running under debugger. - Currently this only really works under Win32 and Mac in CodeWarrior builds, - it always returns false in other cases. + Currently only really works under Win32 and just returns false elsewhere. */ -#if defined(__WXMAC__) || defined(__WIN32__) +#if defined(__WIN32__) extern bool WXDLLIMPEXP_BASE wxIsDebuggerRunning(); #else // !Mac inline bool wxIsDebuggerRunning() { return false; }