6

If a function is declared with a void return value (no return value), then it is an error for the function definition to return any value.

If a function is declared with a non-void return value (returns some value or object), then it is NOT an error if the function definition fails to return a value. Some compilers generate missing-return-value warnings about this.

What is the reason for this? To me it would make sense to have these swapped, so that an error is generated if you fail to return a value, and you only get a warning if you try to return a value from a function that is declared with a void return type.

  • 1
    all compilers generate such warning, do not disable. Maybe this is historical issue from ancient C? – Jacek Cz May 20 '16 at 12:59
  • Obligatory viewing for [asking why questions](https://www.youtube.com/watch?v=wMFPe-DwULM). Also Richard Feynman is awesome. – Barry May 20 '16 at 13:00
  • Your answer can be found here: http://stackoverflow.com/a/9570905/3050692 – JefGli May 20 '16 at 13:02
  • 1
    @Barry Not sure how Feynman is relevant here. The question is apt: there’s no reason for this not to be an error. Now, I don’t know the answer (historical balast, oversight?) but there *is* one. In fact, the standard is quite explicit in that using the return value of such a function is UB. The why allow generating it at all? – Konrad Rudolph May 20 '16 at 13:03
  • @KonradRudolph I'd guess that in the general case, determining whether a function actually returns something or not could be equivalent to the halting problem. – Angew is no longer proud of SO May 20 '16 at 13:03
  • @KonradRudolph Did you watch it? Besides, what answer is OP looking for? Because the standard says it's just UB? That would be the literal answer, but unsatisfactory. Because in C it's fine? Because when C was created, we just assumed `int` everywhere? Because in ALGOL, ... ? – Barry May 20 '16 at 13:05
  • 1
    @Angew It could be, but it isn’t. Determining *whether* a function returns is undecidable, but determining whether it returns a value on all code paths that return is trivial (= there is a deterministic, efficient algorithm for it; it’s not necessarily easy though). – Konrad Rudolph May 20 '16 at 13:05
  • @Barry I know the video well. I don’t know what OP is looking for. But in their place, I’d like to know why the standard doesn’t mandate that compilers generate an error diagnostic for this. – Konrad Rudolph May 20 '16 at 13:05

1 Answers1

7

C++ gives you the ability to shoot yourself in the foot.

It's surprisingly difficult (if not impossible) for a compiler to tell if a function returns something appropriate on all control paths.

So, like the burden of having to initialise variables before use, it leaves it to the programmer.

The behaviour on not explicitly returning a value from a non-void function is undefined.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
  • 3
    “It's surprisingly difficult (if not impossible) for a compiler to tell if a function returns something appropriate on all control paths.” — I’m pretty sure this is a solved problem (unlike, say, the halting problem). Other languages mandate return values, and statically check for it. – Konrad Rudolph May 20 '16 at 13:04
  • I'm not sure it is possible in C++ due to some grammar quirks. It is possible in Java though. – Bathsheba May 20 '16 at 13:04
  • I know I get warnings regarding functions where not all paths return. – NathanOliver May 20 '16 at 13:05
  • 8
    @KonradRudolph: `int f(Program p) { if (p.halts()) { p(); return 0; } }` – Kerrek SB May 20 '16 at 13:06
  • Interesting - so it's actually quite reasonable to have no return value - but it is only in *reading* the return value that is undefined. –  May 20 '16 at 13:08
  • @KerrekSB I don’t see any reason (either theoretical or practical) for a compiler not to flag this as having a missing return value. *Even if* `p.halts()` is always `true`. Simply `throw` at the end of this function if you expect `p.halts()`. – Konrad Rudolph May 20 '16 at 13:09
  • 3
    The actual quote from the standard is *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.* which means it is UB regardless if you access the return value or not. Once you flow off the end you are in UB land. – NathanOliver May 20 '16 at 13:10
  • @KerrekSB (Expanding on my previous comment): In fact, that’s arguably the whole point of a static type system. If you want to convey statically verifiable information about `p.halts`, you’re expected to encode this in its type. – Konrad Rudolph May 20 '16 at 13:17