add debug_warn_err analogous to debug_assert_failed that reports an error code for use with CHECK_ERR et al. (as discussed in bug#70)
This was SVN commit r3037.
This commit is contained in:
parent
bbda296289
commit
813738c295
@ -528,7 +528,7 @@ ErrorReaction display_error(const wchar_t* description, int flags,
|
||||
|
||||
// notify the user that an assertion failed; displays a stack trace with
|
||||
// local variables.
|
||||
ErrorReaction debug_assert_failed(const char* file, int line,
|
||||
ErrorReaction debug_assert_failed(const char* file, int line,
|
||||
const char* func, const char* expr)
|
||||
{
|
||||
// for edge cases in some functions, warnings (=asserts) are raised in
|
||||
@ -546,8 +546,32 @@ ErrorReaction debug_assert_failed(const char* file, int line,
|
||||
const char* base_name = slash? slash+1 : file;
|
||||
|
||||
uint skip = 1; void* context = 0;
|
||||
wchar_t buf[200];
|
||||
swprintf(buf, ARRAY_SIZE(buf), L"Assertion failed in %hs, %hs(%d): \"%hs\"", func, base_name, line, expr);
|
||||
wchar_t buf[400];
|
||||
swprintf(buf, ARRAY_SIZE(buf), L"Assertion failed at %hs:%d (%hs): \"%hs\"", base_name, line, func, expr);
|
||||
return display_error(buf, DE_ALLOW_SUPPRESS|DE_MANUAL_BREAK, skip, context, base_name, line);
|
||||
}
|
||||
|
||||
|
||||
ErrorReaction debug_warn_err(int err, const char* file, int line,
|
||||
const char* func)
|
||||
{
|
||||
// for edge cases in some functions, warnings (=asserts) are raised in
|
||||
// addition to returning an error code. self-tests deliberately trigger
|
||||
// these cases and check for the latter but shouldn't cause the former.
|
||||
// we therefore squelch them here.
|
||||
// (note: don't do so in lib.h's CHECK_ERR or debug_assert to reduce
|
||||
// compile-time dependency on self_test.h)
|
||||
if(self_test_active)
|
||||
return ER_CONTINUE;
|
||||
|
||||
// __FILE__ evaluates to the full path (albeit without drive letter)
|
||||
// which is rather long. we only display the base name for clarity.
|
||||
const char* slash = strrchr(file, DIR_SEP);
|
||||
const char* base_name = slash? slash+1 : file;
|
||||
|
||||
uint skip = 1; void* context = 0;
|
||||
wchar_t buf[400];
|
||||
swprintf(buf, ARRAY_SIZE(buf), L"Function call failed at %hs:%d (%hs): return value was %d", base_name, line, func, err);
|
||||
return display_error(buf, DE_ALLOW_SUPPRESS|DE_MANUAL_BREAK, skip, context, base_name, line);
|
||||
}
|
||||
|
||||
@ -588,8 +612,6 @@ static void tls_init()
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// set the current thread's name; it will be returned by subsequent calls to
|
||||
// debug_get_thread_name.
|
||||
//
|
||||
|
@ -98,6 +98,14 @@ extern void debug_heap_enable(DebugHeapChecks what);
|
||||
// debug_assert
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// rationale: we call this "debug_assert" instead of "assert" for the
|
||||
// following reasons:
|
||||
// - consistency (everything here is prefixed with debug_) and
|
||||
// - to avoid inadvertent use of the much less helpful built-in CRT assert.
|
||||
// if we were to override assert, it would be difficult to tell whether
|
||||
// user source has included <assert.h> (possibly indirectly via other
|
||||
// headers) and thereby stomped on our definition.
|
||||
|
||||
// make sure the expression <expr> evaluates to non-zero. used to validate
|
||||
// invariants in the program during development and thus gives a
|
||||
// very helpful warning if something isn't going as expected.
|
||||
@ -112,8 +120,8 @@ extern void debug_heap_enable(DebugHeapChecks what);
|
||||
#define debug_assert(expr) \
|
||||
STMT(\
|
||||
static unsigned char suppress__ = 0x55;\
|
||||
if(suppress__ == 0x55 && !(expr)) \
|
||||
{ \
|
||||
if(suppress__ == 0x55 && !(expr))\
|
||||
{\
|
||||
switch(debug_assert_failed(__FILE__, __LINE__, __func__, #expr))\
|
||||
{\
|
||||
case ER_SUPPRESS:\
|
||||
@ -126,25 +134,13 @@ STMT(\
|
||||
debug_break();\
|
||||
break;\
|
||||
}\
|
||||
} \
|
||||
}\
|
||||
)
|
||||
|
||||
// rationale: we call our assert "debug_assert" for the following reasons:
|
||||
// - consistency (everything here is prefixed with debug_) and
|
||||
// - to avoid inadvertent use of the much less helpful built-in CRT assert.
|
||||
// if we were to override assert, it would be difficult to tell whether
|
||||
// user source has included <assert.h> (possibly indirectly via other
|
||||
// headers) and thereby stomped on our definition.
|
||||
|
||||
// called when an assertion has failed; notifies the user via display_error.
|
||||
extern enum ErrorReaction debug_assert_failed(const char* file, int line,
|
||||
const char* func, const char* assert_expr);
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// output
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// show a dialog to make sure unexpected states in the program are noticed.
|
||||
// this is less error-prone than "debug_assert(0 && "text");" and avoids
|
||||
// "conditional expression is constant" warnings. we'd really like to
|
||||
@ -153,6 +149,35 @@ extern enum ErrorReaction debug_assert_failed(const char* file, int line,
|
||||
// we therefore just squelch the warning (unfortunately non-portable).
|
||||
#define debug_warn(str) debug_assert((str) && 0)
|
||||
|
||||
|
||||
#define DEBUG_WARN_ERR(err) \
|
||||
STMT(\
|
||||
static unsigned char suppress__ = 0x55;\
|
||||
if(suppress__ == 0x55)\
|
||||
{\
|
||||
switch(debug_warn_err(err, __FILE__, __LINE__, __func__))\
|
||||
{\
|
||||
case ER_SUPPRESS:\
|
||||
suppress__ = 0xAA;\
|
||||
break;\
|
||||
case ER_CONTINUE:\
|
||||
break;\
|
||||
default:\
|
||||
case ER_BREAK:\
|
||||
debug_break();\
|
||||
break;\
|
||||
}\
|
||||
}\
|
||||
)
|
||||
|
||||
extern enum ErrorReaction debug_warn_err(int err, const char* file, int line,
|
||||
const char* func);
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// logging
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// write a formatted string to the debug channel, subject to filtering
|
||||
// (see below). implemented via debug_puts - see performance note there.
|
||||
extern void debug_printf(const char* fmt, ...);
|
||||
|
@ -124,8 +124,7 @@ STMT(\
|
||||
i64 err__ = (i64)(expression);\
|
||||
if(err__ < 0)\
|
||||
{\
|
||||
debug_warn("FYI: CHECK_ERR reports that a function failed."\
|
||||
"feel free to ignore or suppress this warning.");\
|
||||
DEBUG_WARN_ERR(err__);\
|
||||
return (int)(err__ & UINT_MAX);\
|
||||
}\
|
||||
)
|
||||
@ -135,8 +134,7 @@ STMT(\
|
||||
i64 err__ = (i64)(expression);\
|
||||
if(err__ < 0)\
|
||||
{\
|
||||
debug_printf("%s:%d: FYI: CHECK_ERR reports that a function failed."\
|
||||
"feel free to ignore or suppress this warning.\n", __FILE__, __LINE__);\
|
||||
DEBUG_WARN_ERR(err__);\
|
||||
return (int)(err__ & UINT_MAX);\
|
||||
}\
|
||||
)
|
||||
@ -157,8 +155,7 @@ STMT(\
|
||||
i64 err__ = (i64)(expression);\
|
||||
if(err__ < 0)\
|
||||
{\
|
||||
debug_warn("FYI: THROW_ERR reports that a function failed."\
|
||||
"feel free to ignore or suppress this warning.");\
|
||||
DEBUG_WARN_ERR(err__);\
|
||||
throw (int)(err__ & UINT_MAX);\
|
||||
}\
|
||||
)
|
||||
@ -170,8 +167,7 @@ STMT(\
|
||||
i64 err__ = (i64)(expression);\
|
||||
if(err__ < 0)\
|
||||
{\
|
||||
debug_warn("FYI: WARN_ERR_RETURN reports that a function failed."\
|
||||
"feel free to ignore or suppress this warning.");\
|
||||
DEBUG_WARN_ERR(err__);\
|
||||
return;\
|
||||
}\
|
||||
)
|
||||
@ -182,8 +178,7 @@ STMT(\
|
||||
STMT(\
|
||||
i64 err__ = (i64)(expression);\
|
||||
if(err__ < 0)\
|
||||
debug_warn("FYI: WARN_ERR reports that a function failed."\
|
||||
"feel free to ignore or suppress this warning.");\
|
||||
DEBUG_WARN_ERR(err__);\
|
||||
)
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user