On Mon, 26 Feb 2018, Jakub Jelinek wrote: > Hi! > > On Sat, Feb 17, 2018 at 10:08:48AM +0100, Jakub Jelinek wrote: > > Note, this doesn't work, as G++ <= 4.2 rejects: > > template <typename value_type> > > struct S > > { > > char __attribute__ ((__aligned__ (__alignof__ (value_type)))) buf[sizeof > > (value_type)]; > > }; > > > > S<int> s; > > > > with: > > error: requested alignment is not a constant > > > > The following works though, and has been successfully bootstrapped/regtested > > on x86_64-linux and i686-linux. It will fail if we use hash_table on > > overaligned value_type type with alignment > 64, but that is not completely > > unlikely on any target I'm aware of. It uses __alignof__ which should be > > supported by the system GCC's we support for which > > BROKEN_VALUE_INITIALIZATION is true (i.e. >= 3.4 and <= 4.3), non-GCC > > compilers shouldn't get here due to GCC_VERSION != 0 unless they pretend to > > be GCC compatible. > > > > Bootstrapped with system gcc34/g++34 on x86_64-linux, ok for trunk? > > > > 2018-02-17 Jakub Jelinek <ja...@redhat.com> > > > > PR bootstrap/84405 > > * vec.h (vec_default_construct): For BROKEN_VALUE_INITIALIZATION use > > memset and value initialization afterwards. > > * hash-table.h (hash_table<Descriptor, Allocator>::empty_slow): For > > BROKEN_VALUE_INITIALIZATION use placement new into a previously > > cleared appropriately aligned buffer. > > I'd like to ping this patch, or if it isn't acceptable, at least the vec.h > part of it which isn't really more complex than what we have right now.
So BROKEN_VALUE_INITIALIZATION doesn't really mean it's "broken" but that is has certain behavior that doesn't invalidate the clearing done earlier? That said, I wonder if first doing the regular construction and memset afterwards in case of BROKEN_VALUE_INITIALIZATION wouldn't be more reliable and "easier"? > > --- gcc/vec.h.jj 2018-02-16 19:39:03.637058918 +0100 > > +++ gcc/vec.h 2018-02-16 23:51:55.389582056 +0100 > > @@ -490,12 +490,11 @@ template <typename T> > > inline void > > vec_default_construct (T *dst, unsigned n) > > { > > -#ifndef BROKEN_VALUE_INITIALIZATION > > - for ( ; n; ++dst, --n) > > - ::new (static_cast<void*>(dst)) T (); > > -#else > > +#ifdef BROKEN_VALUE_INITIALIZATION > > memset (dst, '\0', sizeof (T) * n); > > #endif > > + for ( ; n; ++dst, --n) > > + ::new (static_cast<void*>(dst)) T (); > > } > > > > /* Copy-construct N elements in DST from *SRC. */ > > --- gcc/hash-table.h.jj 2018-02-16 19:39:03.660058934 +0100 > > +++ gcc/hash-table.h 2018-02-17 00:01:24.207723925 +0100 > > @@ -808,7 +808,18 @@ hash_table<Descriptor, Allocator>::empty > > for ( ; size; ++entries, --size) > > *entries = value_type (); > > #else > > - memset (entries, 0, size * sizeof (value_type)); > > + /* To workaround older GCC versions which don't handle value > > + initialization right, use a placement new into previously > > + cleared buffer. */ > > + char buf[2 * sizeof (value_type) + 64]; > > + gcc_assert (__alignof__ (value_type) <= sizeof (value_type) + 64); > > + char *q = (buf + sizeof (value_type) + 64 > > + - ((uintptr_t) buf % __alignof__ (value_type))); > > + memset (q, '\0', sizeof (value_type)); > > + value_type *p = ::new (q) value_type (); > > + for ( ; size; ++entries, --size) > > + *entries = *p; > > + p->~value_type (); > > #endif > > } > > m_n_deleted = 0; > > Jakub > > -- Richard Biener <rguent...@suse.de> SUSE LINUX GmbH, GF: Felix Imendoerffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nuernberg)