anol
anol

Reputation: 8953

Defining a function returning incompatible type, but unreachable

After reading through the C99 standard, I could not find any sections which would forbid defining function f below:

struct s { double d; };

int f() {
  if (0) return (struct s){.d = 3.14};
  // There is intentionally no return statement of type int, which is valid
}

int main() {
  f();
  return 0;
}

In particular, this program's behavior should be defined, since the return value is (a) never reached in the first place and (b) never used, even if it were reached.

Still, most of my compilers (GCC, Clang and CompCert) prevent this program from being compiled, with error returning 'struct s' from a function with incompatible result type 'int'. I did manage to compile it with tcc, but I don't know if it's mostly due to luck (i.e. lack of verifications).

Could someone please confirm if this program is syntactically C99 valid, and also that its behavior is completely well-defined, or otherwise indicate where the standard forbids it?

I actually prefer that my compilers reject it, but for instance some macro definitions could produce code similar to this one, so it could be actually useful to accept such programs if they are valid.

Background

Below are the possibly relevant excerpts of the C99 standard that I could find, along with my reasoning on why they should not forbid my program from being syntactically valid and semantically well-defined:

§6.8.6.4 The return statement

§6.8.6.4.1 A return statement with an expression shall not appear in a function whose return type is void. A return statement without an expression shall only appear in a function whose return type is void.

In my code, we have a non-void function with a non-void return, so everything seems fine.

§6.8.6.4.3 If a return statement with an expression is executed, the value of the expression is returned to the caller as the value of the function call expression. If the expression has a type different from the return type of the function in which it appears, the value is converted as if by assignment to an object having the return type of the function.

Because the return statement is never executed, the above does not apply.

§6.9.1 Function definitions

§6.9.1.12 If the } that terminates a function is reached, and the value of the function call is used by the caller, the behavior is undefined.

The result of the function call is not used by the caller, so the behavior should be defined.

Upvotes: 2

Views: 1187

Answers (1)

user743382
user743382

Reputation:

"If the expression has a type different from the return type of the function in which it appears, the value is converted as if by assignment to an object having the return type of the function." is a standalone sentence. It is not conditional on "If a return statement with an expression is executed" so applies even to your code. And I'm pretty sure you already know that conversion as if by assignment means that incompatible types allow for a compile-time error.

Upvotes: 10

Related Questions