Compiler warnings
C++ warning: control reaches end of non-void function
This warning means a non-void function has a path that reaches its closing brace without returning a value. If the caller uses that missing result, behavior is undefined. MSVC reports this condition as C4715.
Follow every control-flow path
A function that returns int promises a value whenever it completes normally. A chain of if and else if statements may handle familiar inputs but still omit other values. GCC warns under -Wall with “control reaches end of non-void function”; GCC may attach a warning option and source location to this diagnostic. MSVC calls out missing return paths with C4715. The warning points to the function end, while the missing branch is usually higher in the function.
Failing C++17 example
#include <iostream>
int classify(int value) {
if (value > 0) { return 1; }
else if (value == 0) { return 0; }
}
int main() {
std::cout << classify(-2) << '\n';
return 0;
}
GCC diagnostic core:
warning: control reaches end of non-void functionThis example calls the function with a negative value, so it reaches the closing brace and has undefined behavior. Do not show an output for the broken program.
MSVC reports this missing-return warning as C4715.
Fixed example
#include <iostream>
int classify(int value) {
if (value > 0) { return 1; }
if (value == 0) { return 0; }
return -1;
}
int main() {
std::cout << classify(2) << '\n';
return 0;
}
Expected output:
1
Return after an enum switch
A switch can list every named enum class value and still leave a path without a return. The enum can hold a value outside its enumerators, so add a fallback after the switch when the function returns a value.
Warning example
#include <iostream>
enum class Status { ready, stopped };
int codeFor(Status status) {
switch (status) {
case Status::ready: return 1;
case Status::stopped: return 0;
}
}
int main() {
std::cout << codeFor(Status::ready) << '\n';
return 0;
}
GCC diagnostic core:
warning: control reaches end of non-void functionMSVC reports C4715. Diagnostic wording can vary by compiler version. Do not run this case; it has a path that reaches the end of a non-void function.
Fixed example
#include <iostream>
enum class Status { ready, stopped };
int codeFor(Status status) {
switch (status) {
case Status::ready: return 1;
case Status::stopped: return 0;
}
return -1;
}
int main() {
std::cout << codeFor(Status::ready) << '\n';
return 0;
}
Expected output:
1
Understand the consequence
Flowing off the end of a non-void function other than main and then using the result has undefined behavior. The program has no required result, and you must not print or otherwise rely on a guessed value. This differs from returning an arbitrary default, which is defined but may hide a logic error. The special rule for main allows it to reach its closing brace, which returns zero. That exception does not apply to ordinary functions.
Return a value on every intended path
Add a final return when a valid fallback exists. Restructure branches so each condition returns, or use a final else that handles the remaining cases. For an enum or a closed set of states, a switch can make the intended cases clearer, but include a valid path after it unless the type guarantees exhaustiveness. Choose a fallback that makes sense for callers. Do not return an uninitialized variable.
Turn on useful warnings
GCC’s -Wall enables this warning. Add -Wextra for additional diagnostics, and treat warnings as prompts to inspect behavior rather than proof of a particular runtime result. Compilers can differ in when they issue a warning, especially around templates or optimization. A clean warning list does not prove that every branch is correct. Review the function’s contract and test boundary values.
Exercise
Add a result for negative inputs. The repaired program must return -1 for a negative value.
Broken program
#include <iostream>
int signOf(int value) {
if (value > 0) return 1;
if (value == 0) return 0;
}
int main() { return signOf(-3); }
Compiler diagnostic core:
warning: control reaches end of non-void functionThe negative exercise input also reaches the missing return, so the broken program has no defined output.
Sample input: none.
Expected output after the fix:
-1
Hint 1: List every input range the function must handle. Hint 2: Check which range reaches the closing brace.
Show one possible solution
#include <iostream>
int signOf(int value) {
if (value > 0) return 1;
if (value == 0) return 0;
return -1;
}
int main() {
std::cout << signOf(-3) << '\n';
return 0;
}
Expected output:
-1
Related guides
- Fix an expected primary-expression error
- Read a no-matching-function diagnostic
- Understand an undefined-reference linker error
Keep learning with CppPath
Continue with the Function Parameters & Return Values lesson. The full lesson includes a quiz and a checked coding challenge with a free account.