Commit af7efaaf authored by Kenton Varda's avatar Kenton Varda

Fix canMemcpy() on GCC 5+.

I'm not really sure how Cap'n Proto has worked at all on GCC 5. For some reason this only ended up being tickled after e6e29122.

Fixes #442.
parent cd85d7f1
...@@ -251,6 +251,8 @@ private: ...@@ -251,6 +251,8 @@ private:
friend class Array; friend class Array;
}; };
static_assert(!canMemcpy<Array<char>>(), "canMemcpy<>() is broken");
namespace _ { // private namespace _ { // private
class HeapArrayDisposer final: public ArrayDisposer { class HeapArrayDisposer final: public ArrayDisposer {
......
...@@ -455,17 +455,19 @@ constexpr bool canConvert() { ...@@ -455,17 +455,19 @@ constexpr bool canConvert() {
return sizeof(CanConvert_<U>::sfinae(instance<T>())) == sizeof(int); return sizeof(CanConvert_<U>::sfinae(instance<T>())) == sizeof(int);
} }
#if __clang__ #if __GNUC__ && !__clang__ && __GNUC__ < 5
template <typename T> template <typename T>
constexpr bool canMemcpy() { constexpr bool canMemcpy() {
// Returns true if T can be copied using memcpy instead of using the copy constructor or // Returns true if T can be copied using memcpy instead of using the copy constructor or
// assignment operator. // assignment operator.
// Clang unhelpfully defines __has_trivial_{copy,assign}(T) to be true if the copy constructor / // GCC 4 does not have __is_trivially_constructible and friends, but it does have these older
// assign operator are deleted, on the basis that a strict reading of the definition of "trivial" // intrinsics. Annoyingly, GCC 5+ and Clang define __has_trivial_copy() to be true if the copy
// according to the standard says that deleted functions are in fact trivial. Meanwhile Clang // constructor has been deleted, on the basis t hat a strict reading of the definition of
// provides these admittedly-better intrinsics, but GCC does not. // "trivial" according to the standard says that deleted functions are in fact trivial, thus
return __is_trivially_constructible(T, const T&) && __is_trivially_assignable(T, const T&); // making the intrinsics essentially worthless. GCC 4, however, happens to define them the way
// we want.
return __has_trivial_copy(T) && __has_trivial_assign(T);
} }
#else #else
template <typename T> template <typename T>
...@@ -473,8 +475,7 @@ constexpr bool canMemcpy() { ...@@ -473,8 +475,7 @@ constexpr bool canMemcpy() {
// Returns true if T can be copied using memcpy instead of using the copy constructor or // Returns true if T can be copied using memcpy instead of using the copy constructor or
// assignment operator. // assignment operator.
// GCC defines these to mean what we want them to mean. return __is_trivially_constructible(T, const T&) && __is_trivially_assignable(T, const T&);
return __has_trivial_copy(T) && __has_trivial_assign(T);
} }
#endif #endif
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment