On Fri, 24 Feb 2023 at 09:50, Jonathan Wakely <jwak...@redhat.com> wrote:
>
> On Fri, 24 Feb 2023 at 09:49, Jakub Jelinek wrote:
> >
> > Assuming a compiler handles the T m_vecdata[1]; as flexible array member
> > like (which we need because standard C++ doesn't have flexible array members
> > nor [0] arrays), I wonder if we instead of the m_auto followed by m_data
> > trick couldn't make auto_vec have
> > alignas(vec<vl_embed>) unsigned char buf m_data[sizeof (vec<vl_embed>) + (N 
> > - 1) * sizeof (T)];
> > and do a placement new of vec<vl_embed> into that m_data during auto_vec
> > construction.  Isn't it then similar to how are flexible array members
> > normally used in C, where one uses malloc or alloca to allocate storage
> > for them and the storage can be larger than the structure itself and
> > flexible array member then can use storage after it?
>
> You would still be accessing past the end of the
> vec<vl_embed>::m_vecdata array which is UB.

My thinking is something like:

// New tag type
struct vl_relative { };

// This must only be used as a member subobject of another type
// which provides the trailing storage.
template<typename T>
struct vec<T, va_heap, vl_relative>
{
  T *address (void) { return (T*)(m_vecpfx+1); }
  const T *address (void) const { return (T*)(m_vecpfx+1); }

  alignas(T) alignas(vec_prefix) vec_prefix m_vecpfx;
};

template<typename T, size_t N /* = 0 */>
class auto_vec : public vec<T, va_heap>
{
  // ...
private:
  vec<T, va_heap, vl_relative> m_head;
  T m_data[N];

static_assert(...);
};

Reply via email to