disable enum assignment g++ in if statement - c++

I would like to treat assignment in an if statement as error:
#include <cstdio>
enum some {
a,
b
};
void foo(some e) {
if (e = a) {
puts("yes");
} else {
puts("no");
}
}
int main() {
foo(a);
return 0;
}
This seems like a sane thing to do, except that I'd like to have something like this too:
boost::optional<int> optionalValue;
if (const auto& value = optionalValue) {
}
-Wall gives me enum.cpp:9: warning: suggest parentheses around assignment used as truth value, but I would like to have something more specific than -Wall

You could declare e to be const. Then assignment would be an error.
Or, you can tell g++ to treat warnings as errors with -Werror. Then, coupled with the appropriate warning setting, any assignment in a if expression will be an error. You can enable only this class of warnings with -Wparentheses However, do note that sometimes it's not a mistake, but done on purpose. Which is why g++ suggests using parentheses to disambiguate from accidental assignment.

If you use a more recent version of g++ then it tells you which warning flag corresponds to which diagnostic. Using g++ 4.9.2 your code gives :
m.cc:9:14: warning: suggest parentheses around assignment used as truth value [-Wparentheses]
This tells you that the error comes from the flag -Wparentheses, which is a subset of -Wall.
You can instruct g++ to treat all warnings as errors by using -Werror. But if you only want to treat this particular warning as an error then you can use:
-Werror=parentheses
This version of g++ does not warn for your suggested code const auto& value = optionalValue, so perhaps it's time to upgrade your compiler version.

Related

Compiler not warns about "int in bool context"

In my project I changed many of our function's return value from bool to enum value
The problem is in the integration. The compiler doesn't warn me about wrong use of the functions.
I'm using g++ (with c++14) and with "-Wall -Wextra -Werror" flags
Lets see an example which produces the warning:
typedef enum {
VALUE_1,
VALUE_2,
VALUE_3
} MY_ENUM;
bool bar() {
return VALUE_3;
}
So in this example we return VALUE_3 and get error correctly: error: enum constant in boolean context [-Werror=int-in-bool-context]
But, if we change this example a bit, the compiler will not produce any errors:
typedef enum {
VALUE_1,
VALUE_2,
VALUE_3
} MY_ENUM;
MY_ENUM foo() {
return VALUE_3;
}
bool bar() {
return foo();
}
Of course I understand that enum is type of int, and bool is a type of int so the compiler can process it. But at least I expect for some kind of warning?
Tried with clang too, same results with both examples.
The problem in my project is that I changed about ~150 function's return values, and there are about ~300 calling. So without any warnings I easily miss some...
Can I get it somehow to yell at me?
Couple Ideas:
Have a look here at some different flags:
https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
Add in -Wextra. The site says not all warnings are explicitly added by -Wall and may need explicitly added. Note implicit conversion for enum is c only. Looks like you tagged c++.
Also see
Warnings or errors for C++ implicit conversion of primitives
about primitive conversions.
Enum class will not convert to int if you want to be really specific about using the enum value and therefore will give an error in bool context.
Hope this gets you somewhere.

Calling a function with uninitalized struct variable as a parameter doesn't produce a warning

I have the following code in c++:
#include <iostream>
typedef struct Pair{
int x;
int y;
}Pair;
void dumFun(Pair p){}
int main() {
Pair p;
if (0){
p = {1,2};
}
dumFun(p);
return 0;
}
When I compiled the code, I expected to get a warning for the line with dumFun(p) since I'm calling a function with an uninitialized variable.
What I actually want is that my Makefile will give me warning for uninitialized scalar variable issues that I see with the tool Coverity.
Tried to use flag -Wall and I thought it shows warnings for unused variables usage as this - but it doesn't.
Is there any flag to use on a Makefile that will show me warning for the line I wrote above?
You did not tell the compiler, but at least in Clang there is no warning that would catch this. -Weverything shows all possible warnings, and you can use it to find the specific parameter needed to trigger each warning. Demonstration with -Weverything shows no warnings.
I did not find a suitable parameter in GCC either.

How can I enforce an error when a function doesn't have any return in GCC?

Is it possible to enforce an error (to break the build) when a function definition has no return in its body?
Consider this function:
int sum(int a, int b) {
int c = a + b;
// And here should be return
};
When I compile with g++ -Wall, I get:
no return statement in function returning non-void [-Wreturn-type]
But I want this to be a hard error rather than a warning.
I'm currently using GCC 4.9.2, but if there's a solution for different version of GCC that would be helpful to know, too.
GCC has the option -Werror to turn all warnings into errors.
If you want to upgrade only a specific warning, you can use -Werror=X, where X is the warning type, without the -W prefix. In your particular case, that would be -Werror=return-type.
Note that this will only report a missing return in a function that returns a value. If you want to enforce that return; must be explicitly written in a function returning void, you may be out of luck.

How to get around GCC ‘*((void*)& b +4)’ may be used uninitialized in this function warning while using boost::optional

I have code similar to the following:
#include <boost/optional.hpp>
::boost::optional<int> getitem();
int go(int nr)
{
boost::optional<int> a = getitem();
boost::optional<int> b;
if (nr > 0)
b = nr;
if (a != b)
return 1;
return 0;
}
When compiling with GCC 4.7.2 with Boost 1.53, using the following command:
g++ -c -O2 -Wall -DNDEBUG
The following warning is issued:
13:3: warning: ‘((void)& b +4)’ may be used uninitialized in this function [-Wmaybe-uninitialized]
Apparently, the root problem lies with GCC. See GCC Bugzilla
Does anyone know a workaround?
There are two levels of uninitialized analysis in gcc:
-Wuninitialized: flags variables that are certainly used uninitialized
-Wmaybe-uninitialized: flags variables that are potentially used uninitialized
In gcc (*), -Wall turns on both levels even though the latter has spurious warnings because the analysis is imperfect. Spurious warnings are a plague, so the simplest way to avoid them is to pass -Wno-maybe-uninitialized (after -Wall).
If you still want the warnings, but not have them cause build failure (through -Werror) you can white list them using -Wno-error=maybe-uninitialized.
(*) Clang does not activate -Wmaybe-uninitialized by default precisely because it's very imprecise and has a good number of false positives; I wish gcc followed this guideline too.
I have found that changing the construction of b into the following (effectively equal) code:
auto b = boost::make_optional(false,0);
eliminates the warning. However, the following code (which is also effectively equal):
boost::optional<int> b(false,0);
does not eliminate the warning.
It's still a little unsatisfactory...
Had the same issue with this piece of code:
void MyClass::func( bool repaint, bool cond )
{
boost::optional<int> old = m_sizeLimit; // m_sizeLimit is a boost::optional<int> class attribute
if ( cond )
m_sizeLimit = 60;
else
m_sizeLimit.reset();
if ( repaint )
{
if ( old != m_sizeLimit ) // warning here
doSomething();
}
}
Could not get rid of the warning with Paul Omta answer, tried to write:
boost::optional<int> old;
if ( m_sizeLimit )
old = boost::make_optional<int>(true, m_sizeLimit.value());
else
old = boost::make_optional<int>(false, 0);
...with no success.
Did not want to completely disable the warning from my code, so I found an alternative solution I would recommend: disable the warning locally:
#ifdef SDE_MOBILE
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
#endif
if ( old != m_sizeLimit ) // warning here
doSomething();
#ifdef SDE_MOBILE
#pragma GCC diagnostic pop
#endif
I had a type which wasn't easily constructed so didn't want to go the boost::make_optional route. Assigning an auto variable using the return from a function got around this problem for me. So you can do:
boost::optional<Foo> Default()
{
return boost::none;
}
auto var(Default());
This will also work as a one line lambda so you can just do:
auto var([]()->boost::optional<Foo> { return boost::none; }());

g++ How to get warning on ignoring function return value

lint produces some warning like:
foo.c XXX Warning 534: Ignoring return value of function bar()
From the lint manual
534 Ignoring return value of function
'Symbol' (compare with Location) A
function that returns a value is
called just for side effects as, for
example, in a statement by itself or
the left-hand side of a comma
operator. Try: (void) function(); to
call a function and ignore its return
value. See also the fvr, fvo and fdr
flags in §5.5 "Flag Options".
I want to get this warning, if there exists any, during compilation. Is there any option in gcc/g++ to achieve this? I had turned on -Wall but that apparently did not detect this.
Since C++17 you can use the [[nodiscard]] attribute.
Example:
[[nodiscard]] int bar() {
return 42;
}
Thanks to WhirlWind and paxdiablo for the answer and comment. Here is my attempt to put the pieces together into a complete (?) answer.
-Wunused-result is the relevant gcc option. And it is turned on by default. Quoting from gcc warning options page:
-Wno-unused-result
Do not warn if a caller of a function marked with attribute warn_unused_result (see
Variable Attributes) does not use its return value. The default is -Wunused-result
So, the solution is to apply the warn_unused_result attribute on the function.
Here is a full example. The contents of the file unused_result.c
int foo() { return 3; }
int bar() __attribute__((warn_unused_result));
int bar() { return 5; }
int main()
{
foo();
bar(); /* line 9 */
return 0;
}
and corresponding compilation result:
$gcc unused_result.c
unused_result.c: In function ‘main’:
unused_result.c:9: warning: ignoring return value of ‘bar’, declared with attribute warn_unused_result
Note again that it is not necessary to have -Wunused-result since it is default. One may be tempted to explicitly mention it to communicate the intent. Though that is a noble intent, but after analyzing the situation, my choice, however, would be against that. Because, having -Wunused-result in the compile options may generate a false sense of security/satisfaction which is not true unless the all the functions in the code base are qualified with warn_unused_result.
-Wunused-result should do this for you. This isn't one of the warnings -Wall turns on:
http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
The function has to have the warn_unused_result attribute applied to it (Thanks paxdiablo).
The answers about using __attribute__((warn_unused_result)) are correct. GCC isn't so good at this functionality, though! Be aware: it will not warn for non-POD types. That means, for example, if you return a class with a destructor (or a class with instance variables with destructors) you'll never see a warning about ignoring the result.
Relevant bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66177
Example where it fails:
struct Error {
~Error();
};
__attribute__((warn_unused_result)) Error test();
int main()
{
test();
return 0;
}
So, don't rely on this for return types which aren't pretty simple.
I solved the problem like this:
#define ignore_result(x) if (x) {}
then instead of (void)foo() use ignore_result(foo())
Then the code compiles with -Wall just fine.