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.
Related
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.
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.
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.
When the following bit of code is compiled with the diab c++ compiler (dplusplus), it generates a conversion warning on the third line. It can be resolved by casting the result of the (&&) operator to anything other than bool.
Code:
bool first = 1;
bool second = 1;
bool ret = (first && second); //generates compile warning
Error:
warning: (etoa:1643): narrowing or signed-to-unsigned type conversion
found: int to unsigned char
I verified that nothing is defining bool to another type. Does this look like a compiler issue, or is there something else I might be missing that could cause this?
Wind River's web site indicates that the Diab compiler can compile either C or C++.
In C, the && operator yields a result of type int, with the value 0 or 1. That's consistent with the warning you're seeing.
As of the 1990 ISO standard, C did not have a built-in bool type. It was common to define bool as a typedef. It appears from the message that bool is a typedef for unsigned char, probably in some header. The 1999 ISO C standard adds a new predefined boolean type called _Bool; the identifier bool is defined in <stdbool.h> as a macro that expands to _Bool. But if <stdbool.h> isn't included, bool can be defined in some other way.
In C++, && yields a result of type bool with the value false or true, and bool is a distinct fundamental type. This has been the case at least since the 1998 ISO C++ standard.
I strongly suspect you're getting this warning because you're compiling your code as C rather than as C++. A less likely possibility is that the Diab compiler doesn't fully conform to the C++ standard; it might have a way to tell it to conform more closely.
I haven't used the Diab compiler. Typically you can control the language being compiled by using a particular file extension (typically .c for C and .cpp for C++), or by using a different command, or both.
Consult the compiler's documentation to find out how to invoke it as a conforming C++ compiler.
As an experiment, before changing the way you invoke the compiler, you might try adding a declaration:
int class;
to your source file. This is legal in C, but a syntax error in C++ (since class is a C++ keyword).
UPDATE:
The OP says he's definitely compiling as C++, not as C. But the warning message implies that && yields int, and that bool is the same type as unsigned char.
A warning doesn't directly indicate that the compiler is not conforming; compilers can warn about anything they like. But the content of this warning does suggest a compiler bug, or at least a compiler that doesn't conform to any C+
Any conforming C++ compiler must produce diagnostics for this program. What does your compiler do? (Please don't add any #include directives.)
int main() {
class dummy { }; // Just to make sure it's C++
bool b;
unsigned char c;
bool* pb = &c; // Invalid conversion
unsigned char* pc = &b; // Invalid conversion
}
And what output do you get when you compile and execute this program?
#include <iostream>
int main() {
std::cout << "__cplusplus = " << __cplusplus << "\n";
}
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.