Detecting "=" instead of "==" typo in if condition - c++

Is there a way to make g++ yield a compilation error if I use = instead of == inside of an if condition in c++? I've made this typo a couple times, and it's annoying to track down. That is:
if (x=5){ //bad - sets x equal to 5
//do something
}

-Wparentheses option specifically warns such cases, which is also a part of -Wall option.
From gcc documentation:
-Wparentheses
Warn if parentheses are omitted in certain contexts, such as when there is an assignment in a context where a truth value is expected,
or when operators are nested whose precedence people often get
confused about.
...
When there is the potential for this confusion, GCC will issue a warning when this flag is specified. To eliminate the warning, add explicit braces around the innermost if statement so there is no way the else could belong to the enclosing if.
which can converted into an error using by specifying -Werror=parentheses.
Note that
if(x=5) {...}
is legal and standard requires no such diagnostics. But an implementation is allowed to provide any number of such useful warnings.

You can address this with a different coding style: a lot of programmers I know prefer to use the style if (5 == x) for this reason, because if you forget an equals sign then you get if (5 = x) which does not compile (5 is not an lvalue).
Aside from being a bit simpler than tinkering with compiler options, it is also portable to any standard C++ compiler.
IMO, the only downside is that it doesn't read as naturally if you're not used to it; in English it's more common to say "if x is equal to 5" instead of "if 5 is equal to x." Of course since equality is commutative, both are correct, but most people prefer the former. This is one of those cases where something that seems wrong from a stylistic perspective does help you write more maintainable code.

The Yoda condition is a simple, compiler independant solution: if (5=x){statement} will not compile.

Related

How to enable C++ warnings for bitwise operators with boolean arguments

While working with a rather large C++ code base and the GCC toolchain on Linux, I have encountered code which performs a boolean check as follows:
#include <stdio.h>
int main() {
bool foo = true;
if (~foo) {
// do some expensive operation
printf("This can be bad...\n");
}
return 0;
}
This looks like an obvious bug, since the ~ operator represents bit-wise NOT in C++, and not logical NOT, as it would, say, in MATLAB. The above code would always evaluate to true
Luckily, the issue caused by this bug was not major (it was just a small performance hit), but it got me thinking about how this bug hadn't been found in so much time.
Since the bit-wise operator triggers an implicit cast from the boolean to an integer, which is a promotion, there's nothing wrong with it per se. However, to me it seems as though at least something like clang-tidy should be able to pick this up as a logical error, since it is pretty clear that in most cases, the intent is not to apply a bit-wise operation to a bool, but instead a logical one.
g++ doesn't seem to care about this issue even with -Wall -Wextra -Wconversion enabled, which is sensible given that, as I mentioned before, this isn't against the standard. (I even tried g++ 6.3, which should have a lot of new checks, and still got nothing.)
Using clang-tidy with all checks enabled (which can get really noisy really fast) does warn about the implicit conversion itself ("implicit cast bool -> 'int'"), but there doesn't seem to be a specific warning related to applying bit-wise operators to booleans.
Writing the if-statement differently as if(~foo == true), while verbose and leading to an always-false scenario, does lead to more meaningful errors which can bring the bug into attention, but this doesn't happen when the terser if(~foo) form is used.
Are there any ways/tools to check for such issues, which are 100% correct C++, but very likely bugs?
There is -Wbool-operation in gcc as of gcc 7:
Warn about suspicious operations on expressions of a boolean type. For instance, bitwise negation of a boolean is very likely a bug in the program. For C, this warning also warns about incrementing or decrementing a boolean, which rarely makes sense. (In C++, decrementing a boolean is always invalid. Incrementing a boolean is invalid in C++1z, and deprecated otherwise.)
This warning is enabled by -Wall.
It provides the following warning for your program:
prog.cc:6:9: warning: '~' on an expression of type bool [-Wbool-operation]
if (~foo) {
^~~
prog.cc:6:9: note: did you mean to use logical not ('!')?
gcc demo
Unfortunately it does not appear that clang 5 has such an option. Even turning on (quite nearly) all of the possible warnings listed here, we still don't get the expected warning (Demo) (although we do get a few interesting others).
Finally, for completeness, MSVC 19.00.23506 definitely warns (Demo) (credit to #cbuchart for pointing this out):
source_file.cpp(8): warning C4804: '~': unsafe use of type 'bool' in operation

Why isn't g++ -Wreorder smarter?

Looking at What's the point of g++ -Wreorder, I fully understand what -Wreorder is useful for. But it doesn't seem unreasonable that the compiler would be able to detect whether such a reordering is harmless:
struct Harmless {
C() : b(1), a(2) {}
int a;
int b;
};
or broken:
struct Broken {
C() : b(1), a(b + 1) {}
int a;
int b;
};
My question is then: why doesn't GCC detect (and warn about) the actual use of an undefined member in an initializer instead of this blanket warning on the ordering of initializers?
As far as I understand, -Wuninitialized only applies to automatic variables, and indeed it does not detect the error above.
EDIT:
A stab at formalizing the behavior I want:
Given initializer list : a1(expr1), a2(expr2), a3(expr3) ... an(exprn), I want a warning if (and only if) the execution of any of the initializers, in the order they will be executed, would reference an uninitialized value. I.e. in the same manner as -Wuninitialized warns about use of uninitialized automatic variables.
Some additional background: I work in a mostly windows-based company, where basically everybody but me uses Visual Studio. VS does not have this warning, thus nobody cares about having the correct order (and have no means of knowing when they screw up the ordering except manual inspection), thus leaving me with endless warnings that I have to constantly fix everytime someone breaks something. I would like to be informed about only the cases that are really problematic and ignore the benign cases. So my question is maybe better phrased as: is it technically feasible to implement a warning/error like this? My gut feeling says it is, but the fact that it isn't already implemented makes me doubt it.
My speculation is that it's for the same reason we have -Wold-style-cast: safety erring on the side of being too conservative. All it takes is a moment's inattention to transform Harmless into CarelessMistake. Maybe this developer's in a hurry or has an older version of GCC or sees that it's "just a warning" and presses on.
This is basically true among many warnings. They often are spurious, and require a little bit of restructuring to compile cleanly, but on some occasions they represent real problems. Every good programmer will prefer some working through some false positives if that means they get fewer false negatives.
I would be surprised if there's a valid direct answer to the question. There's no technical reason I see that it couldn't be done. It's just . . . why bother trying to figure out if something questionable is actually okay? Programming is the human's job.
As a personal reason, I think initializing variables in the order you declare them often makes sense.

What is the difference between these (bCondition == NULL) and (NULL==bCondition)? [duplicate]

This question already has answers here:
What's the reasoning behind putting constants in 'if' statements first?
(8 answers)
Closed last month.
While exploring msdn sites ,most of the condition checking places they are using (NULL == bCondition).
what is the purpose of using these notations?
Provide some sample to explain these please.
Thanks.
The use of NULL == condition provides more useful behaviour in the case of a typo, when an assignment operator = is accidentally used rather then the comparison operator ==:
if (bCondition = NULL) // typo here
{
// code never executes
}
if (NULL = bCondition) // error -> compiler complains
{
// ...
}
C-compiler gives a warning in the former case, there are no such warnings in many languages.
It's called Yoda Conditions. (The original link, you need high rep to see it).
It's meant to guard against accidental assignment = in conditions where an equality comparison == was intended. If you stick to Yoda by habit and make a typo by writing = instead of ==, the code will fail to compile because you cannot assign to an rvalue.
Does it worth the awkwardness? Some disagree, saying that compilers do issue a warning when they see = in conditional expressions. I say that it simply happened just two or three times in my lifetime to do this mistake, which does not justify changing all the MLOCs I wrote in my life to this convention.
There is no difference. It is an ancient way of defensive programming that has been obsolete for over 20 years. The purpose was to protect from accidentally typing = instead of == when comparing two values. Pascal programmers migrating to C were especially prone to write this bug.
From Borland Turbo C released in 1990 and forward, every known compiler warns against "possibly incorrect assignment", when you manage to type out this bug.
So writing (NULL == bCondition) is not better or worse practice than the opposite, unless your compiler is extremely ancient. You don't need to bother about writing them in any particular order.
What you should bother with, is to adapt a coding style where you never write assignments inside if/loop conditions. There is never a reason to do so. It is a completely superfluous, risky and ugly feature of the C language. All industry de-facto coding standards ban assignment inside conditions.
References:
MISRA C:2004 13.1
CERT C EXP18-C
Many people prefer writing NULL == bCondition so that they accidently don't assign the NULL value to bCondition.
Because of typo it happens that instead of writing
bCondition == NULL
they end up writing
bCondition = NULL // the value will be assigned here.
In case of
NULL = bCondition // there will be an error
It's simply a good defensive measure. Some may also find it more convenient to read. In case of a mistyped assignment instead of the equality operator, the compiler will attempt to modify NULL, which is not an lvalue and will produce an error message. When using bCondition = NULL, the compiler might produce a warning about using an assignment as a truth value, a message which can get lost and go unnoticed.
While usually there is no difference between variable == value and value == variable, and in principle there shouldn't be, in C++ there sometimes can be a difference in the general case if operator overloading is involved. For example, although == is expected to be symmetric, someone could write a pathological implementation that isn't.
Microsoft's _bstr_t string class suffers from an asymmetry problem in its operator== implementation.

Expressions with no side effects in C++

See, what I don't get is, why should programs like the following be legal?
int main()
{
static const int i = 0;
i < i > i;
}
I mean, surely, nobody actually has any current programs that have expressions with no side effects in them, since that would be very pointless, and it would make parsing & compiling the language much easier. So why not just disallow them? What benefit does the language actually gain from allowing this kind of syntax?
Another example being like this:
int main() {
static const int i = 0;
int x = (i);
}
What is the actual benefit of such statements?
And things like the most vexing parse. Does anybody, ever, declare functions in the middle of other functions? I mean, we got rid of things like implicit function declaration, and things like that. Why not just get rid of them for C++0x?
Probably because banning then would make the specification more complex, which would make compilers more complex.
it would make parsing & compiling the
language much easier
I don't see how. Why is it easier to parse and compile i < i > i if you're required to issue a diagnostic, than it is to parse it if you're allowed to do anything you damn well please provided that the emitted code has no side-effects?
The Java compiler forbids unreachable code (as opposed to code with no effect), which is a mixed blessing for the programmer, and requires a little bit of extra work from the compiler than what a C++ compiler is actually required to do (basic block dependency analysis). Should C++ forbid unreachable code? Probably not. Even though C++ compilers certainly do enough optimization to identify unreachable basic blocks, in some cases they may do too much. Should if (foo) { ...} be an illegal unreachable block if foo is a false compile-time constant? What if it's not a compile-time constant, but the optimizer has figured out how to calculate the value, should it be legal and the compiler has to realise that the reason it's removing it is implementation-specific, so as not to give an error? More special cases.
nobody actually has any current
programs that have expressions with no
side effects in them
Loads. For example, if NDEBUG is true, then assert expands to a void expression with no effect. So that's yet more special cases needed in the compiler to permit some useless expressions, but not others.
The rationale, I believe, is that if it expanded to nothing then (a) compilers would end up throwing warnings for things like if (foo) assert(bar);, and (b) code like this would be legal in release but not in debug, which is just confusing:
assert(foo) // oops, forgot the semi-colon
foo.bar();
things like the most vexing parse
That's why it's called "vexing". It's a backward-compatibility issue really. If C++ now changed the meaning of those vexing parses, the meaning of existing code would change. Not much existing code, as you point out, but the C++ committee takes a fairly strong line on backward compatibility. If you want a language that changes every five minutes, use Perl ;-)
Anyway, it's too late now. Even if we had some great insight that the C++0x committee had missed, why some feature should be removed or incompatibly changed, they aren't going to break anything in the FCD unless the FCD is definitively in error.
Note that for all of your suggestions, any compiler could issue a warning for them (actually, I don't understand what your problem is with the second example, but certainly for useless expressions and for vexing parses in function bodies). If you're right that nobody does it deliberately, the warnings would cause no harm. If you're wrong that nobody does it deliberately, your stated case for removing them is incorrect. Warnings in popular compilers could pave the way for removing a feature, especially since the standard is authored largely by compiler-writers. The fact that we don't always get warnings for these things suggests to me that there's more to it than you think.
It's convenient sometimes to put useless statements into a program and compile it just to make sure they're legal - e.g. that the types involve can be resolved/matched etc.
Especially in generated code (macros as well as more elaborate external mechanisms, templates where Policies or types may introduce meaningless expansions in some no-op cases), having less special uncompilable cases to avoid keeps things simpler
There may be some temporarily commented code that removes the meaningful usage of a variable, but it could be a pain to have to similarly identify and comment all the variables that aren't used elsewhere.
While in your examples you show the variables being "int" immediately above the pointless usage, in practice the types may be much more complicated (e.g. operator<()) and whether the operations have side effects may even be unknown to the compiler (e.g. out-of-line functions), so any benefit's limited to simpler cases.
C++ needs a good reason to break backwards (and retained C) compatibility.
Why should doing nothing be treated as a special case? Furthermore, whilst the above cases are easy to spot, one could imagine far more complicated programs where it's not so easy to identify that there are no side effects.
As an iteration of the C++ standard, C++0x have to be backward compatible. Nobody can assert that the statements you wrote does not exist in some piece of critical software written/owned by, say, NASA or DoD.
Anyway regarding your very first example, the parser cannot assert that i is a static constant expression, and that i < i > i is a useless expression -- e.g. if i is a templated type, i < i > i is an "invalid variable declaration", not a "useless computation", and still not a parse error.
Maybe the operator was overloaded to have side effects like cout<<i; This is the reason why they cannot be removed now. On the other hand C# forbids non-assignment or method calls expresions to be used as statements and I believe this is a good thing as it makes the code more clear and semantically correct. However C# had the opportunity to forbid this from the very beginning which C++ does not.
Expressions with no side effects can turn up more often than you think in templated and macro code. If you've ever declared std::vector<int>, you've instantiated template code with no side effects. std::vector must destruct all its elements when releasing itself, in case you stored a class for type T. This requires, at some point, a statement similar to ptr->~T(); to invoke the destructor. int has no destructor though, so the call has no side effects and will be removed entirely by the optimizer. It's also likely it will be inside a loop, then the entire loop has no side effects, so the entire loop is removed by the optimizer.
So if you disallowed expressions with no side effects, std::vector<int> wouldn't work, for one.
Another common case is assert(a == b). In release builds you want these asserts to disappear - but you can't re-define them as an empty macro, otherwise statements like if (x) assert(a == b); suddenly put the next statement in to the if statement - a disaster! In this case assert(x) can be redefined as ((void)0), which is a statement that has no side effects. Now the if statement works correctly in release builds too - it just does nothing.
These are just two common cases. There are many more you probably don't know about. So, while expressions with no side effects seem redundant, they're actually functionally important. An optimizer will remove them entirely so there's no performance impact, too.

What does a "true;" or "10;" statement mean in C++ and how can it be used?

In C++ one can write any of the following statements:
10;
true;
someConstant; //if this is really an integer constant
or something like
int result = obtainResult();
result; // looks totally useless
The latter can be used to suppress a compiler warning "A variable is initialized but not referenced" (C4189 in VC++) if a macro that is expanded into an empty string in some configuration is later used with the result variable. Like this:
int result = obtainResult();
result;
assert( result > 0 ); // assert is often expanded into an empty string in Release versions of code
What's the meaning of such statements? How can they be used except for compiler warning suppression?
This kind of statements is a logical expansion of how other pieces of the language works. Consider having a function that returns a value, for example int foo(), that also has some side effects. Sometimes you only want those side effects to happen, so you write foo(); as a statement.
Now, while this does not look exactly like 10;, the function call will evaluate to an int sooner or later, and nothing happens to that int, just like with 10;.
Another example of the same issue is that since you can do a = b = 10;, that means b = 10 has to evaluate to 10, hence you can not do assignment without generating a value that has to be suppressed.
Being able to write such values as statements is just a logical way of building the language, but for the cases you present it might even be a good idea to give a compiler warning for it.
Unless you use it to suppress compiler warnings ;)
These statements (called expression-statements in the C++ grammar) are valid because they are expressions.
Expressions are all constructs that calculate some kind of value, such as
3 + 5
someVariable
someFunctionCall( 2 )
someVar += 62
val > 53
I think, to keep the grammar simple, they decided to not differentiate between those expressions that actually have a side effect (such as the function call or the assignment) and those that don't.
Such a statement does nothing, and will most likely be optimized away by any decent compiler.
It may be useful for getting rid of the unused variable warning, but with some compilers you may get a statement has no effect warning instead.
They have no practical use beyond compiler warning suppression, and in general the compiler will elide any such constant-value statement that has no side effect.
They are expressions that will be evaluated, assuming the compiler doesn't optimise them away. As for "meaning", I'm not sure what you "mean" by that!
In C and C++, a statement that is just an expression is evaluated.
The fact that the expression might be useless is harmless, and with the optimizer turned on can result in no code generated at all. However, as you've observed, it usually does count as use of a variable.
Note that statements containing only an expression are quite common. A simple function call is one, for example. In printf("hello, world.\n");, the return value of printf() is ignored but the function is still called and its intended effect (text output) happens.
Also, a variable assignment x = 3; is also a statement made up of a simple expression, since assignment is an operator and returns a value in addition to its side effect of modifying the lvalue.
Although legal I think these statements are confusing and should be avoided, even for suppressing warnings. For me it is more reasonable to suppress the warning using something like this:
int result = 0;
result = obtainResult();
assert (result > 0);
In some embedded enviroments accessing a read only register will have side effects, e.g. clearing it.
Writing int temp = IV; to clear it causes a warning because temp isn't used, in which case I write IV;
I agree with Magnus' answer. There is one thing that puzzles me though: why do you use this nonsense
int result = obtainResult();
result; // looks totally useless
to get rid of compiler warnings? In my humble opinion it is much worse NOT to have a warning in such situation. The result variable is still not used - you have just "swept the dirt under the carpet". This "lone variable" approach looks as if there was something missing (Have I accidently deleted something?). Why don't you use
(void)obtainResult();
in the first place? It assures anyone who would be reading your code that you do not care about the return result. It is very difficult to put this "accidently". Obviously this does not generate any compiler warnings.