On 09/18/2017 06:19 AM, Florian Weimer wrote:
I would like to see the GCC project to document that if the address of a
member is taken, this does not constitute an access to the object as a
whole.
That is, in the following code:
#include <stdatomic.h>
struct S {
_Atomic int a;
int b;
};
int
load_a (struct S *p)
{
return atomic_load_explicit (&p->a, memory_order_relaxed);
}
int
store_b (struct S *p, int b)
{
p->b = b;
}
If one thread calls load_a and another thread calls store_b on the same
struct S *, no data race happens.
This is an extension over the C standard because of the way “->” is
defined. C requires that E1->E2 it is evaluated as (*(E1))->E2, and *E1
is defined as an access to the entire struct, so there is a data race in
load_a with the assignment in store_b.
It's true that E1->E2 is equivalent to (*(E1))->E2 (this is made
clear in C11 by Footnote 96) but C doesn't use the term "access"
in the definition of the * operator. The * operator is defined
to result in an lvalue that designates an object, and operator .
to evaluate the first operand, which doesn't imply accessing it.
If E1->E2 implied accessing all members of *E1 then there would
be no way to assign an initial value to just the E2 member without
also accessing all other members of *E1, even those that haven't
yet been initialized.
Martin