1

Let's look at such piece of code:

#include <iostream>

int foo(int i) {return i; }

int foobar(int z) {return foo(z);}

int main() {
std::cout << foobar(3) << std::endl;
}

It compiles fine with g++ -std=c++11 ... and gives output 3. But The same output is given by:

#include <iostream>

int foo(int i) {return i; }

int foobar(int z) { foo(z);}

int main() {
std::cout << foobar(3) << std::endl;
}

It compiles without problems but clearly the keyword return is missed in foobar. Is it a bug in gcc 4.8.3 or maybe I'm not aware of some c++11 principle? (Runned on Fedora 20)

kotu
  • 90
  • 1
  • 8
  • 1
    It's not a bug, but the consequence is undefined behavior. – David G Dec 14 '14 at 21:55
  • 2
    I imagine if you use `-Wall` or `-Wextra`, this would be caught. – Oliver Charlesworth Dec 14 '14 at 21:55
  • 1
    -Wreturn-type should be specified (included in -Wall, which shoul be present anyway) – quantdev Dec 14 '14 at 21:56
  • possible duplicate of [C++ why main works with no return value](http://stackoverflow.com/questions/19293642/c-why-main-works-with-no-return-value). There is a special exception in the standard: `main` is allowed to omit the `return`. – Raymond Chen Dec 14 '14 at 22:18
  • I think that under SO rules that doesn't count as a duplicate. Sure, if you read between the lines that question and its answers are somewhat relevant here, but there's no direct answer there to this question. – MSalters Dec 14 '14 at 23:08
  • Similar to [Why does this C++ snippet compile (non-void function does not return a value)](http://stackoverflow.com/q/20614282/1708801) – Shafik Yaghmour Dec 15 '14 at 02:32

2 Answers2

6

The C++ standard doesn't make a mandate for compilers to insist on a return-statement in functions return non-void. Instead, flowing off the end of such a function without a return-statement is undefined behavior. The relevant statement in the standard is in 6.6.3 [stmt.return] paragraph 2, last sentence (and in 3.6.1 [basic.start.main] paragraph 5 is the statement making it OK for main() to flow off this function):

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.

The primary reason for this approach is that it may be non-trivial or even impossible if the function actually ever really returns. Consider this function declaration and function definition:

extern void will_always_throw();
int does_not_return_anything() {
    will_always_throw();
}

Assuming will_always_throw() indeed does as the name suggests, there is nothing wrong. In fact, if the compiler gets smarter and manages to verify that will_always_throw(), indeed, always throws (or a "noreturn" attribute is attached to will_always_throw(), it may warn about the last statement in this definition never being reached:

int does_return_something_just_in_case() {
    will_always_throw();
    return 17;
}

The general approach to deal with these situations is for compilers to support suitable options enabling/disabling warnings as necessary. For example, on your code all compilers I have access to (gcc, clang, and icc) create a warning assuming warnings are enable (using -Wall for the first two and -w2 for Intel's compiler).

Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380
4

The code compiles fine because it is well-formed, and so you can run it. But since this is undefined behavior, you cannot rely on any behavior of the program, anything is legal. To prevent accidents like this, enable compiler warnings. if you compile your code with -Wall, you will see

main.cpp:10:28: warning: no return statement in function returning non-void [-Wreturn-type]
 int foobar(int z) { foo(z);}

Here you can get more information about those warnings. Use them and make sure your code compiles warning free. It can catch a lot of errors in your code at compile time.

Community
  • 1
  • 1
Baum mit Augen
  • 49,044
  • 25
  • 144
  • 182
  • @Columbo Right. Can you suggest a better formulation? I.e. how is code that compiles called? Is it "legal" already? I do not think so, but I'm no language lawyer at all. – Baum mit Augen Dec 14 '14 at 22:02
  • 1
    Code that the compiler does not diagnose as ill-formed is *well-formed*. – Casey Dec 14 '14 at 22:11