Reputation: 323
I have a assert macro that's defined as:
#define likely(cond) (__builtin_expect((cond), 1))
#define unlikely(cond) (__builtin_expect(!!(cond), 0))
static void assert_fail(const char *__assertion, const char *__file,
unsigned int __line, const char *__function) {
fprintf(stderr, "\nASSERT failed %s:%d %s()\n%s\n", __file, __line, __function, __assertion);
void *array[50];
size_t size = backtrace(array, 50); // Fill out array of pointers to stack entries
backtrace_symbols_fd(&array[1], size, STDERR_FILENO);
exit(1);
}
#define assert(expr) ( likely(expr) ? (void) (0) : \
assert_fail(#expr, __FILE__, __LINE__, __func__ ))
Which works fine, except when you make a simple error inside an assert condition, eg a wrong variable name:
assert(size > 0);
It prints a perfectly sensible error, then 5 notes (including repeats) which makes it much harder to read. Is there any sane way to address this that would make it easier to read? The core issue seems to be the use of macros, but I can't see how to avoid that here, given the use of __FILE__
, __LINE__
, etc.
Disabling the "note: each undeclared identifier is reported only once for each function" would cut it in half if that was possible (though I cannot find any way to do that)
abc.c: In function 'init':
abc.c:53:12: error: 'size' undeclared (first use in this function)
assert(size > 0);
^
include/assert.h:21:41: note: in definition of macro 'likely'
#define likely(cond) (__builtin_expect((cond), 1))
^
abc.c:53:5: note: in expansion of macro 'assert'
assert(size > 0);
^
abc.c:53:12: note: each undeclared identifier is reported only once for each function it appears in
assert(size > 0);
^
include/assert.h:21:41: note: in definition of macro 'likely'
#define likely(cond) (__builtin_expect((cond), 1))
^
abc.c:53:5: note: in expansion of macro 'assert'
assert(size > 0);
^
Upvotes: 3
Views: 538
Reputation: 223739
As a general rule, when dealing with compiler errors, you address the first error you find then recompile. That way you don't waste time chasing down cascading errors.
In this particular case, you'll notice that you have an "error" line followed by several "note" lines. Whenever you see a "note" message, it's giving you additional information on the most recent "error" or "warning message". You shouldn't suppress messages like these (and I don't believe you can), as they can give you valuable information on the true source of an error.
Here's an example of where these "note" messages are useful:
#include <stdio.h>
void f1(double x);
int main()
{
f1(3);
return 0;
}
void f1(int x)
{
printf("x=%d\n", x);
}
In this code the declaration of f1
doesn't match the definition. The compiler generate the following message:
x1.c:12:6: error: conflicting types for ‘f1’
void f1(int x)
^
x1.c:3:6: note: previous declaration of ‘f1’ was here
void f1(double x);
The "error" message tells you that the definition at line 12 doesn't match a declaration, but it doesn't say what declaration it conflicts with. That appears in the "note" message that follows. In a large project, you might have trouble finding that conflict without the "note" message.
Upvotes: 3
Reputation: 1
If expression evaluates to TRUE, assert() does nothing. If expression evaluates to FALSE, assert() displays an error message on stderr (standard error stream to display error messages and diagnostics) and aborts program execution.
Upvotes: -1