Richard Smith
2014-Apr-08 00:21 UTC
[LLVMdev] Why "I = ++I" instead of "++I" in COFFDump.cpp ?
On Mon, Apr 7, 2014 at 12:09 PM, Joerg Sonnenberger <joerg at britannica.bec.de> wrote:> On Mon, Apr 07, 2014 at 08:38:58AM -0600, Richard wrote: > > Oops, meant to send this to the mailing list instead of to Reid > > privately. (Why cc the mailing list instead of just sending to the > > mailing list?) > > > > In article <CACs> tyJ6zaHeiS0eNhBkdcZE--JY4k7yH9_P1yFbGqod6uymMw at mail.gmail.com>, > > Reid Kleckner <rnk at google.com> writes: > > > > > Looks like a bug. This can probably be simplified with C++11. > > > > > > On Fri, Apr 4, 2014 at 10:39 AM, Robison, Arch <arch.robison at intel.com > >wrote: > > > > > > > for (; I != E; I = ++I) { > > > > ... > > > > } > > > > > > > > Is there a reason for writing "I = ++I" instead of "++I" ? > > > > I don't see how it's a bug because functionality isn't impacted by > > this. It's simply a redundant assignment. > > It is a bug as it violates the sequence point rule. One memory location > shall not be modified twice.Not in C++11, and (probably) not in C11. The side-effect of pre-increment is sequenced before its value computation, and its value computation is sequenced before the assignment. (C++ doesn't have sequence points any more, and C only has them as a vestigial remnant of the pre-memory-model world.) -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20140407/09541b3f/attachment.html>
In article <CAOfiQq=gtrW-qHLLn-5bfmwZ6Qr4wv3mi=NP78AetEOpbTJVqA at mail.gmail.com>, Richard Smith <richard at metafoo.co.uk> writes:> On Mon, Apr 7, 2014 at 12:09 PM, Joerg Sonnenberger <joerg at britannica.bec.de > > wrote: > > > It is a bug as it violates the sequence point rule. One memory location > > shall not be modified twice. > > > Not in C++11, and (probably) not in C11. The side-effect of pre-increment > is sequenced before its value computation, and its value computation is > sequenced before the assignment. (C++ doesn't have sequence points any > more, and C only has them as a vestigial remnant of the pre-memory-model > world.)OK, still looking on how to find this in the standard. Discussion of postfix ++ and --: 5.2 Postfix expressions 5.2.6 Increment and decrement "The value computation of the ++ expression is sequenced before the modification of the operand object." Discussion of prefix ++ and --: 5.3 Unary expressions 5.3.2 Increment and decrement ...doesn't say anything about sequencing It seems that with postfix operators the reason the code in 1.9.15 ("i = i++ + 1", for example) was yielding undefined behavior was because although the value computation of postfix++ is sequenced before the modification of the operand object (5.2.6), the standard doesn't guarantee anything about the relative sequencing of the postfix++ modification and the assignment of the computed rvalue to the lvalue. So a conforming implementation could do either: // initially i = 9 i = i++ + 1; // 1. evalute i++ to get 9 // 2. evalute 1 to get 1 // 3. add 9 + 1 to get 10 // 4. assign 10 to i // 5. increment i to 11 -or- // initially i = 9 i = i++ + 1; // 1. evalute i++ to get 9 // 2. increment i to 10 // 3. evalute 1 to get 1 // 4. add 9 + 1 to get 10 // 5. assign 10 to i Am I getting closer? -- "The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline> The Computer Graphics Museum <http://ComputerGraphicsMuseum.org> The Terminals Wiki <http://terminals.classiccmp.org> Legalize Adulthood! (my blog) <http://LegalizeAdulthood.wordpress.com>
Krzysztof Parzyszek
2014-Apr-08 17:35 UTC
[LLVMdev] Why "I = ++I" instead of "++I" in COFFDump.cpp ?
On 4/8/2014 11:39 AM, Richard wrote:> > In article <CAOfiQq=gtrW-qHLLn-5bfmwZ6Qr4wv3mi=NP78AetEOpbTJVqA at mail.gmail.com>, > Richard Smith <richard at metafoo.co.uk> writes: > >> On Mon, Apr 7, 2014 at 12:09 PM, Joerg Sonnenberger <joerg at britannica.bec.de >>> wrote: >> >>> It is a bug as it violates the sequence point rule. One memory location >>> shall not be modified twice. >> >> >> Not in C++11, and (probably) not in C11. The side-effect of pre-increment >> is sequenced before its value computation, and its value computation is >> sequenced before the assignment. (C++ doesn't have sequence points any >> more, and C only has them as a vestigial remnant of the pre-memory-model >> world.) > > OK, still looking on how to find this in the standard.C99: 6.5 Expressions 1 An expression is a sequence of operators and operands that specifies computation of a value, or that designates an object or a function, or that generates side effects, or that performs a combination thereof. 2 Between the previous and next sequence point an object shall have its stored value modified at most once by the evaluation of an expression. Furthermore, the prior value shall be read only to determine the value to be stored.70) 70) This paragraph renders undefined statement expressions such as i = ++i + 1; a[i++] = i; while allowing i = i + 1; a[i] = i; C++ 2003: 5 Expressions [...] 4 Except where noted, the order of evaluation of operands of individual operators and subexpressions of individual expressions, and the order in which side effects take place, is unspecified.53) Between the previous and next sequence point a scalar object shall have its stored value modified at most once by the evaluation of an expression. Furthermore, the prior value shall be accessed only to determine the value to be stored. The requirements of this paragraph shall be met for each allowable ordering of the subexpressions of a full expression; otherwise the behavior is undefined. [Example: i = v[i++]; // the behavior is unspecified i = 7, i++, i++; // i becomes 9 i = ++i + 1; // the behavior is unspecified i = i + 1; // the value of i is incremented —end example] 53) The precedence of operators is not directly specified, but it can be derived from the syntax. C++ working draft: 1.9 Program execution [...] 13 Sequenced before is an asymmetric, transitive, pair-wise relation between evaluations executed by a single thread (1.10), which induces a partial order among those evaluations. Given any two evaluations A and B, if A is sequenced before B, then the execution of A shall precede the execution of B. If A is not sequenced before B and B is not sequenced before A, then A and B are unsequenced. [ Note: The execution of unsequenced evaluations can overlap. —end note ] Evaluations A and B are indeterminately sequenced when either A is sequenced before B or B is sequenced before A, but it is unspecified which. [ Note: Indeterminately sequenced evaluations cannot overlap, but either could be executed first. —end note ] 14 Every value computation and side effect associated with a full-expression is sequenced before every value computation and side effect associated with the next full-expression to be evaluated.8) 15 Except where noted, evaluations of operands of individual operators and of subexpressions of individual expressions are unsequenced. [ Note: In an expression that is evaluated more than once during the execution of a program, unsequenced and indeterminately sequenced evaluations of its subexpressions need not be performed consistently in different evaluations. —end note ] The value computations of the operands of an operator are sequenced before the value computation of the result of the operator. If a side effect on a scalar object is unsequenced relative to either another side effect on the same scalar object or a value computation using the value of the same scalar object, and they are not potentially concurrent (1.10), the behavior is undefined. [ Note: The next section imposes similar, but more complex restrictions on potentially concurrent computations. —end note ] [ Example: void f(int, int); void g(int i, int* v) { i = v[i++]; // the behavior is undefined i = 7, i++, i++; // i becomes 9 i = i++ + 1; // the behavior is undefined i = i + 1; // the value of i is incremented f(i = -1, i = -1); // the behavior is undefined } —end example ] When calling a function (whether or not the function is inline), every value computation and side effect associated with any argument expression, or with the postfix expression designating the called function, is sequenced before execution of every expression or statement in the body of the called function. [ Note: Value computations and side effects associated with different argument expressions are unsequenced. —end note ] Every evaluation in the calling function (including other function calls) that is not otherwise specifically sequenced before or after the execution of the body of the called function is indeterminately sequenced with respect to the execution of the called function.9) Several contexts in C++ cause evaluation of a function call, even though no corresponding function call syntax appears in the translation unit. [ Example: Evaluation of a new expression invokes one or more allocation and constructor functions; see 5.3.4. For another example, invocation of a conversion function (12.3.2) can arise in contexts in which no function call syntax appears. —end example ] The sequencing constraints on the execution of the called function (as described above) are features of the function calls as evaluated, whatever the syntax of the expression that calls the function might be. 8) As specified in 12.2, after a full-expression is evaluated, a sequence of zero or more invocations of destructor functions for temporary objects takes place, usually in reverse order of the construction of each temporary object. 9) In other words, function executions do not interleave with each other. HTH, -Krzysztof -- Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation