Why does flowing off the end of a non-void function without returning a value not produce a compiler error?
C99 and C++ standards require non-void
functions to return a value, except main
. The missing return statement in main
will be defined (to return 0
). In C++ it's undefined behaviour if execution actually reaches the end of a non-void
function other than main
, while in C it's only UB if the caller uses the return value.
This means functions can look like they might reach the end without returning a value, but actually can't reach the closing }
. John Kugelman's answer shows some examples, like a noreturn function called from one side of an if
. It's only undefined behaviour if execution actually does get to the end without reaching a return
earlier. The rationale includes that checking if every real code path returns a value is quite difficult (without knowing which functions never return), so it's not illegal to compile a function like your example, only to actually call it like your main
does.
As an extension, at least one compiler (MSVC) allows a return value to be set with inline assembly, but most others still require a return statement in functions that use inline asm
.
From C++11 draft:
§ 6.6.3/2
Flowing off the end of a function [...] results in undefined behavior in a value-returning function.
§ 3.6.1/5
If control reaches the end of
main
without encountering areturn
statement, the effect is that of executingreturn 0;
Note that the behaviour described in C++ 6.6.3/2 is not the same in C.
gcc will give you a warning if you call it with -Wreturn-type option.
-Wreturn-type Warn whenever a function is defined with a return-type that
defaults to int. Also warn about any
return statement with no return-value
in a function whose return-type is not
void (falling off the end of the
function body is considered returning
without a value), and about a return
statement with an expression in a
function whose return-type is void.This warning is enabled by -Wall.
Just as a curiosity, look what this code does:
#include <iostream>
int foo() {
int a = 5;
int b = a + 1;
}
int main() { std::cout << foo() << std::endl; } // may print 6
This code has formally undefined behaviour, and in practice it's calling convention and architecture dependent. On one particular system, with one particular compiler, the return value is the result of last expression evaluation, stored in the eax
register of that system's processor, if you disable optimization.
This seems to be a consequence of GCC internals with optimization disabled, because in that case it picks the return-value register if it needs any to implement a statement. With optimization enabled in C++ mode, GCC and clang assume this path of execution is unreachable because it contains undefined behaviour. They don't even emit a ret
instruction, so execution falls into the next function in the .text section. Of course undefined behaviour means that anything could happen.
Is it Undefined behavior to not having a return statement for a non-void function in which control can never off over the end?
The two statements are in no way contradictory.
The first statement is about what happens when control flow exits a non-void
function without executing a return
statement. The second statement is about what happens when control flow does not exit the function at all. Calls to functions like exit
or std::terminate
do not ever have control flow proceed past the point when those functions are called.
But that has nothing to do with the nature of the return value.
The behavior of the program when a non-void
function runs out of stuff to do without an explicit return
statement (or throw
. Or co_return
these days) is governed by [stmt.return]/2:
Flowing off the end of a function is equivalent to a return with no value; this results in undefined behavior in a value-returning function.
What does a non void C function without return statement actually return? [duplicate]
- what does a non void function without any return statement actually return ? Could it be the last allocated variable on the stack ?
The C standard does not define the behavior if a function does not execute return
with a value and the return value of the function is used.
(There is some evidence that, in some situations, GCC deliberately returns the value of the last full expression evaluated in the function, but that was discussed in comments some time ago, and I do not have a reference.)
GCC raises a warning for that , but not an error. Wouldn't a compiler error be actually more pertinent for such a case instead of a compiler warning ?
The C standard does not prohibit a function with a non-void return type from returning without returning a value (by allowing program control to flow to the terminating }
of the function definition). So a conforming compiler should allow this in the function definition, meaning it can warn but should not produce an error. It is allowed to call such a function and not use its return value; that has behavior defined by the C standard.
If the compiler can see that a function call uses the return value of a function that does not return a value, the compiler could produce an error for that.
It is occasionally useful for a function with a non-void return type to return a value in some situations and not in others, such as a function that accepts a command to perform and returns a value when a “Get value of setting” command is performed and does not return a value when a “Set value of setting” command is performed.
Why do I get the warning 'control reaches end of non-void function' even when the return is guaranteed
The compiler correctly assumes that r
is a variable value, it does not process it as a constant, that being the case it cannot be sure what the value is going to be and therefore if the body of the cycle will or will not be executed.
If you use a constant the warning goes away because the compiler will assemble the code using a constant value.
You can check this behavior here.
Why does this C++ snippet compile (non-void function does not return a value) [duplicate]
This is undefined behavior from the C++11 draft standard section 6.6.3
The return statement paragraph 2 which says:
[...] Flowing off the end of a function is equivalent to a return with no value; this results in undefined behavior in a value-returning function. [...]
This means that the compiler is not obligated provide an error nor a warning usually because it can be difficult to diagnose in all cases. We can see this from the definition of undefined behavior in the draft standard in section 1.3.24
which says:
[...]Permissible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message).[...]
Although in this case we can get both gcc
and clang
to generate a wanring using the -Wall
flag, which gives me a warning similar to this:
warning: control reaches end of non-void function [-Wreturn-type]
We can turn this particular warning into an error using the -Werror=return-type
flag. I also like to use -Wextra -Wconversion -pedantic
for my own personal projects.
As ComicSansMS mentions in Visual Studio this code would generate C4716 which is an error by default, the message I see is:
error C4716: 'Min' : must return a value
and in the case where not all code paths would return a value then it would generate C4715, which is a warning.
control reaches end of non-void function produces error instead of warning
I'm wondering if there's a workaround to convert this error to a warning using compiler flags?
I would expect the -Wno-error
option to have that effect. It should also be possible to narrow the scope of that to the specific diagnostic you report, but beware: there is no way with command-line options alone to narrow the effect to this particular instance of the issue.
Addendum
The question having been edited to show that the diagnostic category is return-type
, I can say that one would use -Wno-error=return-type
to make all diagnostics of this type warnings instead of errors.
Related Topics
Invalid Operands Error for Addition and Integer Division
How to Print Bytes as Hexadecimal
What Is This Weird Colon-Member (": ") Syntax in the Constructor
What Is Meant by Resource Acquisition Is Initialization (Raii)
When a Function Has a Specific-Size Array Parameter, Why Is It Replaced With a Pointer
How to Convert Between Big-Endian and Little-Endian Values in C++
How to Reverse a String in Place in C or C++
Where Are Static Variables Stored in C and C++
How to Align Text to the Right Using Cout
Correct Way of Passing Pointer to Another Thread
Reading Every Nth Frame from Videocapture in Opencv
Why Do I Have to Access Template Base Class Members Through the This Pointer
How to Get the List of Files in a Directory Using C or C++