SC22/WG14/N716 Minor issue with Compound Literals ================================== Clive Feather clive@demon.net 1997-09-18 Abstract -------- There is an ambiguity in the wording of Compound Literals. This paper explains the issue and proposes new wording to clean it up. Discussion ---------- N716 (Compound Literals) states, under Semantics: | The value of the compound literal is that of an unnamed object | initialized by the initializer list [...] otherwise, it has automatic | storage duration associated with the enclosing block. Consider the situation where a compound literal is evaluated more than once during the lifetime of its block, such as the second compound literal in example 8. The wording is unclear whether a new object is created each time the compound literal is evaluated, or whether a single object is simply reinitialized. If the former is the case, a burden will be placed on implementations, which will now have to handle dynamic allocation with block-related lifetime. If the address of the object is not taken, there is no way to distinguish between these two cases, and the as-if rule can be used. However, if the address is taken, there is a problem. For example, consider the following: struct foo { struct foo *next; int i }; int f (void) { int j; struct foo *p = NULL, *q; for (j = 0; j < 10; j++) q = &((struct foo) { .next = p, .i = j }), p = q; } If the first interpretation is taken, it builds up a linked list of objects. If the second is taken, it is equivalent to: struct foo { struct foo *next; int i }; int f (void) { int j; struct foo *p = NULL, *q; struct foo __compound_literal; for (j = 0; j < 10; j++) __compound_literal.next = p, // The order of these __compound_literal.i = j, // two is unspecified q = &__compound_literal, p = q; } I believe that it is the second interpretation that was intended, but that the wording should be altered to clarify it. Proposal ======== Add to the semantics (currently 6.3.2.6) after the paragraph beginning "The value of the compound literal" (currently paragraph 6): If a compound literal is re-evaluated while storage for the unnamed object created by that literal is still guaranteed to exist, the effect is to change the value of the existing object, not to create a second unnamed object. Add a new example: Example: Each compound literal creates only a single object in a given scope: struct foo { int i; }; int f (void) { struct foo *p = 0, *q; int j; for (j = 0; j < 2; j++) q = p, p = &((struct foo){ j }); return p == q && q.i == 1; } The function f() always returns the value 1. Note that if the body of the for loop were enclosed in braces, the lifetime of the unnamed object would be the body of the loop only, and on entry next time round p would be pointing to an object which is no longer guaranteed to exist, which is undefined behaviour. ==== END ====