You cannot force a proper check
I don't think there is any way to do that in the way you want it. After all, in the statement printf("%d",fun ())
you are actually checking the return value from fun()
by sending it to another function. Of course, printf
doesn't really "check" the return value, but you could have used it this way:
void exit_if_fun_returns_negative_value(int val) { if(val<0) exit(EXIT_FAILURE); }
int main(void)
{
exit_if_fun_returns_negative_value(fun());
}
But there is no way to make the compiler understand the difference between this and your printf
statement. I assume you want to force the programmer to save the return value in a variable, but I don't know how that should be done, and even if you could do that, it does not ensure a proper check. Just look at this example:
char *array;
void *ptr;
ptr = realloc(array, 20);
strcpy(array, "Hello, World!");
Note how we are saving the return value in ptr
but since we're not doing something like if(ptr == NULL) exit(EXIT_FAILURE);
it's pretty pointless.
But you can prevent completely ignoring the return value
However, there is a way to prevent statements where you're not using (which of course is not the same thing as actually checking) the return value at all.
As far as I know, there is no portable way to do this. You will have to rely on compiler extensions. Gcc has such an extension.
__attribute__ ((warn_unused_result)) int foo (void)
{
return 5;
}
int main(void)
{
foo();
}
Compiling this will generate this warning:
$ gcc main.c
main.c: In function ‘main’:
main.c:9:5: warning: ignoring return value of ‘foo’, declared with attribute warn_unused_result [-Wunused-result]
9 | foo();
| ^~~~~
In order to treat it as an error, compile with -Werror
$ gcc main.c -Werror
main.c: In function ‘main’:
main.c:9:5: error: ignoring return value of ‘foo’, declared with attribute warn_unused_result [-Werror=unused-result]
9 | foo();
| ^~~~~
cc1: all warnings being treated as errors
If you want all other warnings to be just warnings, compile with -Werror=unused-result
. Example:
$ cat main.c
__attribute__ ((warn_unused_result))
int foo (void)
{
return 5;
}
int main(void)
{
int *x = 5;
foo();
}
$ gcc main.c -Werror=unused-result
main.c: In function ‘main’:
main.c:9:14: warning: initialization of ‘int *’ from ‘int’ makes pointer from integer without a cast [-Wint-conversion]
9 | int *x = 5;
| ^
main.c:10:5: error: ignoring return value of ‘foo’, declared with attribute warn_unused_result [-Werror=unused-result]
10 | foo();
| ^~~~~
cc1: some warnings being treated as errors
Change the signature to include an output parameter
One option to accomplish something similar is to move the return value to a parameter. That will force saving the "return value" to the parameter, and you cannot call the function without sending an output variable to it. Change
int fun (){ return 3;}
to
void fun(int *ret) { *ret=3; }
But as I mentioned above, I cannot see how you can force a proper check of the variable. This only forces an assignment.
Wrapper functions
Another option is to use wrapper functions. This will often greatly reduce the flexibility so think twice before using it, but it is an option that could be useful in some cases. Let's say that you have a header/source pair. Put the prototype of the wrapper in the header file and the implementation of both the wrapper and the function in the source file. That will hide the original function from the programmer. It can look like this:
.h
int fun_wrapper();
.c
int fun() { return 3; }
int fun_wrapper()
{
int ret = fun();
if(ret<0) exit(EXIT_FAILURE);
return ret;
}
How to use this technique for library functions
I created a related question that has an answer. It's about how to use this for fgets
and other functions from a library: How to create wrappers to library functions with original name?