Why is a [[noreturn]] function checked for return type?

244 Views Asked by At

Suppose I have a function with signature [[noreturn]] void die(int exit_code);. If I write the statement:

check_some_condition() or die(EXIT_FAILURE);

I get an error message (with GCC 5.4.0):

error: expression must have bool type (or be convertible to bool)

but why is the type checked, if the compiler knows that going into that function, the return value won't matter; and if the condition checks out, again the return type doesn't matter?

Edit: Does the wording of the standard regarding [[noreturn]] not address this point, i.e. relax the requirements regarding types so as to "legitimize" such expressions?

3

There are 3 best solutions below

4
StoryTeller - Unslander Monica On

Every expression must have a well determined type, period. So even though the function doesn't return, it must still be possible to evaluate the type of the expression check_some_condition() or die(EXIT_FAILURE)

And from that it follows that the function return type must be viable for use in a logical operation.

5
Peter On

noreturn doesn't tell the compiler that the function returns no value. It tells the compiler that the function will not return. It also has no effect on the function's return type.

In an expression, the compiler is required to check that operands of expressions have valid types. In an expression like check_some_condition() or die(EXIT_FAILURE), that requires the return type of both check_some_condition() and die() to be checked. noreturn does not affect the function's return type, so does not affect the need for that check. If the function returns void, the expression is invalid.

0
Theodoros Chatzigiannakis On

The concept you are looking for is called a bottom type. In a type system, a bottom type is a type that is convertible to any other type. (Also compare it with a top type, to which all types are convertible.)

The bottom type is a perfect candidate for a function that doesn't return. It's type-safe to assign it to anything, precisely because the assignment will never happen anyway. If C++ had a bottom type, and if you declared your function as returning the bottom type, your snippet could have been perfectly legal and your expectation would have been correct.

Unfortunately, C++ doesn't have such a type. As pointed out already, [[noreturn]] is not a type -- it's an attribute that's used to express an intention (to other programmers and to the optimizer) in a way that's orthogonal to the type system. As far as the type checker is concerned, the function's return type is still void and that can't be converted to a boolean.