views:

483

answers:

5

I am using Coverity on a project to find errors.

It reports an error for this expression (The variable names are of course changed):

x=
   (a>= b) ?
   ++x: 0;

The message is:

EVALUATION_ORDER defect: In "x=(a>= b) ? ++x: 0;", "x" is written in "x" (the assignment LHS) and written in "(a>= b) ? ++x: 0;" but the order in which the side effects take place is undefined because there is no intervening sequence point. END OF MESSAGE

While I can understanding that "x = x++" is undefined, this one is a bit harder for me. Is this one a false positive or not?

+23  A: 

Conditional operator ?: has a sequence point between evaluation of the condition (first operand) and evaluation of second or third operand, but it has no dedicated sequence point after the evaluation of second or third operand. Which means that two modifications of x in this example are potentially conflicting (not separated by a sequence point). So, Coverity is right.

Your statement in that regard is virtually equivalent to

a >= b ? x = ++x : x = 0;

with the same problem as in x = ++x.

Now, the title of your question seems to suggest that you don't know whether x = ++x is undefined. It is indeed undefined. It is undefined for the very same reason x = x++ is undefined. In short, if the same object is modified more than once between a pair of adjacent sequence points, the behavior is undefined. In this case x is modified by assignment and by ++ an there's no sequence point to "isolate" these modifications from each other. So, the behavior is undefined. There's absolutely no difference between ++x and x++ in this regard.

AndreyT
@AndreyT- +1: Am surprised why Comeau Online does not give error for either this case or the simple case of 'x = x++;'
Chubsdad
@chubsdad: I don't remember Comeau Online ever catching such situations. GCC is known to issue warnings in cases like that, but it doesn't complain about the `?:` case.
AndreyT
+10  A: 

Regardless of the accuracy of the message, replacing the code in question by x= (a>= b) ? x+1: 0; achieves the same end without any confusion. If the tool is confused then maybe the next person to look at this code will be too.

This does assume that x does not have an overloaded increment operator with side-effects that you rely on here.

Steve Townsend
And please, out of the goodness of your heart to other developers, please don't call things `x`, `a` and `b`.
Dominic Rodger
@Dominic: the question clearly states that the names where changed from the original names.
Joachim Sauer
@Joachim - ah, missed that, phew!
Dominic Rodger
If it has an overloaded increment operator with side effects you rely on, someone deserves to be shot! :-p
Steven Schlansker
If it has an overloaded increment operator, @Steven, then there's no longer any issue of undefined behavior. The increment operator will be fully evaluated before the assignment operator begins.
Rob Kennedy
+7  A: 

The statement x = ++x; writes to the variable x twice before hitting the sequence point and hence the behavior is undefined.

Amarghosh
+3  A: 

It is hard to imagine a compiler producing code for "x = ++x;" which would in fact not work the same as "++x". If x is not volatile, however, it would be legal for a compiler to process the statement "y = ++x;" as

  y=x+1;
  x=x+1;

The statement "x = ++x;" would thus become

  x=x+1;
  x=x+1;

If having the destination of one an arithmetic assignment expression get used too quickly as a source operand for another would cause a pipeline delay, the former optimization might be reasonable. Obviously disastrous if the incremented and assigned variable are one and the same.

If variable 'x' is volatile, I can't think of any code sequence where a compiler that wasn't deliberately trying to be mean could legitimately regard "x = x++;" as having any effect other than reading all parts of 'x' exactly once and writing the same correct value to all parts of 'x' exactly twice.

supercat
A: 

I suppose that logically, if you write either "x=++x" or "x=x++", either way you would expect the end result to be that x is one more than it started as. But make it just a shade more complicated. What if you wrote "x=x+(++x)" ? Is this the same as "x=x+(x+1)" ? Or do we add one first and then add x to itself, i.e. "x=(x+1)+(x+1)"? What if we wrote "x=(x--)+(x++)" ?

Even if you could write a language spec that gave unambiguous meaning to these sort of constructs, and could then implement it cleanly, why would you want to? Putting a unary increment in an assignment to the same variable just doesn't make sense, and even if we forced sense out of it, it provides no useful functionality. Like, I'm sure we could write a compliler that would take an expression like "x+1=y-1" and figure out that that really means "x=y-2", but why bother? There's no gain.

Even if we wrote compilers that did something predictable with "x=x++-++x", programmers would have to know and understand the rules. Without any obvious benefit, it would just add complexity to programs for no purpose.

Jay