On Fri, 16 Feb 2018, Jakub Jelinek wrote: > Hi! > > As the system.h comment says, it took us years to get value initialization > right, and unfortunately we've started hitting it in GCC codebase now. > There are various related PRs, 4.2.[0-3] are most broken in this regard, > value initialization of non-PODs doesn't actually initialize there anything, > but https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84405#c5 shows a testcase > where any GCC < 4.3 just calls the default ctor for the > *entries = value_type (); > in hash-table.h even when value_type has no user provided ctor, and one > pointer field and another field with user provided ctor. We want to > zero initialize the pointer and default initialize the other field, but > < 4.3 just default initializes the other field and pointer (m_key) remains > uninitialized. > The vec_default_construct case can hit another bug in < 4.4, if we have a > similar class with multiple fields and at least one of them with user provided > ctor, and at least one of them without user provided ctor, the new T () > default initializes it rather than value initializes it. > > The following patch provides sufficient workaround so that GCC 3.4.6 as a > system compiler can bootstrap GCC (haven't tested other versions). It is > not enough to get GCC 4.2.[0-3] usable as bootstrap compiler, either we add > 2-3 further workarounds, or just reject GCC >= 4.2.0 and <= 4.2.3 in > configure. > > Ok for trunk?
Ok. I'll see if fixing libcpp makes GCC 4.2.[0-3] usable as well. Richard. > 2018-02-16 Jakub Jelinek <ja...@redhat.com> > > PR bootstrap/84405 > * system.h (BROKEN_VALUE_INITIALIZATION): Define for GCC < 4.3. > * vec.h (vec_default_construct): Use memset instead of placement new > if BROKEN_VALUE_INITIALIZATION is defined. > * hash-table.h (hash_table<Descriptor, Allocator>::empty_slow): Use > memset instead of value initialization if BROKEN_VALUE_INITIALIZATION > is defined. > > --- gcc/system.h.jj 2018-01-03 10:19:54.530533857 +0100 > +++ gcc/system.h 2018-02-15 21:56:37.168139415 +0100 > @@ -824,6 +824,12 @@ extern void fancy_abort (const char *, i > /* Some compilers do not allow the use of unsigned char in bitfields. */ > #define BOOL_BITFIELD unsigned int > > +/* GCC older than 4.4 have broken C++ value initialization handling, see > + PR11309, PR30111, PR33916, PR82939 and PR84405 for more details. */ > +#if GCC_VERSION > 0 && GCC_VERSION < 4004 && !defined(__clang__) > +# define BROKEN_VALUE_INITIALIZATION > +#endif > + > /* As the last action in this file, we poison the identifiers that > shouldn't be used. Note, luckily gcc-3.0's token-based integrated > preprocessor won't trip on poisoned identifiers that arrive from > --- gcc/vec.h.jj 2018-01-03 10:19:54.606533869 +0100 > +++ gcc/vec.h 2018-02-15 22:00:36.386216876 +0100 > @@ -490,8 +490,12 @@ 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 > + memset (dst, '\0', sizeof (T) * n); > +#endif > } > > /* Copy-construct N elements in DST from *SRC. */ > --- gcc/hash-table.h.jj 2018-01-03 10:19:54.899533916 +0100 > +++ gcc/hash-table.h 2018-02-15 21:58:14.449170915 +0100 > @@ -804,8 +804,12 @@ hash_table<Descriptor, Allocator>::empty > } > else > { > +#ifndef BROKEN_VALUE_INITIALIZATION > for ( ; size; ++entries, --size) > *entries = value_type (); > +#else > + memset (entries, 0, size * sizeof (value_type)); > +#endif > } > m_n_deleted = 0; > m_n_elements = 0; > > Jakub > > -- Richard Biener <rguent...@suse.de> SUSE LINUX GmbH, GF: Felix Imendoerffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nuernberg)