3

In my answer to a question here I explained what happened when postfix ++ was used on a global variable on the same line as a return statement.

The informative appendix C of C11 states that there is a sequence point immediately after a return and refers to normative chapter 6.8.6.4, where no text regarding sequence points can be found.

Where in the C standard can I find normative text stating that there is a sequence point after a return statement?

(I only found normative text stating this for library functions, as a special case, at 7.1.4/3.)

Community
  • 1
  • 1
Lundin
  • 195,001
  • 40
  • 254
  • 396

2 Answers2

5

C 2011 (draft n1570) 6.8 4: “Each of the following is a full expression: … the (optional) expression in a return statement. There is a sequence point between the evaluation of a full expression and the evaluation of the next full expression to be evaluated.”

So technically the sequence point is not after a return but is between the evaluation of the expression in the return and the next expression. Consider this code, called when a is initially 0:

int a = 0;

int Foo(void) { return a++; }

void Bar(void)
{
    int b = Foo() + a;
    …
}

In Foo() + a, whether Foo() or a is evaluated first is unspecified. We will consider both orders in light of both potential rules (sequence point after return versus sequence point between the expression of the return and the next full expression). If the implementation does a first, then it must do:

a
Sequence point
Foo()
+

and then some other full expression would follow, so, by either rule, there would be a sequence point, and this code is the same either way, as far as we are concerned. The result is that b is set to 0.

If the implementation does Foo() first, then, with the “sequence point after a return” rule, the implementation must do:

Sequence point
Foo()
Sequence point
a
+

This code would have defined behavior: a is incremented by the side effect in Foo, and that is complete before a is accessed, then + is performed. The result is that a is set to 1. Although the result may be 0 or 1 with this “sequence point after return” rule, it is merely unspecified which of the two orders is used; the behavior is not completely undefined.

However, if the implementation does Foo() first and uses the standard C rule of “sequence point between the expression of a return and the next full expression”, then we have:

Sequence point
Foo()
???
a
???
+
???

The “???” mark places where the required sequence point might be—anywhere after the return and before the next full expression. In this case, the value of a might be accessed in a and modified in Foo(), and there is no intervening sequence point. That is undefined behavior.

Therefore, the rule “sequence point after the expression of a return and before next full expression” is different from “sequence point immediately after a return”; the first has undefined behavior in this example, and the second does not.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
  • 1
    Thank you, the text in 6.8/4 was what I was looking for. And apparently this was clarified in C11, because C99 didn't have §4. I don't follow your example regarding undefined behavior though, since there is also a sequence point after all function parameters have been evaluated, but before the function is called. So each function with a return statement is "protected" by sequence points both at the beginning and the end. So I believe your example is merely _unspecified_ behavior, since we can't know if Foo() or `a` is evaluated first. – Lundin Mar 26 '13 at 14:42
  • @Lundin: Good point about the sequence point between parameter evaluation and function call. That means there is a difference the two rules. I have updated the answer. – Eric Postpischil Mar 26 '13 at 15:42
  • Are there any cases where the lack of a sequence point between the evaluation of a return value and the evaluation of whatever part of the enclosing expression would be evaluated text allow compilers to process code more usefully than would otherwise be possible? If not, is there any reason anyone seeking to make or use quality compilers should need to care about whether a sequence point is mandated there? – supercat May 27 '21 at 17:49
4

I don't think you're going to find what you're looking for. no text regarding sequence points can be found that's true, it's only implied by section 6.8 p4.

The C++ standard (ISO/IEC 14882:2003) in section 1.9 (footnote 11) states the fact that a sequence point after the return is not explicitily written anywhere in the C standards:

11) The sequence point at the function return is not explicitly specified in ISO C, and can be considered redundant with sequence points at full-expressions, but the extra clarity is important in C + +. In C + +, there are more ways in which a called function can terminate its execution, such as the throw of an exception.

Mike
  • 47,263
  • 29
  • 113
  • 177
  • @larsmans yeah... that was a bit redundant wasn't it? Thanks for the fix. – Mike Mar 26 '13 at 13:17
  • @Mike Thank you. It seems that this has been corrected in C11, as per 6.8 §4. C99 didn't have that paragraph. – Lundin Mar 26 '13 at 14:42