I'm somewhat confused how GCC decides when to print a macro expansion
trace when a warning is generated.
"header.h" contains this:
#define X(cond) if (cond)
#define Z(cond) X(cond)
For this main.c file,
#include "header.h"
int f(int i)
{
Z(i = 1) return 1;
return 0;
}
I get the following warning (with -O2 -Wall):
main.c: In function ‘f’:
main.c:5:3: warning: suggest parentheses around assignment used as truth
value [-Wparentheses]
Z(i = 1) return 1;
^
No macro expansion trace is shown in this case. But if I cause a
different warning, say using this code in main.c:
#include "header.h"
int f(int i)
{
int left = i + 1;
Z(left < i) return 1;
return 0;
}
macro expansion context is provided:
In file included from main.c:1:0:
main.c: In function ‘f’:
header.h:1:20: warning: assuming signed overflow does not occur when
assuming that (X + c) < X is always false [-Wstrict-overflow]
#define X(cond) if (cond)
^
/tmp/header.h:2:17: note: in expansion of macro ‘X’
#define Z(cond) X(cond)
^
main.c:6:3: note: in expansion of macro ‘Z’
Z(left < i) return 1;
^
But if I change "header.h" to mark the final macro as part of a system
header, like this:
#define X(cond) if (cond)
#pragma GCC system_header
#define Z(cond) X(cond)
I get:
In file included from main.c:1:0:
main.c: In function ‘f’:
header.h:1:20: warning: assuming signed overflow does not occur when
assuming that (X + c) < X is always false [-Wstrict-overflow]
#define X(cond) if (cond)
^
header.h:3:17: note: in expansion of macro ‘X’
#define Z(cond) X(cond)
^
As you can see, nothing at all points to the source location of the
outermost macro, and in a more complicated context, demystifying the
warning could be quite difficult.
The lack of macro trace in the first case seems like a bug to me as
well, but maybe not, so some suggestions how this feature is supposed to
work would be appreciated.
(This is extracted from real-world code involving glib's
g_return_if_fail macro.)
--
Florian Weimer / Red Hat Product Security Team