_Static_warning?
Martin Sebor
msebor@redhat.com
Tue May 19 14:52:00 GMT 2015
On 05/18/2015 11:07 PM, Eduardo Piombino wrote:
> That's really helpful and it's very close to what I've been looking for.
> Had I figured this trick (I tried [ab]using so many other warnings
> with no gain) I may have settled for this solution, weren't it for the
> fact that in my current setup the _Static_warning is not fired from
> its own line like your example, but from a macro.
>
> $ cat h.c && ../gcc/bin/gcc -Wall -c h.c -o/dev/null
> int static_warning_dummy(char * p) __attribute__ ((nonnull(1)));
> int static_warning_dummy(char * p) { return 0; }
> #define _Static_warning(x, txt) (int) (x) ? 0 :
> static_warning_dummy((char *) x);
>
> #define foo(x) do { _Static_warning(x, errormsg); bar(x); } while(0)
>
> void bar(int p)
> {
> }
>
> int main(void)
> {
> _Static_warning(0, "bar"); // here you see the message in the logs
> foo(0); // here you don't
> }
>
> h.c: In function âmainâ:
> h.c:13:2: warning: null argument where non-null required (argument 1)
> [-Wnonnull]
> _Static_warning(0, "bar"); // here you see the message in the logs
> ^
> h.c:14:2: warning: null argument where non-null required (argument 1)
> [-Wnonnull]
> foo(0); // here you don't
> ^
>
> The consequence is that when the compiler prints out the line that
> triggered it, it will print out the original line of code, and not the
> one where I actually invoked the _Static_warning, losing the message
> parameter in the way.
I would consider this a bug. GCC should include in the warning
the context from which the macro was invoked just as it does in
the _Static_assert case, and just as Clang does (below).
$ cat t.c && clang -Wall -c -o/dev/null t.c
void foo (char*, ...) __attribute__ ((nonnull (1)));
#define foo(p) foo (p, "p is null")
#define bar(p) _Static_assert (p, "p is null")
void baz (void) {
foo (0);
bar (0);
}
t.c:6:5: warning: null passed to a callee that requires a non-null argument
[-Wnonnull]
foo (0);
^ ~
t.c:2:35: note: expanded from macro 'foo'
#define foo(p) foo (p, "p is null")
^
t.c:7:5: error: static_assert failed "p is null"
bar (0);
^ ~
t.c:3:16: note: expanded from macro 'bar'
#define bar(p) _Static_assert (p, "p is null")
^
1 warning and 1 error generated.
> There may exist some kind of workaround to this, but I can't see it right now.
It's not pretty but this seems to work:
$ cat -n t.c && gcc -O2 -Wall -c -o/dev/null t.c
1 #define Static_warning(x, txt) \
2 (void)__builtin_choose_expr (x, 0, (char[sizeof txt - 2 +
!!x]){ txt })
3 #define foo(x) do { Static_warning (x, "errormsg"); } while(0)
4
5
6 void bar (void) {
7 Static_warning (0, "bad");
8 foo (0);
9
10 Static_warning (1, "good");
11 foo (1);
12 }
t.c: In function âbarâ:
t.c:2:67: warning: initializer-string for array of chars is too long
(void)__builtin_choose_expr (x, 0, (char[sizeof txt - 2 + !!x]){ txt })
^
t.c:7:5: note: in expansion of macro âStatic_warningâ
Static_warning (0, "bad");
^
t.c:2:67: warning: initializer-string for array of chars is too long
(void)__builtin_choose_expr (x, 0, (char[sizeof txt - 2 + !!x]){ txt })
^
t.c:3:21: note: in expansion of macro âStatic_warningâ
#define foo(x) do { Static_warning (x, "errormsg"); } while(0)
^
t.c:8:5: note: in expansion of macro âfooâ
foo (0);
^
Martin
More information about the Gcc-help
mailing list