Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to raise warning if return value is disregarded?

I'd like to see all the places in my code (C++) which disregard return value of a function. How can I do it - with gcc or static code analysis tool?

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; } 

Please note that:

  • it should work even if the function and its use are in different files
  • free static check tool
like image 232
Drakosha Avatar asked Jan 11 '10 15:01

Drakosha


2 Answers

You want GCC's warn_unused_result attribute:

#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; } 

Trying 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 

You can see this in use in the Linux kernel; they have a __must_check macro that does the same thing; looks like you need GCC 3.4 or greater for this to work. Then you will find that macro used in kernel header files:

unsigned long __must_check copy_to_user(void __user *to,                                         const void *from, unsigned long n); 
like image 70
Eric Seppanen Avatar answered Oct 26 '22 10:10

Eric Seppanen


For C++17 the answer to this question changes since we now have the [[nodiscard]] attribute. Covered in [dcl.attr.nodiscard]:

The attribute-token nodiscard may be applied to the declarator-id in a function declaration or to the declaration of a class or enumeration. It shall appear at most once in each attribute-list and no attribute-argument-clause shall be present.

and

[ Example:

struct [[nodiscard]] error_info { /* ... */ }; error_info enable_missile_safety_mode(); void launch_missiles(); void test_missiles() {   enable_missile_safety_mode(); // warning encouraged   launch_missiles(); } error_info &foo(); void f() { foo(); }             // warning not encouraged: not a nodiscard call, because neither                                 // the (reference) return type nor the function is declared nodiscard 

 — end example ]

So modifying your example (see it live):

[[nodiscard]] int f(int z) {     return z + (z*2) + z/3 + z*z + 23; }   int main() {   int i = 7;   f(i); // now we obtain a diagnostic    return 1; } 

We now obtain a diagnostic with both gcc and clang e.g.

warning: ignoring return value of function declared with 'nodiscard' attribute [-Wunused-result]   f(i); // now we obtain a diagnostic   ^ ~ 
like image 24
Shafik Yaghmour Avatar answered Oct 26 '22 12:10

Shafik Yaghmour