GCC 6 Will Warn You About Misleading Code Indentations
phoronix.com
phoronix.com
> "The warning is not issued for code involving multiline preprocessor logic ... The warning is not issued after a @code{#line} directive, since this typically indicates autogenerated code"
Seems like a good thing to have, and pretty conservative about not causing false positives. In particular, constructs like double-iteration should be fine:
for(y=0; y<ymax; y++)
for(x=0; x<xmax; x++)
{
//...
}
Which I checked because I like this construct and people very rarely think about it. for(y=0; y<ymax; y++)
{
for(x=0; x<xmax; x++)
{
//...
}
}
?Edit: Oh, I get it, {} are only "mandatory" if we have more than one instruction, the second for loop gets counted as one instruction and hence the omitting of {}. Thanks!
if (x)
y;
Is the same as: if (x) {
y;
} if (x) y;
also has the same meaning. for (i=0;i<imax;i++)
printf("%d\n", i);
You can omit the braces if the body of the loop is a single block, just like an if statement. You can also do this: if (a == b)
if (b == c)
{
do_thing();
}
Same deal with the for loop. The nested loop is a single block.braces—{}—allow you to take multiple lines of code and have them be guarded at the same time rather than having to repeat the condition. GP is taking advantage of the fact that the next for clause will be considered a single statement, and therefore the second set of braces are not technically needed.
However, omitting braces for single-line snippets has caused plenty of havoc in the past (cf. Apple's gotofail). Some would say it is better to always include braces in control flow.
namespace SomeNamespace {
class SomeClass
{
//...
}}
Which avoids having shifted the whole file an extra indent level to the right. But I haven't seen anyone else doing this. package{
class{
main{
now we indent
}
}}https://github.com/apache/spark/blob/master/core/src/main/ja...
And it's fair enough to indent with a main since it is so infrequent. Ideally you only have one main entry point.
For instance, consider how "break" or "continue" inside the braces would work.
The behaviour of 'break' might be confusing but then that's always the case in nested loops, no matter how you notate them.
I agree that it would be very bad form to use "break" inside a block like that. But in the cases where this construct applies, it would still be bad form to break if the outer block had curly braces and indentation, because skipping the rest of a row isn't a natural operation in the sort of way that skipping the rest of a collection is.
for(y=0; y<ymax; y++)
printf("y=%i\n",y);
for(x=0; x<xmax; x++)
{
//...
}
And it will not work anymore as intended.Granted it's a small mistake and it will not take more than 5 minutes to fix, but it still add a small load to your already busy mind.
for(int y=0; y < ymax; y++)
...
and didn't shadow y from an enclosing scope, that would have given the compiler a chance to catch that error. for(i=0; i<imax; i++)
printf("i=%i\n",i)
{
//...
}
Which also compiles and which is wrong in the same way. I don't recall ever having made or having seen this.It's almost like everybody forgot about https://matt.sh/howto-c#_formatting already. :(
I'm not convinced. Even iterating over a 2D grid, one loop is iterating over the columns, and the other the rows, and indentation (and braces) can help see which is which.
Man's gotta have an opinion. At least C doesn't have optional semi-colons.
static int
next_pixel(*x, *y, width, height) {
(*x)++;
...
if (last pixel...)
return 0;
return 1;
}
/* later on... */
do {
/* do something with coordinates x, y */
} while (next_pixel(&x, &y, WIDTH, HEIGHT));
This is, of course, not only restricted to 2D arrays, but could cover walking of a tree or a filesystem... for(y=0; y<ymax; y++) {
for(x=0; x<xmax; x++) {
//...
}
}if(0 != (i = getValue()))
> if (i = 0)
instead of
> if (i == 0)
if ((i = getValue())) if (0 != (0 != (i = getValue()))) if (condition) {
foo();
bar();
baz(); }These checks absolutely should be part of the compiler (and this isn't a stylistic warning; it's a correctness warning). Our software ecosystem would have been in a far worse place if C compiler developers had decided to not support the -Wall switch in favor of lint(1). There's a lot more friction involved with using an external tool compared to just modifying CFLAGS.
Clang lets you write plugins (which at least solves the code reuse problem), however, these are currently strongly coupled to the compiler version itself. See for example, the chromium guide to writing clang plugins "Don't Write A Clang Plugin"[1]
https://chromium.googlesource.com/chromium/src/+/master/docs...
If not for anything else, then for the fact that yi{ will _always_ yank the current block for me. Omitting braces will ruin this.
Running astyle would make it worse because you would hide the bug.
THIS IS WHY YOU SHOULD NOT USE -Werror. NOT EVER. (And if you can't bring yourself to do anything about mere warnings, you shouldn't be in software engineering.)
> This new warning isn't enabled by default.
And even if it were, it's a matter of adding -Wno-misleading-indentation to make builds green again. Not a big deal. And besides, it's likely that fixing those warnings could be done mechanically. (and it's hardly true that every project that ships with -Werror has such misleading indentation somewhere in its code)
How does that help the person who is building the release you shipped six months ago with a new compiler?