Doc. No.: N1285
Date: 2008-03-10
Reply to: Clark Nelson
Phone: +1-503-712-8433
Email: clark.nelson@intel.com

Extending the lifetime of temporary objects

In N1253 I proposed extending the lifetime of temporary (a.k.a rvalue) objects, for increased safety and usability, to fix an inadvertent quiet change from C89, and for improved compatibility with C++. This direction was accepted in principle at the Kona meeting. This paper proposes specific wording changes to achieve that effect.

Two alternative formulations are presented: a distributed approach, and a factored approach.

The distributed approach

Change the last sentence of 6.5.2.2p5:

If an attempt is made to modify the result of a function call or to access it after the next sequence point end of evaluation of the containing full expression or full declarator, the behavior is undefined.

Change the last sentence of 6.5.15p4:

If an attempt is made to modify the result of a conditional operator or to access it after the next sequence point end of evaluation of the containing full expression or full declarator, the behavior is undefined.

Change the last sentence of 6.5.16p4:

If an attempt is made to modify the result of an assignment operator or to access it after the next sequence point end of evaluation of the containing full expression or full declarator, the behavior is undefined.

Change the last sentence of 6.5.17p2:

If an attempt is made to modify the result of a comma operator or to access it after the next sequence point end of evaluation of the containing full expression or full declarator, the behavior is undefined.

Change the relevant bullet of J.2:

The factored approach

This approach makes use of existing statements from 6.2.4p2 :

If an object is referred to outside of its lifetime, the behavior is undefined. The value of a pointer becomes indeterminate when the object it points to reaches the end of its lifetime.

Please note that this approach additionally declares an example like this, which was conforming under C99, to be non-conforming:

struct X { int a[5]; } f();
int *p = f().a;
printf("%p\n", p);

Because it uses the (indeterminate) value of a pointer to a temporary object. Personally, I think this is a good thing, but I wanted to be very clear and up front about this change.

Add a new paragraph to the end of 6.2.4 "Storage durations of objects":

A non-lvalue expression with structure or union type, where the structure or union contains a member with array type (including, recursively, members of all contained structures and unions) refers to an object with automatic storage duration and temporary lifetime.«FN») Its lifetime begins when the expression is evaluated; its initial value is the value of the expression. Its lifetime ends at the end of evaluation of the containing full expression or full declarator. Any attempt to modify an object with temporary lifetime results in undefined behavior.

«FN») The address of such an object is taken implicitly when an array member is accessed.

Also delete all the sentences cited and modified under the distributed approach:

The last sentence of 6.5.2.2p5:

If an attempt is made to modify the result of a function call or to access it after the next sequence point, the behavior is undefined.

The last sentence of 6.5.15p4:

If an attempt is made to modify the result of a conditional operator or to access it after the next sequence point, the behavior is undefined.

The last sentence of 6.5.16p4:

If an attempt is made to modify the result of an assignment operator or to access it after the next sequence point, the behavior is undefined.

The last sentence of 6.5.17p2:

If an attempt is made to modify the result of a comma operator or to access it after the next sequence point, the behavior is undefined.

The relevant bullet of J.2: