Back to index
Last updated Saturday, August 20, 2016

I originally wrote this on Friday, August 19, 2016. I originally had it on https://xexyl.net but I think it is more fitting here on https://essays.xexyl.net.

On August 18 I decided to upgrade from Fedora 23 to Fedora 24 even though I was dreading the entire process; I have legitimate reasons to not trust the Fedora devs but I also don't want to find another distribution because it's frankly a bloody waste of time (and I don't like Ubuntu by principle and in any case I didn't much like Debian even if it has been years since I last tried it). Of course the upgrade was botched but I was able to salvage it by thinking the entire process through and not doing it all at once (I put it off until earlier today, August 19).

But there is another thing which is a bloody waste of time and it too has to do with software developers and in this case the GCC devs. They had this idea to introduce a new warning enabled by -Wall (and unless I missed it in the man page there isn't a way to disable it individually but even if there is it shouldn't be enabled by -Wall). -Wall should be encouraged. But what do I see but (and I knew about this change but I didn't think it'd be as annoying and/or brain dead as it is - and I would have to upgrade eventually anyway) problems with this new warning which is '-Wmisleading-indentation' by itself (but again is enabled by default when passed '-Wall'). The following is from the gcc man page on the warning:

-Wmisleading-indentation (C and C++ only)

Warn when the indentation of the code does not reflect the block structure. Specifically, a warning is issued for "if", "else", "while", and "for" clauses with a guarded statement that does not use braces, followed by an unguarded statement with the same indentation.

In the following example, the call to "bar" is misleadingly indented as if it were guarded by the "if" conditional.

if (some_condition ())
foo ();
bar (); /* Gotcha: this is not guarded by the "if". */

In the case of mixed tabs and spaces, the warning uses the -ftabstop= option to determine if the statements line up (defaulting to 8).

The warning is not issued for code involving multiline preprocessor logic such as the following example.


	     if (flagA)
	       foo (0);
	   #if SOME_CONDITION_THAT_DOES_NOT_HOLD
	     if (flagB)
	   #endif
	       foo (1);
    

The warning is not issued after a "#line" directive, since this typically indicates autogenerated code, and no assumptions can be made about the layout of the file that the directive references.

This warning is enabled by -Wall in C and C++.

So what is my problem with this? It is after all true it can 'mislead' some people (I'm inclined to say only people who can't read C or perhaps are too rushed or exhausted, the latter of which I don't buy because I am very often that state - and in fact currently am - but I have no problem reading the supposedly misleading code which prompted me to write this). My problems:

  1. It is enabled by -Wall (with seemingly no way to disable).
  2. It could potentially discourage -Wall (because it's frustrating and time consuming fixing code which doesn't need fixing).
  3. Working code which is known to work needn't be (and shouldn't be) tampered with without an actual code change (formatting of the code itself doesn't count).
  4. Slightly related to #3 is having to go through and 'fix' all the code - which is itself (more) error prone while leaving it the hell alone is not at all error prone; going through all the code is a waste of time too. And updating the formatting of text means diff output will show it too. Why would that matter? Because the fact there is a difference makes one think there might be a reason for it - and even though the formatting of the code is the only change there still is that change. And it's a nightmare in that I have working changes in code and now I have to ironically throw in misleading and/or useless changes (and functionality of revision control shouldn't have to be used for formatting).

Ignoring warnings is not wise and it also over time makes it a habit; then what happens when you ignore a legitimate warning? And if you have -Werror (turning warnings into errors which also has merit depending on which warnings are enabled and what you are compiling) it isn't any better (unless you ignore warnings in which case you probably won't have -Werror enabled anyway if even -Wall).

The below code and warning demonstrates the warning. It might seem petty and it might seem like a silly 'error' in the format but it likely would happen over time and possibly by different developers. But anyone who can't read the code arguably has a lot to learn and practise. I have two demonstrations: the first is from an actual piece of code in a project of mine but made into a single source file (removing the need to understand context by including only the variables in the 'misleading code' and simplifying an 'if' condition); the second is me being silly and is in the file 'mislead.c' found here (it includes in comments the warning issued by GCC). The first example is this (the source can also be found here):

#include <libxml2/libxml/xmlmemory.h>
#include <libxml2/libxml/parser.h>
#include <libxml2/libxml/xpath.>

int main()
{
    xmlDocPtr file = NULL;
    int status = 1;

    if (file)
      xmlFreeDoc(file);

      if (status)
	return 0;
      else
	return 1;
}

Note I normally wouldn't have the second if/else because I could just invert the status variable for the return value; in the real code (with context irrelevant to this document) it is a bit more complex (although it too could be turned into a single return statement but this way is convenient since it demonstrates the issue).

What is the warning generated? Compile the code like so:

$ gcc -Wall -I/usr/include/libxml2 mislead-xml.c -o mislead-xml -lxml2
mislead-xml.c: In function ‘main’:
mislead-xml.c:10:5: warning: this ‘if’ clause does not guard... [-Wmisleading-indentation]
     if (file)
     ^~
mislead-xml.c:13:7: note: ...this statement, but the latter is misleadingly indented as if it is guarded by the ‘if’
       if (status)
       ^~

So what is GCC actually having a problem with? The only thing 'wrong' here is the call to 'xmlFreeDoc' is at the same column as the 'if (status)' below it. The fact GCC warns about this means essentially it wants you to use '{}' (surrounding 'xmlFreeDoc(file);' or the 'if (status) .. else ..') or change the column of the 'xmlFreeDoc' call or the 'if' check (so that they no longer are at the same column).

This is nothing but style policing (they as good as say this in the man page but in a more favourable way); the code is is clear but the warning suggests there might be a problem. The programmer now needs to look at the code, evaluate the situation and then 'fix' it to shut GCC up.

It might also as a side effect actually confuse inexperienced C programmers. Whether this is reported or not doesn't change the possibility. Yes it most certainly is possible: they might change it to something else (because they might now distrust themselves more) and in the process cause a compiler error, more warnings or even introduce a bug all without fully realising it. Another possibility is they (who might not even be a programmer so much as a user but with just enough knowledge to make slight changes but certainly not enough to read compiler warnings and errors) try another person's code first, see it works well but want to make a slight change (maybe a string?) and then they go on to compile it and suddenly the compiler is warning them it might be incorrect; what should they do? Just because something is not in the same scope/linkage does not mean it can't cause problems elsewhere; they might not have touched the bad code (or maybe the suspect code references what they changed?) but even if they haven't it could cause them to question themselves. That isn't the slightest bit productive. If there has to be a warning don't tie it to '-Wall'! I'm somewhat inclined to say this decision is completely stupid but I'll err on saying it was very poorly thought out and is extremely misguided and unhelpful (potentially harmful); I would say the latter is in fact the truth. On the other hand, I might also suggest aliases for the option:

  1. -Wobfuscate-compiler-output (which is not to say compiler output doesn't confuse many people)
  2. -Wannoy-obfuscators (it might possibly help IOCCC contestants to enable -Wall in their Makefile to add confusion although only for those unfortunate enough to run GCC 6 and of those who don't know to remove -Wall).
  3. -Wwaste-time-and-effort
  4. -Wconfuse-inexperienced
  5. -Wpotentially-break-code
  6. -Wstyle-police

I quite like the first three but especially the first because GCC output already can be obfuscated (and is to those who don't have experience reading the output); the third is 100% accurate too. The second is true but only if passing -Wall (which wouldn't be necessary for the final Makefile for submission). This is not to say the others aren't also equally valid; they all are (except maybe 2 but I had to throw it in anyway) 100% valid. Of course these aliases are quite deliberately ridiculous because the warning itself is ridiculous.

Some might ask why I don't file a bug for this. The reason is it is it's also a waste of time; by the time it's fixed (if it is) all the code I work on will have been fixed. Someone might suggest it in the meantime and until then I'll have to be more careful lest I trick the compiler into thinking I don't know how to write basic C - or confusing people with extremely limited C experience. Maybe it is because I'm a cynic or maybe it is because some developers (like those of GNOME or systemd) are too full of themselves but I question whether it is worth my time bothering; it probably should be mentioned to them but I don't have the time or patience and I don't see this changing any time soon (though I note I could have reported this in the time I wrote this I was too irritated to positively file a bug report).