aboutsummaryrefslogtreecommitdiff
path: root/gcc/vec.h
diff options
context:
space:
mode:
authorMartin Sebor <msebor@redhat.com>2017-06-16 03:48:59 +0000
committerMartin Sebor <msebor@gcc.gnu.org>2017-06-15 21:48:59 -0600
commitc3684b7b86da9b6b01f6fb274227fc6401df053e (patch)
tree921877ef9f69c6bac6285495a3eec052a4fad2a3 /gcc/vec.h
parent6a382041ddccd829db190f7c112ecfff2e7d369a (diff)
downloadgcc-c3684b7b86da9b6b01f6fb274227fc6401df053e.zip
gcc-c3684b7b86da9b6b01f6fb274227fc6401df053e.tar.gz
gcc-c3684b7b86da9b6b01f6fb274227fc6401df053e.tar.bz2
PR c++/80560 - warn on undefined memory operations involving non-trivial types
gcc/c-family/ChangeLog: PR c++/80560 * c.opt (-Wclass-memaccess): New option. gcc/cp/ChangeLog: PR c++/80560 * call.c (first_non_public_field, maybe_warn_class_memaccess): New functions. (has_trivial_copy_assign_p, has_trivial_copy_p): Ditto. (build_cxx_call): Call maybe_warn_class_memaccess. gcc/ChangeLog: PR c++/80560 * dumpfile.c (dump_register): Avoid calling memset to initialize a class with a default ctor. * gcc.c (struct compiler): Remove const qualification. * genattrtab.c (gen_insn_reserv): Replace memset with initialization. * hash-table.h: Ditto. * ipa-cp.c (allocate_and_init_ipcp_value): Replace memset with assignment. * ipa-prop.c (ipa_free_edge_args_substructures): Ditto. * omp-low.c (lower_omp_ordered_clauses): Replace memset with default ctor. * params.h (struct param_info): Make struct members non-const. * tree-switch-conversion.c (emit_case_bit_tests): Replace memset with default initialization. * vec.h (vec_copy_construct, vec_default_construct): New helper functions. (vec<T>::copy, vec<T>::splice, vec<T>::reserve): Replace memcpy with vec_copy_construct. (vect<T>::quick_grow_cleared): Replace memset with default ctor. (vect<T>::vec_safe_grow_cleared, vec_safe_grow_cleared): Same. * doc/invoke.texi (-Wclass-memaccess): Document. libcpp/ChangeLog: PR c++/80560 * line-map.c (line_maps::~line_maps): Avoid calling htab_delete with a null pointer. (linemap_init): Avoid calling memset on an object of a non-trivial type. libitm/ChangeLog: PR c++/80560 * beginend.cc (GTM::gtm_thread::rollback): Avoid calling memset on an object of a non-trivial type. (GTM::gtm_transaction_cp::commit): Use assignment instead of memcpy to copy an object. * method-ml.cc (orec_iterator::reinit): Avoid -Wclass-memaccess. gcc/testsuite/ChangeLog: PR c++/80560 * g++.dg/Wclass-memaccess.C: New test. From-SVN: r249234
Diffstat (limited to 'gcc/vec.h')
-rw-r--r--gcc/vec.h41
1 files changed, 30 insertions, 11 deletions
diff --git a/gcc/vec.h b/gcc/vec.h
index 755a1f8..cbdd439 100644
--- a/gcc/vec.h
+++ b/gcc/vec.h
@@ -407,6 +407,26 @@ struct GTY((user)) vec
{
};
+/* Default-construct N elements in DST. */
+
+template <typename T>
+inline void
+vec_default_construct (T *dst, unsigned n)
+{
+ for ( ; n; ++dst, --n)
+ ::new (static_cast<void*>(dst)) T ();
+}
+
+/* Copy-construct N elements in DST from *SRC. */
+
+template <typename T>
+inline void
+vec_copy_construct (T *dst, const T *src, unsigned n)
+{
+ for ( ; n; ++dst, ++src, --n)
+ ::new (static_cast<void*>(dst)) T (*src);
+}
+
/* Type to provide NULL values for vec<T, A, L>. This is used to
provide nil initializers for vec instances. Since vec must be
a POD, we cannot have proper ctor/dtor for it. To initialize
@@ -612,7 +632,7 @@ vec_safe_grow_cleared (vec<T, A, vl_embed> *&v, unsigned len CXX_MEM_STAT_INFO)
{
unsigned oldlen = vec_safe_length (v);
vec_safe_grow (v, len PASS_MEM_STAT);
- memset (&(v->address ()[oldlen]), 0, sizeof (T) * (len - oldlen));
+ vec_default_construct (v->address () + oldlen, len - oldlen);
}
@@ -818,7 +838,7 @@ vec<T, A, vl_embed>::copy (ALONE_MEM_STAT_DECL) const
{
vec_alloc (new_vec, len PASS_MEM_STAT);
new_vec->embedded_init (len, len);
- memcpy (new_vec->address (), m_vecdata, sizeof (T) * len);
+ vec_copy_construct (new_vec->address (), m_vecdata, len);
}
return new_vec;
}
@@ -835,7 +855,7 @@ vec<T, A, vl_embed>::splice (const vec<T, A, vl_embed> &src)
if (len)
{
gcc_checking_assert (space (len));
- memcpy (address () + length (), src.address (), len * sizeof (T));
+ vec_copy_construct (end (), src.address (), len);
m_vecpfx.m_num += len;
}
}
@@ -1089,13 +1109,12 @@ inline void
vec<T, A, vl_embed>::quick_grow_cleared (unsigned len)
{
unsigned oldlen = length ();
- size_t sz = sizeof (T) * (len - oldlen);
+ size_t growby = len - oldlen;
quick_grow (len);
- if (sz != 0)
- memset (&(address ()[oldlen]), 0, sz);
+ if (growby != 0)
+ vec_default_construct (address () + oldlen, growby);
}
-
/* Garbage collection support for vec<T, A, vl_embed>. */
template<typename T>
@@ -1454,7 +1473,7 @@ vec<T, va_heap, vl_ptr>::reserve (unsigned nelems, bool exact MEM_STAT_DECL)
va_heap::reserve (m_vec, nelems, exact PASS_MEM_STAT);
if (handle_auto_vec)
{
- memcpy (m_vec->address (), oldvec->address (), sizeof (T) * oldsize);
+ vec_copy_construct (m_vec->address (), oldvec->address (), oldsize);
m_vec->m_vecpfx.m_num = oldsize;
}
@@ -1616,10 +1635,10 @@ inline void
vec<T, va_heap, vl_ptr>::safe_grow_cleared (unsigned len MEM_STAT_DECL)
{
unsigned oldlen = length ();
- size_t sz = sizeof (T) * (len - oldlen);
+ size_t growby = len - oldlen;
safe_grow (len PASS_MEM_STAT);
- if (sz != 0)
- memset (&(address ()[oldlen]), 0, sz);
+ if (growby != 0)
+ vec_default_construct (address () + oldlen, growby);
}