[clang] [Clang] Add `noalias` to `this` pointer in C++ constructors (PR #136792)

Richard Smith via cfe-commits cfe-commits at lists.llvm.org
Wed Apr 23 15:25:31 PDT 2025


zygoloid wrote:

> * I'm not sure this matches the requirements for C++ semantics; noalias is very aggressive, so we might end up with undefined behavior in unintended cases.  I'd like someone familiar with the relevant standard bits to comment on the requirements here.  CC @zygoloid

The relevant rule is [[class.cdtor]/2](https://eel.is/c++draft/class.cdtor):

> During the construction of an object, if the value of any of its subobjects or any element of its object representation is accessed through a glvalue that is not obtained, directly or indirectly, from the constructor's `this` pointer, the value thus obtained is unspecified.

It would be nice if this explicitly said that the behavior is undefined, rather than the value being unspecified, but I think the effect is mostly the same. (I suggested fixing this a few years ago, but WG21 wanted a paper examining the design space that I didn't have the cycles to work on at the time.) There are two cases here:

* When the access is a read, we can choose that the value obtained is an indeterminate value, for which the uses with defined behavior are [very narrow](https://eel.is/c++draft/basic.indet) (you can copy it around through byte-shaped types, but that's pretty much it). But as long as we're not treating a read through a pointer that aliases part of `*this` as UB, we may be OK here -- we don't have to produce any particular value and can reorder the load past other code, including stores through `*this`.

* When the access is a modification, it's really not clear what "the value thus obtained is unspecified" means, but my best guess is that it means the value stored in the object is unspecified. That might be a problem for `noalias`, because you can't reorder that effect after a store through a pointer that is based on `this`. Eg:

```c++
struct A {
  A(int *p) {
    // Cannot reorder this store past the store to `n`.
    *p = 1;
    n = 2;
  }
  int n;
};
// Must leave a.n == 2.
A a = A(&a);
```

But... I don't know what exactly `noalias` would mean and maybe it's still right in this case.

https://github.com/llvm/llvm-project/pull/136792


More information about the cfe-commits mailing list