On 2016.03.18 at 22:05 +0800, Cy Cheng wrote: > Hi, > > Please look at this c code: > > typedef struct _PB { > void* data; /* required.*/ > int f1_; > float f2_; > } PB; > > PB** bar(PB** t); > > void qux(PB* c) { > bar(&c); /* c is escaped because of bar */ > c->f1_ = 0; > c->f2_ = 0.f; > } > > // gcc-5.2.1 with -fno-strict-aliasing -O2 on x86 > call bar > movq 8(%rsp), %rax <= load pointer c > movl $0, 8(%rax) > movl $0x00000000, 12(%rax) > > // intel-icc-13.0.1 with -fno-strict-aliasing -O2 on x86 > call bar(_PB**) > movq (%rsp), %rdx <= load pointer c > movl %ecx, 8(%rdx) > movq (%rsp), %rsi <= load pointer c > movl %ecx, 12(%rsi) > > GCC only load pointer c once, but if I implement bar in such way: > PB** bar(PB** t) { > char* ptr = (char*)t; > *t = (PB*)(ptr-8); > return t; > } > > Does this volatile C99 standard rule > (http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf): > > 6.5.16 Assignment operators > > "3. ... The side effect of updating the stored value of the left operand > shall occur between the previous and the next sequence point."
No. We discussed this on IRC today and Richard Biener pointed out that bar cannot make c point to &c - 8, because computing that pointer would be invalid. So c->f1_ cannot clobber c itself. -- Markus