9

I know that one should always compile with both -Wall and -Wextra as they enable warnings and help us to understand our mistake, if any.

I've read that the -Wextra compiler flag is not recommended to use because it is too verbose with a lot of false positives.

I was quite surprised on reading this. So I started googling about it but I didn't get any answer as all the search results showed was "what does the -Wextra flag do?".

So, my questions are

  • In which all situations does the -Wextra flag emit uneccessary warnings?
  • Is it possible to stop the -Wextra flag from enabling the other flags that cause GCC from emitting these types of warnings?
Roman Nikitchenko
  • 12,800
  • 7
  • 74
  • 110
Spikatrix
  • 20,225
  • 7
  • 37
  • 83
  • 1
    Where did you read this? – Wintermute Feb 07 '15 at 11:45
  • @Wintermute , From [here](http://www.stackoverflow.com/questions/28345001/why-doesnt-c-return-an-error-when-i-use-a-large-int/28345019?noredirect=1#comment45051822_28345019) – Spikatrix Feb 07 '15 at 11:48
  • 1
    What is a "useless warning"? All warnings are useful – Ed Heal Feb 07 '15 at 11:50
  • @EdHeal , You're right. I've edited it. – Spikatrix Feb 07 '15 at 11:51
  • 3
    I disagree with him there. There are many useful warnings in `-Wextra`, and spurious warnings are easily suppressed. For example, unused parameters can be unnamed in C++, and in C you can write `(void) varname;` to indicate that the variable is meant to be unused. Always use both `-Wall` and `-Wextra`, that's my advice, and you won't spend hours debugging because you just don't see that bloody semicolon after `if();` you typoed there. I'll acknowledge that opinion plays a role here, though. – Wintermute Feb 07 '15 at 11:53
  • You can learn all about the [flag from the documentation](https://gcc.gnu.org/onlinedocs/gcc-4.9.2/gcc/Warning-Options.html#Warning-Options). I think your primary question about "unnecessary" warnings is subjective. –  Feb 07 '15 at 12:01
  • `-Wextra` will indicate comparisons between signed and unsigned. That's definitely **not** useless or "unnecessary". – Nobilis Feb 07 '15 at 13:09
  • Not only you should be using `-Wextra`, you should be using `-pedantic -Wall -Wextra -Wcast-align -Wcast-qual -Wctor-dtor-privacy -Wdisabled-optimization -Wformat=2 -Winit-self -Wlogical-op -Wmissing-declarations -Wmissing-include-dirs -Wnoexcept -Wold-style-cast -Woverloaded-virtual -Wredundant-decls -Wshadow -Wsign-conversion -Wsign-promo -Wstrict-null-sentinel -Wstrict-overflow=5 -Wswitch-default -Wundef -Werror -Wno-unused` (yes, those are not implied by `-Wextra`). See here for why: https://stackoverflow.com/questions/5088460/flags-to-enable-thorough-and-verbose-g-warnings/9862800#9862800 – peppe Feb 07 '15 at 13:11
  • @EdHeal A useless warning is one that typically warns for code that is written exactly the way it should be written. An example of a warning that would be useless for most is the one you might get for `int main(void) { return 0; }`: "warning: traditional C rejects ISO C style function definitions" (enabled by GCC's `-Wtraditional`). Do you really want to argue that such a warning is useful for you, and that you will turn it on in your projects? –  Feb 07 '15 at 15:19
  • I think that is useful – Ed Heal Feb 07 '15 at 16:04
  • @EdHeal: I very strongly disagree that all warnings are useful. Too many false positives just creates noise (and can result in ugly code; see the 2nd list in cmaster's answer). Too much noise, if fixed, results in you fixing "bugs" that weren't bugs (and possibly introducing *actual* bugs); if not fixed, they get in the way of the *real* problems. – Tim Čas Feb 09 '15 at 13:05
  • @EdHeal: Oh and, re: `-Wtraditional`, I'd say that's only useful in a *VERY* specific circumstance (legacy code that'll be compiled with a legacy compiler); if you're writing *new* traditional code nowadays, you're doing something very, very wrong. That makes `-Wtraditional` useless (or, indeed, harmful) for general use. – Tim Čas Feb 09 '15 at 13:08

6 Answers6

9

The point about the usefulness of -Wextra warnings is that the corresponding warnings have these properties (more or less):

  1. They generate false positives.

  2. The false positives are relatively frequent.

  3. Adapting the code to avoid false positives is a nuisance.

The consequence is, that many projects that switch on -Wall -Wextra give up trying to avoid all the warnings. Consequently, when you compile such a project, you see hundreds and hundreds of warnings, almost all about legit code. And the one warning that you should have seen slips unnoticed in the endless warning stream. Worse: the fact that a normal compilation spits out so many warnings makes you get sloppy about avoiding the new warnings that your new code introduces. Once a project reaches a few tens of warnings, the fight is usually over; it will require a heroic effort to bring the warning count back to zero.

Here is an example of some perfectly legitimate code that is barked at by -Wextra:

void myClass_destruct(MyClass* me) {}

It's a destructor and it's empty. Yet, it should be there simply to facilitate calling it at the appropriate points (subclass destructors), so that it is easy to add stuff to MyClass that needs cleanup. However, -Wextra will bark at the unused me parameter. This forces programmers to write code like this:

void myClass_destruct(MyClass* me) {
    (void)me;    //shut up the compiler barking about the unused parameter
}

This is plain noise. And it gets annoying to write such code. However, in order to achieve a zero warning count under a -Wextra regime, this noise needs to be added to the code. So, you can pick any two of these three:

  1. Clean code

  2. Zero warning count

  3. -Wextra warnings

Choose wisely which one you want to drop, you won't get all three.

cmaster - reinstate monica
  • 38,891
  • 9
  • 62
  • 106
  • And of course what's noise to one won't necessarily be noise to another. Some people may prefer having all unused function parameters marked in the code as unused, to make it clear that it's intentional. (But in this case, I'd agree with you.) –  Feb 07 '15 at 15:25
  • 1
    Note that the `(void)me;` trick sometimes doesn't work, either. In at least one version of GCC (sorry, can't recall which), I've had that line give me a "Warning: Statement with no effect" warning. I can't quite recall how I've managed to get around it, though, but it got ugly. – Tim Čas Feb 09 '15 at 13:00
  • 3
    You can fix the unused parameter warning by writing `myClass_destruct(MyClass*)` or `myClass_destruct(MyClass* /*me*/)`. Neither looks like "plain noise" to me, and both make it clear when a parameter is deliberately unused. – Nemo Apr 13 '16 at 22:05
  • @Nemo Good idea. Have to remember that for the next time I have to develop with that warning switched on. Thanks. – cmaster - reinstate monica Apr 14 '16 at 05:55
  • 1
    This question is tagged with "C", and you can't just omit function parameter names in C. See e.g. https://stackoverflow.com/questions/7090998/portable-unused-parameter-macro-used-on-function-signature-for-c-and-c – Vladimír Čunát Jan 03 '20 at 14:30
4

Some of -Wextra warnings are enforcing appropriate coding style which can conflict with some people processes. This is the only reason to avoid it. My solution in this case is to 'correct' exact set using -Wno-* syntax.

For example -Wextra implies -Wempty-body which warns you about empty bodies of some control structures like if, else and while. But if you follow from one side 'iterative' implementation style and from another want serious amount of warnings, this will be uncomfortable for you.

Here is evolving code example:

void doSomething()
{
    if (validatePreConditions())
    {
         //TODO Handle it some time.
    }

    // ... Here you have real code.

}

If you have -Werror, and want to start testing without pre-condition check implemeneted, you are in trouble.

But here is pitfall, what is acceptable for 'in-development' code is to be fixed by the time code is going to production. So my option for such cases is to have different set of warnings and different build profiles. So, for example, 'developer' build is OK to have empty bodies but anything going to be merged into main-line MUST NOT have such gaps.

Another example is -Wignored-qualifiers which is included into -Wextra. In some cases you know compiler will ignore your const qualifier but you're adding it just for your own comfort (I personally don't support these qualifiers on return type but some people think they do good job with such marks).

Roman Nikitchenko
  • 12,800
  • 7
  • 74
  • 110
3

In which all situations does the -Wextra flag emit uneccessary warnings?

What is your definition of unnecessary? You can consult the manual (this is for 4.9.2) to see exactly what the warning flags do. Then you can decide for yourself whether or not it's right for your code base.

Is it possible to stop the -Wextra flag from enabling the other flags that cause GCC from emitting these types of warnings?

Stick -Wno- in front of a warning in order to disable it. Not all warnings have a warning flag, which means you probably have to stick with it. You can also generally find more information by browsing their bugtracker by searching for certain warning flags and seeing if any discussions exist. If it's not in the documentation, it might be there. The developers might also express rationale for why things are the way they are.


In order to address the comment you linked to in the comments,

...or warnings about missing field initializers (when you're intentionally initializing a structure with { 0 }, making the compiler zero-initialize everything else automagically).

This argument is moot because it's already been fixed. For example, the following code produces no missing initializer fields warning:

typedef struct { int a; int b; } S;

int main()
{
    S s = { 0 };
}
  • `-fdiagnostics-show-option` can be useful to get the flags to disable with `Wno-`. – mafso Feb 07 '15 at 12:32
  • 1
    The example with the structure initialization is when the first member is of an aggregate type. It that case even `-Wall` only will warn although the diagnostic is not required by the Standard. – ouah Feb 07 '15 at 12:33
  • @Ouah This is the [test case](https://gcc.gnu.org/bugzilla/attachment.cgi?id=33627) present in the bug report. (`-Wall` doesn't warn for me, unless you're referring to something else.) –  Feb 07 '15 at 12:35
  • Then this is a different problem. Gcc warns about `struct { struct { int a; } x; } s = { 0 };` with `-Wall` (also for `{ 0, }`), for example. Tested with GCC 4.9.2. – mafso Feb 07 '15 at 12:41
  • @remyabel in the test case you linked the first member is an `int`. You will get the same warning with `int x[1][1] = {0};` even if the diagnostic is not required by the Standard. What I'm trying to show is `-Wextra` but also `-Wall` are both issuing diagnostics not required by the Standard (and yes it is allowed by the Standard to behave like this). – ouah Feb 07 '15 at 12:41
  • @ouah Can you provide an online demo? This is what [coliru](http://coliru.stacked-crooked.com/a/85a841e2eee5913e) produces. –  Feb 07 '15 at 12:45
  • @remyabel I cannot, try it with your gcc install. By the way your last link is using g++, we are discussing gcc for C. – ouah Feb 07 '15 at 12:48
  • @Ouah All of my tests have been with `-x c -std=c99`. 4.8.3 same results, g++-trunk no warning. –  Feb 07 '15 at 12:48
  • @remyabel OK, I didn't notice `-x` option. So you get the warning *warning: missing braces around initializer* in your link. This warning is not a C Standard required warning as I'm trying to explain. Maybe they changed this behavior in their latest gcc version but they were allowed to warn (but not required to). – ouah Feb 07 '15 at 12:57
  • @ouah That's a different [bug report](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53119). Since it's not covered by `-Wextra`, it doesn't pertain to my answer. (The documentation states that `-Wall` enables `-Wmissing-braces`. `-Wno-missing-braces` takes care of that.) –  Feb 07 '15 at 13:01
3

It's very simple;

A useless warning is one that never points out an actual bug.

Of course this is undecidable, it's impossible to know beforehand if a particular warning will ever 'save the bacon'.

All GCC warnings have at sometime or other pointed out real bugs, so the general theme with the GCC messages are that -Wall warnings are likely to point at errors and are easy to suppress if they don't. So this plays well with -Werror.

The -Wextra messages, OTOH point at real errors less often or may be point out constructs that are common practice in some older code or are just difficult to change to an alternative way of expressing the code. So sometimes they may indeed be "too verbose".

For new code you will normally want -Wextra on.

For old code it should be turned on if it's not "too verbose".

user3710044
  • 2,261
  • 15
  • 15
2

There are basically three types of warnings, and GCC is not very good about grouping them or making this clear:

  1. Warnings that indicate something formally invalid at the source level that should not even compile, but that's allowed for whatever reason (usually compatibility with legacy code). These are mandated by the language standard.

  2. Warnings indicating that your program will necessarily invoke undefined behavior if it reaches the point in the code where the warning occurs. Your program could still be valid if the code is unreachable, and in fact this will likely occur with things like:

    int i = 1;
    if (INT_MAX > 0x7fffffff) <<= 31;
    
  3. Warnings that are purely heuristic, and do not by themselves indicate any programming error or invalidity of your program, where the compiler is simply warning you that you may have intended something different from what you wrote.

-Wextra turns on a lot of "type 3" warnings.

Generally everyone agrees types 1 and 2 are valuable, but as mentioned above, even type 2 can have false positives. Type 3 generally has lots of false positives; some of them can be suppressed with harmless changes to the code, while others require actually making your code worse (or turning off the warning locally) to avoid them.

Here's where people will disagree. To some programmers, you just turn on -Wall -Wextra and locally work around or disable warnings where false positives turn up. Unless you do that, though, false positives create a lot of noise and potentially lower the signal to noise ratio, causing you not to notice the more-serious warnings by getting you used to seeing warnings when you compile.

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
0

There are (at least) two camps of C programmers: those that think the compiler may sometimes know better, and those that think who is the compiler to tell me how to write my code, after all, I know what I'd doing.

Camp 1 enables warnings as much as they can, use lint and other code checkers to even get more hints about questionable or potentially broken code.

Camp 2 doesn't like their sloppiness being pointed out all the time by a machine, let alone spend extra effort fixing what they think is perfect as-is.

Camp 1 is sought by the industry, because they produce less buggy code, less defects, less customer bug reports. If you're programming launch vehicles, satellite equipment, anything that needs safety, controls really expensive equipment, this camp's mindset is what is needed.

Camp 2 obviously gets away far too often and the general software quality of many applications you use (on your computer, smart phone, appliance, ...) is an indication of this.

What camp do you want to belong to? The disadvantages of -Wextra depend on this answer. One man's disadvantage is another man's advantage.

Jens
  • 69,818
  • 15
  • 125
  • 179