Skip to content

CWG2957 [expr.ref] Evaluating a non-static reference member is not access #634

Description

@frederick-vs-ja

Full name of submitter (unless configured in github; will be published with the issue): Jiang An

Reference (section label): [expr.ref], [intro.memory]

Link to reflector thread (if any):

Issue description:

Currently, the following example is rejected by some implementation, because they think volatile reading is performed (Godbolt link).

int n{};
struct S { int& r; };
constexpr S s{n};
constexpr volatile S s2{n};

static_assert(&static_cast<const volatile S&>(s).r == &n); // GCC rejects this
static_assert(&s2.r == &n); // GCC and Clang reject this

However, the standard wording doesn't ever seem to consider s or s2 to be accessed. It's unclear whether this is intended.

Also, assuming f1 and f2 are concurrently executed in different threads in the following example.

struct S { int& r; }; // Note that S is trivially copyable and thus memcpy/memmove calls can be well-defined.

S s{/* ... */};

void f1() {
  int* p = &s.r;
  // operations unrelated to s
}

void f2(const S& s2) {
  std::memcpy(&s, &s2, sizeof(S));
}

It seems that there can't be data race (in the standard meaning) due to the current specification because s is not considered accessed in f1. But presumably there should be UB due to data race.

A note in [intro.memory] suggests that this falls into the "additional memory location" case. However, the current specification doesn't seem to allow such additional memory location to be observable or accessed.

Suggested resolution:

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions