[cfe-dev] Warnings are different on preprocessed file

David Blaikie dblaikie at gmail.com
Wed Apr 30 08:35:46 PDT 2014


On Wed, Mar 12, 2014 at 7:13 AM, Richtarsky, Martin
<martin.richtarsky at sap.com> wrote:
> Hi,
>
> is this expected behavior?

To answer this original question: Yes, it is expected behavior that
preprocessing source and compiling it does not produce the same
results as compiling the preprocessed source directly.

Certain warnings produce (too many) false positives without taking
into account whether they were expanded from a macro, etc.

Take, for example:

#define FUNC_TEST(arg) (func(arg) ? GOOD : BAD)

Perhaps this macro is the idiomatic way to call 'func' in this
library? (ie: 'func' is an internal name, only ever meant to be
accessed via the macro)

Sometimes the user wants the result:

if (FUNC_TEST(42) == GOOD) { ... }

but sometimes it's not needed:

FUNC_TEST(42);

Which all seems fine. But if the user explicitly wrote:

func(arg) ? GOOD : BAD;

we would like to warn the user that they have unused-values there?
(Why would anyone /ever/ write that code? The whole conditional
operator and the values GOOD and BAD are discarded, the user might as
well just write "func(arg);")

So using the presence/absence of a macro helps diagnose the bad cases
while not needlessly warning on reasonable cases.

To your later comment about "no other compiler does this" - I suspect
some do, but also one of Clang's engineering novelties is that it
keeps track of all this macro expansion information so it /can/ reason
about warnings using this information. Many other compilers don't have
this information available to make such choices about when to emit and
suppress warnings.

- David

>
> cat preproc_warning.sh
> #!/bin/bash
>
> echo "-- direct compilation:"
> clang++ -c preproc_warning.cpp -o /dev/null
> echo "-- preprocessing:"
> clang++ -E preproc_warning.cpp -o preproc_out.cpp
> echo "-- compilation of preprocessed source:"
> clang++ -c preproc_out.cpp -o /dev/null
>
>
> cat preproc_warning.cpp
> #include <stddef.h>
>
> #define CHECK(a) ( a ? 1 : NULL)
>
> int func1()
> {
>     int a;
>     return NULL; // produces warning during direct compilation and compilation of preprocessed source
> }
>
> int func2()
> {
>     int a;
>     return (CHECK(a)); // produces warning only on preprocessed source
> }
>
>
> shows this output:
> -- direct compilation:
> preproc_warning.cpp:8:12: warning: implicit conversion of NULL constant to 'int' [-Wnull-conversion]
>     return NULL; // produces warning during direct compilation and compilation of preprocessed source
>     ~~~~~~ ^~~~
>            0
> 1 warning generated.
> -- preprocessing:
> -- compilation of preprocessed source:
> preproc_warning.cpp:8:12: warning: implicit conversion of NULL constant to 'int' [-Wnull-conversion]
>     return __null;
>     ~~~~~~ ^~~~~~
>            0
> preproc_warning.cpp:14:23: warning: implicit conversion of NULL constant to 'int' [-Wnull-conversion]
>     return (( a ? 1 : __null));
>     ~~~~~~            ^~~~~~
>                       0
> 2 warnings generated.
>
>
> Best regards,
> Martin
>
> _______________________________________________
> cfe-dev mailing list
> cfe-dev at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev



More information about the cfe-dev mailing list