Skip to content

CWG3219 [basic.types.trivial] Overeager no-op when no suitable value for value representation #980

Description

@hubert-reinterpretcast

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

Reference (section label): [basic.types.trivial]

Link to reflector thread (if any): N/A

Issue description:

The wording says:

in which case the object’s value is replaced with an unspecified member of the corresponding subset that would result in the program having defined behavior, if any.

In other words, the object's value is unchanged/the object does not receive a value when no such value exists.

This runs into problems with the following:

  • The symbolic value model does not acknowledge any changes to the value from manipulation of the object representation except when an object acquires a value representation.
  • bit_cast has undefined behaviour when an object in the result does not receive a value.

For the first, consider:

#include <cstring>
int main(void) {
  int x = 42, *p = &x, *q = p + 1;
  std::memcpy(&p, &q,
              sizeof(p)); // giving `p` the value of `q` would _not_ lead to the
                          // program having defined behaviour
  return *p; // Is the value of `p` here still `&x`? Prior to P2434R5, no.
             // After: Maybe, but no UB if not (could be `&errno`)—seems
             // unimplementable in general.
}

For the second, consider:

#include <memory>
#include <cstdio>
int main(void) {
  int x = 42, *p = &x, *q = p + 1;
  p = std::bit_cast<int *>(q);  // UB here
  std::fprintf(stderr, "Hello!\n");  // observable checkpoint too late
  return *p;
}

Note that the status quo before P2434R5 already made the bit_cast case undefined behaviour when the value representation did not correspond to any value of the object's type.

Suggested resolution:

in which case the object’s value is replaced with an unspecified member of the corresponding subset, if any, that—if possible—would result in the program having defined behavior, if any. [Note: Lvalue-to-rvalue conversion has undefined behavior if the value representation of the object is not valid for the object's type.]

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions