This is the mail archive of the gcc-help@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: _Static_warning?


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]