https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121685
--- Comment #4 from Jonathan Wakely <redi at gcc dot gnu.org> --- (In reply to Richard Biener from comment #3) > So even though m_mcowner cannot possibly be bound to nullptr it might still > bind to a released object? Likewise may it bind to an object of > insufficient size? Not in a correct program. If you access an object through a std::vector<int>& reference then there must be a valid object of that type at that location, or you have UB. It's OK to form the reference, e.g. via a cast, but not to access the object through the reference. The usual TBAA rules for pointers. It's OK for a reference to outlive the object it refers to, but you can't access the object after its lifetime ends. > So, consider > > int *p = new int; > int &q = *p; > delete p; > fun (q, 0); > > with > > int fun(int &q, int released) { if (!released) return q; return 0; } The `return q` statement is undefined behaviour within the f(q,0) call, because there is no object within its lifetime at that location. > or > > char c; > int &q = *(char *)&c; The cast is OK, but reading from or writing to q is undefined. > alternatively > > int *p = (int *)malloc (1); > int &q = *p; The cast is OK, and forming the reference is OK, but reading/writing through the reference would not be. There is no object of type int at that location, and the storage is not suitably sized for an int (but malloc does guarantee it's suitably aligned for an int ... but that's not sufficient to make it correct). > or > > char c[1]; > int &q = new int (&c); Even the new-expression might be UB here, because &c is not guaranteed to be sufficiently aligned for int. Even if it happens to be aligned suitably, you can't create an int there because there isn't sufficient storage.