C++ requires that a function with a return type always returns a value or not return at all (throw an exception, longjmp() out, abort the program).
However, it doesn't require a diagnostic for a violation of this rule, because it's too complicated to enforce, and C++ trusts the programmer more than the compiler. Consider:
Code:
int foo()
{
if(complicated_condition()) {
bla bla bla;
do_the_switch = true;
}
more code;
if(!do_the_switch) return 0;
switch(something())
{ // under complicated_condition(), something() can only return 1, 2 or 3
case 1: return 100;
case 2: return 200;
case 3: return 300;
default: assert(!"something() returned unexpected value");
}
}
The compiler would have to do a lot of work to track down the relationship between complicated_condition() and something()'s return value. It would have to analyze the data flow across procedures, potentially even taking global state into account, and with the need to prove that it cannot change between the calls in a way that would change the outcome. Only then can it say with certainty that the function does not return a value under some circumstances.
Therefore, C and C++ compilers are not required to give diagnostics.
Java and C#, on the other hand, don't trust the programmer. Their language standards dictate that the compiler must implement some very simple flow analysis and that functions must return a value or throw along every path deemed possible by this method. (And that variables are initialized before use, using the same heuristic. Another thing C++ doesn't require, although it says that accessing an uninitialized variable is undefined.)
GCC uses the following method, I think:
1) If the compiler can prove that a possible way returns no value, it gives an error, but only in standard mode (there is old code that doesn't always return a value for int functions, and GCC needs to maintain compatibility). Typically, that means that the function contains no return statement at all.
2) If the compiler can prove that a possible way returns no value, and it's not in standard mode, it gives a warning.
3) If the compiler thinks it's possible that a path that returns no value is taken, and -Wextra is specified, it gives a warning.
4) Otherwise, no warning is emitted.