warning for passing NULL as format arg

Hello cfe-dev,

I came across some surprising behavior involving -Wformat. I was generating some C code and an error in the code generator led to it emitting something similar to the following:

    printf(NULL, “foo”);

Using Clang on macOS (version “Apple LLVM version 10.0.0 (clang-1000.11.45.5)”) this compiles warning-free even with -Wformat -Wformat-nonliteral -Wformat-zero-length. Is this to be expected? Obviously it’s quite unlikely a human would write this code, but I was surprised the compiler had nothing to say about this.

Thanks,
Matt

Hi Matt,

Emitting something like -Wnonnull on builtins that require non-null arguments seems totally reasonable to me, there are probably other builtins where this is a more plausible mistake to make. If you're interested in implementing this, there are some similar diagnostics in SemaChecking.cpp, which would be a good starting point.

Erik

Thanks for the reply, Erik. It didn’t occur to me that Clang might be treating this differently as a builtin. Even so, -Wnonnull would only complain if printf was tagged with __attribute__((nonnull(1))) (which it isn’t on my system), right?

I confess, I’ve never really understood how to use __attribute__((nonnull)) and it has always seemed harmful to me. When Clang or GCC see a nonnull-tagged prototype for a function, they liberally remove null checks within the function body, making it difficult to code defensively. E.g.

    int foo(int *p) __attribute__((nonnull));
    int foo(int *p) {
      assert(p != NULL); // <- this will get dropped on anything > -O0
      return *p;
    }

Effectively, compilers treat nonnull as both a warning guide and an optimisation hint. I can get the second effect in isolation with something like __builtin_assume(p != NULL), but I don’t know how to isolate the first effect. I realise this is a bit off into the weeds now, but if you have any thoughts on this topic I’d be interested to hear them.

There’s _Nonnull (https://clang.llvm.org/docs/AttributeReference.html#nonnull) which doesn’t allow the optimizer to allow make assumptions based on the presence of the attribute.

Erik is probably saying that you could change clang to act as if this attribute is present on some functions even if it isn’t.

Ah perfect. I was not aware of this attribute; thanks for the pointer!

I think the correct solution is not to teach Clang special behaviour for builtins but for their prototypes in the libc headers to include _Nonnull.