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

Reply via email to