[Bug other/59783] New: inline expansion stack when attribute error/warning triggered is displayed incorrectly
daniel.santos at pobox dot com
gcc-bugzilla@gcc.gnu.org
Mon Jan 13 04:11:00 GMT 2014
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59783
Bug ID: 59783
Summary: inline expansion stack when attribute error/warning
triggered is displayed incorrectly
Product: gcc
Version: 4.8.2
Status: UNCONFIRMED
Severity: minor
Priority: P3
Component: other
Assignee: unassigned at gcc dot gnu.org
Reporter: daniel.santos at pobox dot com
In C < C11, __attribute__((error())) is a wonderful replacement for
_Static_assert() (e.g.,
http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/include/linux/compiler.h#n316).
However, when used in nested __always_inline functions where parameters to the
function are treated as compiletime constants and tested via such a mechanism,
the compiler doesn't tell us the correct root cause of the problem.
static void inline __attribute__((always_inline)) validate_pair(int x, int y) {
extern void diedie() __attribute__((error("x + y = too many")));
if (x + y > 32)
diedie();
}
static void inline __attribute__((always_inline)) a1(int x, int y) {
validate_pair(x, y);
/* do some stuff */
}
static void inline __attribute__((always_inline)) a2(int x, int y) {
validate_pair(x, y);
/* do some other stuff */
}
static void inline __attribute__((always_inline)) b(int x, int y) {
if (x & 1)
a1(x, y);
else
a2(x, y);
}
int main(int argc, char *argv[]) {
b(4, 12);
b(5, 13);
b(6, 13);
b(28, 14);
b(27, 14);
b(2, 15);
return 0;
}
When built with -O1 or greater, it yields this output:
In function ‘validate_pair’,
inlined from ‘main’ at asdf.c:15:18:
asdf.c:6:15: error: call to ‘diedie’ declared with attribute error: x + y = too
many
diedie();
^
In function ‘validate_pair’,
inlined from ‘main’ at asdf.c:10:18:
asdf.c:6:15: error: call to ‘diedie’ declared with attribute error: x + y = too
many
diedie();
^
It is correct that these two errors were inlined from the function main, but
the line number given is the function that actually calls validate_pair(),
although the actual inline instantiation stack for the first error was main()
-> b() -> a1() -> validate_pair() and for the second error main() -> b() ->
a1() -> validate_pair(). The work-around is essentially to use a preprocessor
macro, although a lot of simplicity, type-safety, etc. are then lost.
Since we are working with compile-time constant values, what would be nice
(similar to what is requested for bug #41373) is to display the entire inline
function instantiation/expansion stack, e.g.:
In function ‘validate_pair’,
inlined from ‘a2’ at asdf.c:15:18:
inlined from ‘b’ at asdf.c:23:25:
inlined from ‘main’ at asdf.c:30:15:
asdf.c:6:15: error: call to ‘diedie’ declared with attribute error: x + y = too
many
diedie();
This way, we can trace it to the exact function call (or inline function
expansion) that caused the problem. Welcome to the new age of C
metaprogramming! (and thank you for helping to make it possible) This is an age
of compile-time data (if not types, like C++ metaprogramming). So if you
*really* wanted to be helpful, you could do something like this:
In function ‘validate_pair’,
inlined from ‘a2’ [with x=28, y=14] at asdf.c:15:18:
inlined from ‘b’ [with x=28, y=14] at asdf.c:23:25:
inlined from ‘main’ [with x=28, y=14] at asdf.c:30:15:
asdf.c:6:15: error: call to ‘diedie’ declared with attribute error: x + y = too
many
diedie();
Now I realize that actually involves a lot as many data types can be treated as
compiletime constants, even structs and pointers to structs and functions, but
I didn't think it could hurt to throw it out there. Essentially, displaying
the constant parameters of an inlined function call like you do the template
parameters in a C++ templatized function or type.
See also: bug #41373
More information about the Gcc-bugs
mailing list