
Useful GCC warning options not enabled by -Wall -Wextra - rbanffy
https://kristerw.blogspot.com/2017/09/useful-gcc-warning-options-not-enabled.html
======
vog
Nice summary. Out of curiosity:

Why are those warnings not automatically included in "-Wall -Wextra"? Is there
any issue with enabling them? Are these somewhat experimental?

How do these GCC warning compare to Clang warnings? Do these warnings exist
there, too?

~~~
jcelerier
> Why are those warnings not automatically included in "-Wall -Wextra"? Is
> there any issue with enabling them? Are these somewhat experimental?

Because tons of people keep complaining "muh my build breaks if they enable
new warnings". Dammit, idiots, if your build break there's a good chance your
software is already broken too; that's the point of breaking the build: making
bugs visible so that you have to fix them.

~~~
quotemstr
That's why you don't enable -Werror in release builds, contrary to received
wisdom on the subject.

When you compile with -Werror, you surrender control over your build's success
to the whims of the same people who think that it's okay that memcpy(0, 0, 0)
is undefined behavior. The personal opinions of future compiler authors
shouldn't affect whether your program builds successfully. Sometimes warnings
are bogus.

Sure, use -Werror in development. But don't make it the default.

~~~
jlg23
I disagree. Rather write nasty rants in comments that explain compiler-
specific workarounds. It should not be too many anyway, if one adheres to
KISS.

Otherwise you surrender control over the correctness of your program "to the
whims of the same people who think that it's okay that memcpy(0, 0, 0) is
undefined behavior".

More debatable decisions will be made in compiler implementations and I'd
rather force the user who compiles the program to understand the implications
of warnings by turning them into errors than letting them ignore them (because
"it compiled, after all!").

If I was to make the call, I'd make "-Werror" default in all compilers, remove
the option and allow to disable it by "\--I-really-want-to-ignore-warnings-
for-fscks-sake" which when used would sleep(30) after an all-caps nag screen
that tells people "don't ever use that option."

~~~
spc476
I have one project where I run with "-pedantic -std=c99 -Wall -Wextra". The
one error that pops up is:

    
    
         warning: ISO C forbids assignment between function pointer and ‘void *’ [-pedantic]
    

But POSIX requires that behavior (the actual target of the build). So for now,
it's benign, but if the platform changes (to a non-POSIX system) then yes, it
will have to be investigated.

~~~
nwellnhof
This affects many codebases. For example, looking up functions with `dlsym`
triggers this warning which is probably one of the main reasons for the POSIX
requirement. It's unfortunate that GCC doesn't allow to disable only this
particular warning. When writing cross-platform code, `-pedantic` is too
useful to disable completely.

------
minexew
My absolute favorite for modern C++ is

-Werror=switch

Using this, you can enforce that a switch statement over an enum value is
complete (covers all cases) simply by omitting the default case.

~~~
asveikau
You're not the first person I've seen suggest that this condition is worth
flagging, but I don't completely understand why. People who conform to such a
style then go on to add a "default" case that is a no-op, which I guess is
more explicit, but also feels a little tedious and verbose. Switch statements
in C can do all sorts of funky things (vide: Duff's device) so I think
omitting a case label for an enum value feels like a much lesser crime. What
if you just don't have meaningful things to do for that enum value?

~~~
jlg23
> I think omitting a case label for an enum value feels like a much lesser
> crime.

This is not about the coding police coming to get you but preventing you from
shooting yourself into your feet when you extend the enumeration. Quite often
you want to cover all cases and write code that signals an error if the
default branch is called. CL even has a special version of the CASE macro
(CL's "switch") called ECASE[1] with the only difference being that ECASE
signals an error on unhandled cases.

[1]
[http://www.lispworks.com/documentation/HyperSpec/Body/m_case...](http://www.lispworks.com/documentation/HyperSpec/Body/m_case_.htm)

~~~
balls187
> This is not about the coding police coming to get you but preventing you
> from shooting yourself into your feet when you extend the enumeration.

This.

And not necessarily yourself, but whomever maintains the software after you.

Of course this doesn't prevent someone from adding a "default" label in some
future iteration.

~~~
asveikau
I think you guys are missing something in my perplexed state at this
construct. I'm not saying it out of lack of experience or because I disbelieve
in the "going out of my way to make things more maintainable though verbosity"
aspect. It's just that many times in practice I have rarely seen an honest
switch statement that _really_ needs case labels for all possible values.
_Much_ more common in my experience, 1 or more cases are no-ops. I think it's
pointless to list out the no-ops, but I've seen people advocate just that.

There are exceptions to this "some cases are no-ops" thing. But I think it's
the minority of switches I've seen.

From that perspective it does seem like the coding police angle. It's
reminiscent of certain things in Java, like making a bunch of implicit
conversions into errors, or C#, which forbids implicit fall-through on a
switch. Those too are for safety and maintainability. They also make a lot of
constructs more ugly. My question is: is it worth it? In this case (unintended
pun) I don't think so.

~~~
Sean1708
Really? I've literally never written (or at least I don't ever remember
writing) a case statement without either specifying every possible value or
adding a meaningful default case.

------
usernam
Warnings are good, but it's a pity there's no good warning suppression method
which is compact (and does not require to disable the warning on the entire
file).

People generally "fix" warnings by writing equally useless statements like "x
= x" (common for -Wunused). I've seen codebases which aim for zero warnings,
but with -Wextra/-Weverything it's just silly. Warnings are supposed to be
just that: warnings.

I'd rather want a clean way to suppress the warning and mark it as such
instead, so that's hidden by default when the programmer takes note of it.

We have push/pop pragmas, but they are even worse readability-wise. I'd rather
have a neighboring comment with dedicated syntax instead.

~~~
warkdarrior
You can enable/disable warnings in gcc on a line-by-line basis using pragmas:
[https://gcc.gnu.org/onlinedocs/gcc/Diagnostic-
Pragmas.html#D...](https://gcc.gnu.org/onlinedocs/gcc/Diagnostic-
Pragmas.html#Diagnostic-Pragmas)

~~~
usernam
I mentioned that. However, push/pop statements require a minimum of 3 lines of
pragmas to suppress an unused statement. This doesn't work, you'll end up
disabling warnings for entire functions.

------
zakk
I wonder why -Wnull-dereference is not default.

~~~
maxlybbert
I would guess "because people complain when it gives warnings related to
macros." That's almost always the answer, especially for C.

------
kazinator
I usually add these old standbys:

-Wimplicit-function-declaration: warn when a function is used without being declared (not needed in -std=c99 mode, but I write in c90). Catches functions not being declared in header files, which would result in broken type checking.

-Wmissing-prototypes: external function is defined without a previous prototype declaration. This catches functions that should be _static_ : you fix it by making the function _static_ , or else by prototyping it (in a header) so that it is properly public.

-Wstrict-prototypes: catches accidental old-style definitions or declarations, like void foo(), which isn't a prototype.

~~~
wyldfire
> Catches functions not being declared in header files, which would result in
> broken type checking.

Actually it could be much more interesting than that -- the implicit function
decl will be `int foo(int)` so you risk your compiler pushing the wrong args
on the stack.

------
chocolatebunny
I'm confused by -Wrestrict. Isn't the whole point of the restrict keyword
aliasing like that? what's the point of restrict if there is no enforcement by
default?

~~~
zuzun
The restrict keyword is supposed to enable optimizations, not to increase
safety. You promise you won't access the memory location through different
pointers and the compiler throws some precautions overboard.

------
jerf
Honest question: Are these warnings smart enough to fire only against "raw"
source code? Many of the first few I could see happening from macro expansion
and it would be nice to just let those go without warning and let the
optimizations hopefully pick up the pieces. Or is that some of the false
positives these bring up that were referenced?

~~~
Ded7xSEoPKYNsDd
Unless you enable -Wsystem-headers, GCC doesn't warn about things in system
headers, so for noisy headers it's easiest to mark them as such (with -isystem
<dir>).

------
conistonwater
I think one of the most amazing things I ever found out about clang is that
you can change warning settings directly inside the file with special
#pragma's, without having to modify anything in the build process itself.

~~~
etqwzutewzu
Same as gcc.

------
Shorel
I find more useful to make the program also warning free in clang instead of
adding such options.

~~~
jhasse
clang just adds more stuff to -Wextra but you can get most of the warnings in
GCC too.

~~~
Shorel
It's more than only warnings.

If you code runs fine with two or three different compilers you can also be
sure that you don't rely on undefined or compiler specific behaviour.

It's the same reason some multiplatform libraries are extremely battle tested
and comparatively bug free when compared to single platform code.

------
rurban
Easier would be to use AX_COMPILER_FLAGS from
[https://www.gnu.org/software/autoconf-
archive/ax_compiler_fl...](https://www.gnu.org/software/autoconf-
archive/ax_compiler_flags.html)

This probes for:

    
    
        checking whether C compiler accepts -Werror=unknown-warning-option... yes
        checking whether C compiler accepts -Wno-suggest-attribute=format... yes
        checking whether C compiler accepts -fno-strict-aliasing... yes
        checking whether C compiler accepts -Wall... yes
        checking whether C compiler accepts -Wextra... yes
        checking whether C compiler accepts -Wundef... yes
        checking whether C compiler accepts -Wnested-externs... yes
        checking whether C compiler accepts -Wwrite-strings... yes
        checking whether C compiler accepts -Wpointer-arith... yes
        checking whether C compiler accepts -Wmissing-declarations... yes
        checking whether C compiler accepts -Wmissing-prototypes... yes
        checking whether C compiler accepts -Wstrict-prototypes... yes
        checking whether C compiler accepts -Wredundant-decls... yes
        checking whether C compiler accepts -Wno-unused-parameter... yes
        checking whether C compiler accepts -Wno-missing-field-initializers... yes
        checking whether C compiler accepts -Wdeclaration-after-statement... yes
        checking whether C compiler accepts -Wformat=2... yes
        checking whether C compiler accepts -Wold-style-definition... yes
        checking whether C compiler accepts -Wcast-align... yes
        checking whether C compiler accepts -Wformat-nonliteral... yes
        checking whether C compiler accepts -Wformat-security... yes
        checking whether C compiler accepts -Wsign-compare... yes
        checking whether C compiler accepts -Wstrict-aliasing... yes
        checking whether C compiler accepts -Wshadow... yes
        checking whether C compiler accepts -Winline... yes
        checking whether C compiler accepts -Wpacked... yes
        checking whether C compiler accepts -Wmissing-format-attribute... yes
        checking whether C compiler accepts -Wmissing-noreturn... yes
        checking whether C compiler accepts -Winit-self... yes
        checking whether C compiler accepts -Wredundant-decls... (cached) yes
        checking whether C compiler accepts -Wmissing-include-dirs... yes
        checking whether C compiler accepts -Wunused-but-set-variable... no
        checking whether C compiler accepts -Warray-bounds... yes
        checking whether C compiler accepts -Wimplicit-function-declaration... yes
        checking whether C compiler accepts -Wreturn-type... yes
        checking whether C compiler accepts -Wswitch-enum... yes
        checking whether C compiler accepts -Wswitch-default... yes
        checking whether C compiler accepts -Wno-suggest-attribute=format... no
        checking whether C compiler accepts -Wno-error=unused-parameter... yes
        checking whether C compiler accepts -Wno-error=missing-field-initializers... yes
        checking whether C compiler accepts -Werror=unknown-warning-option... (cached) yes
        checking whether the linker accepts -Wl,--no-as-needed... no
        checking whether the linker accepts -Wl,--fatal-warnings... no
        checking whether the linker accepts -Wl,-fatal_warnings... yes
        checking whether the linker accepts -Wl,-fatal_warnings... yes

