[gimple] assignments to volatile

Mike Stump mikestump@comcast.net
Thu Jun 24 19:37:00 GMT 2010


On Jun 24, 2010, at 7:32 AM, Mark Mitchell wrote:
> Mike Stump wrote:
> 
>>> x = y = z;
>>> 
>>> where "y" is volatile?
> 
>> C++ requires a re-read of y, the patch was going to remove the
>> re-read, I objected because the patch then makes the compiler not
>> conform to the C++ standard.
> 
> I think that you have to read rather a lot into the C++ standard to
> arrive at that conclusion.

I disagree.  It we meant to create a temporary for a = b = c, when a b and c are all class types, we would have listed 5.17 in 12.2.  Do you know of any C++ compilers that so create a temporary?  g++ certainly doesn't.  Now, compare 6.6.3.  It can create a temporary, and it does list 12.2, and is listed by 12.2.

Do you think:

	(0, a)

can create a temporary for a as well?  The standard uses similar wording there as well:

  The  type  and value of the result are the type and value of the right
  operand; the result is an lvalue if its right operand is.

I think what your missing is kinda basic, from 1.7:

  An object is created by  a  definition  (_basic.def_), by a new-expression (_expr.new_) or by the imple-
  mentation (_class.temporary_)  when  needed.

This is meant to describe when objects are created.  We don't have a definition, so basic.def doesn't apply.  We don't have a new, so expr.new doesn't apply, and class.temporary doesn't apply, so, there is in fact no object created.  If one had been created the standard would has said it.  I think your confusing the as-if rule, which says, you can create temporaries all you want, as long as you can't observe it.  This is different, we can observe it, so it can't be created.

If you want to claim an object is create, start from 1.7, and tell me which of basic.def, expr.new or class.temporary is used, and we'll work forward from there.  Now, how do I know we're dealing with an object, because of 3.10:

   An  lvalue refers to an object or function.

Now, how do I know we're dealing with an lvalue:

  the result is an lvalue

QED.  So, the standard is perfectly clear on this point, but I do admit, the wording could be improved in 5.17.

> But, I suggest that you raise the issue on the C++ reflector and report back.  I think that it would be very helpful to hear what other implementors think.

I'd rather just survey what their compilers do.  If they all agree with you, maybe indeed g++ is the odd man out.  I have a sneaky suspicion that none of them do.  When all compilers match, I don't usually waste the reflector's time on such trivial matters, though, would be good to reword the standard to say the result is the left hand side, so that people are less able to be confused by the wording.

> But, this point may be moot; I don't know if the proposed patch changes
> the behavior here or not.  Nathan, can you clarify that?

I thought his patch was clear:

+  /* should not reread obj */
+  /* { dg-final { scan-assembler "movl\[ \t\]\[^,\]+, obj_8" } } */
+  /* { dg-final { scan-assembler-not "movl\[ \t\]obj_8," } } */
+  return cond ? obj_8 = 0 : 0;

>>> int x; volatile int y; int z; x ? y = z : 0
>>> 
>>> generating a read from "y" while:
>>> 
>>> x ? y = 0 : 0
>>> 
>>> does not.
>> 
>> I wasn't arguing this case.  I believe both standards have them
>> behaving the same.
> 
> And which way is that?  Do you think that y needs to be read, or not?

In:

volatile int i, j, k;
volatile int vi;
void foo(int p) {
  k = (i ? j=0 : k);
}

j is re-read.  It is re-read regardless if j=0, or j=k is used in the source.  Now, for the simpler:

volatile int i, j, k;
volatile int vi;
void foo(int p) {
  i ? j=0 : 0;
}

neither gcc nor g++ re-reads, and I'm not arguing changing that.  Nor is anyone suggesting changing that, so I don't see the point of asking.  I'm dodging what the standard says, well, unless someone wants to propose we change how they behave currently.



More information about the Gcc-patches mailing list