How to raise a warning if the return value is not taken into account?

I would like to see all the places in my code (C ++) that do not take into account the return value of the function. How can I do this - using gcc or static code analysis?

Bad code example:

int f(int z) { return z + (z*2) + z/3 + z*z + 23; } int main() { int i = 7; f(i); ///// <<----- here I disregard the return value return 1; } 

Note:

  • it should work even if the function and its use are in different files.
  • free static verification tool
+41
c ++ c gcc static-analysis
Jan 11
source share
7 answers

You need the GCC attribute warn_unused_result :

 #define WARN_UNUSED __attribute__((warn_unused_result)) int WARN_UNUSED f(int z) { return z + (z*2) + z/3 + z*z + 23; } int main() { int i = 7; f(i); ///// <<----- here i disregard the return value return 1; } 

Attempting to compile this code produces:

 $ gcc test.c test.c: In function `main': test.c:16: warning: ignoring return value of `f', declared with attribute warn_unused_result 

This can be seen in the Linux kernel ; they have a __must_check macro that does the same; It looks like you need GCC 3.4 or higher for this. Then you will find this macro used in kernel header files:

 unsigned long __must_check copy_to_user(void __user *to, const void *from, unsigned long n); 
+47
Jan 11
source share

As far as I know, there is no GCC option for warning. However, if you are interested in certain functions, you can mark them with an attribute:

 int fn() __attribute__((warn_unused_result)); 

which would give a warning if the return value of fn () was not used. Caveat: I never used this function myself.

+10
Jan 11
source share

You can use this handy template to execute at runtime.

Instead of returning an error code (e.g. HRESULT), you return return_code <HRESULT>, which claims to be out of scope without a readable value. This is not a static analysis tool, but it is nonetheless useful.

 class return_value { public: explicit return_value(T value) :value(value), checked(false) { } return_value(const return_value& other) :value(other.value), checked(other.checked) { other.checked = true; } return_value& operator=(const return_value& other) { if( this != &other ) { assert(checked); value = other.value; checked = other.checked; other.checked = true; } } ~return_value(const return_value& other) { assert(checked); } T get_value()const { checked = true; return value; } private: mutable bool checked; T value; }; 
+10
Jan 11
source share

Any static analysis code (like PC-Lint ) should be able to tell you that. For PC-Lint, I know that it is.

+4
Jan 11
source share

a static analyzer will do the job for you, but if your code base is more trivial, prepare for congestion; -)

+4
Jan 11
source share

A static analyzer will be your best choice here. We use Coverity here, but there are free tools that you can also use.

If you need a quick and dirty solution, and you have a Linux-style shell, you can try something like:

 grep -rn "function_name" * | grep -v "=" 

This will find every line that refers to the specified function, but does not contain "=". You can get a lot of false positives (and maybe some false negatives), but if you don't have a static analyzer, this is a good place to start.

+4
Jan 11
source share

The classic lint program was used for very problematic functions that returned a value that was ignored. The problem was that many of these warnings were undesirable - leading to excessive noise in the output stream (it was collecting pieces of fluff that you wanted it to ignore). This is probably why GCC does not have a standard warning for it.

Another problem - the flip side - is "how do you suppress the warning when you know that you are ignoring the result, but actually it’s all the same." The classic script for this:

 if (signal(SIGHUP, SIG_IGN) != SIG_IGN) signal(SIGHUP, sighandler); 

You care about the first result from signal() ; you know that the second will be SIG_IGN (since you just set it). To get away from warnings, I sometimes use some option:

 if ((old = signal(SIGHUP, SIG_IGN)) != SIG_IGN) old = signal(SIGHUP, sighandler); 

This assigns old both times. You can follow this with "assert (old == SIG_IGN)".

+2
Jan 11 '10 at 16:48
source share



All Articles