Thursday, 25 October 2018

Warnings Series - Return Type

In this series of posts I'm discussing how compiling with multiple compilers can help to catch errors at development time. In the last post I discussed how to detect out of range errors. In this post, I'm going to look at turning some warnings into errors. As an example, I'm using the first warning that I promote to an error on every project I work on.

Background

As discussed in my previous posts, you can enable warnings under GCC and Clang using the -W flags. This can turn on a group of warnings, for example using -Wall, or an individual warning like -Wmaybe-uninitialized. If you want to be stricter, you can promote those warnings to errors that will stop your program from compiling. This can be done by adding -Werror= as a compiler flag, e.g. -Werror=maybe-uninitialized will make unitialized warnings into errors.

Return Type

All compilers have a warning regarding missing the return statement from a function. Consider the following code:

1
2
3
4
5
6
7
8
9
int* allocate_int() {
    int ret = new int(0);
}
 
int main() {
    int* x = allocate_int();
    std::cout << *x;
    delete x;
}

As you can see if you the function allocate_int is missing a return statement, therefore the variable x is undefined. This can then introduce strange logic errors that can be different between builds and runs of your program. One of the first times I ran into this error, the symptom of it was that if logging was enabled a variable was true and the program worked. If logging was disabled, an error was always returned as the variable was false.

Since then, this is always the first warning that I promote to an error on all projects I work on. For new projects, it prevents the error from being introduced. For legacy projects, it helps find and prevent subtle errors. In most legacy projects I've worked on, enabling this error has resulted in a failed compile.

Note: There is no return statement on the main function and this doesn't produce a warning or error. The reason for this is that the C++ standard specifies that main will implicitly return 0 if there is no return statement. This implicit return has resulted in papers such as p1276 calling for main to allow void.

Catching the error

Clang

When compiling with Clang and this is a warning by default when using no compiler flags. To promote the warning to an error you can use -Werror=return-type.

GCC

For GCC the warning is not enabled by default in older versions of the compiler. It is included as part of the -Wall flag or can be enabled individually using -Wreturn-type. To promote it to an error you can use -Werror=return-type.

Note: From v8.0 of GCC you will receive a warning with no additional compiler flags, however, you must still use -Werror=return-type to cause a compilation error.

MSVC

With MSVC this results in a compilation error by default.

Comparing the errors

To view the errors from each compiler you can use godbolt to compare the output.

No comments:

Post a Comment