Commit 9a781ed4 authored by Nicholas Ormrod's avatar Nicholas Ormrod Committed by Facebook Github Bot 2

New strings no longer relocatable

Summary:gcc-5.0 introduced non-relocatable strings in libgcc. Only treat gcc < 5 strings as relocatable. Enable relocation for fbstrings via typedef.

Re https://github.com/facebook/folly/issues/316, thanks tomhughes for reporting this.

Reviewed By: snarkmaster, ot

Differential Revision: D3115580

fb-gh-sync-id: d8aff947d55a0a0c57f6b997f651a190e05f2779
fbshipit-source-id: d8aff947d55a0a0c57f6b997f651a190e05f2779
parent 8ddc5992
...@@ -975,6 +975,7 @@ public: ...@@ -975,6 +975,7 @@ public:
> const_reverse_iterator; > const_reverse_iterator;
static const size_type npos; // = size_type(-1) static const size_type npos; // = size_type(-1)
typedef std::true_type IsRelocatable;
private: private:
static void procrustes(size_type& n, size_type nmax) { static void procrustes(size_type& n, size_type nmax) {
......
...@@ -386,7 +386,10 @@ constexpr construct_in_place_t construct_in_place{}; ...@@ -386,7 +386,10 @@ constexpr construct_in_place_t construct_in_place{};
} // namespace folly } // namespace folly
// gcc-5.0 changed string's implementation in libgcc to be non-relocatable
#if __GNUC__ < 5
FOLLY_ASSUME_FBVECTOR_COMPATIBLE_3(std::basic_string); FOLLY_ASSUME_FBVECTOR_COMPATIBLE_3(std::basic_string);
#endif
FOLLY_ASSUME_FBVECTOR_COMPATIBLE_2(std::vector); FOLLY_ASSUME_FBVECTOR_COMPATIBLE_2(std::vector);
FOLLY_ASSUME_FBVECTOR_COMPATIBLE_2(std::list); FOLLY_ASSUME_FBVECTOR_COMPATIBLE_2(std::list);
FOLLY_ASSUME_FBVECTOR_COMPATIBLE_2(std::deque); FOLLY_ASSUME_FBVECTOR_COMPATIBLE_2(std::deque);
......
...@@ -16,6 +16,11 @@ ...@@ -16,6 +16,11 @@
#include <folly/Traits.h> #include <folly/Traits.h>
#include <cstring>
#include <string>
#include <utility>
#include <folly/ScopeGuard.h>
#include <gtest/gtest.h> #include <gtest/gtest.h>
using namespace folly; using namespace folly;
...@@ -108,6 +113,42 @@ TEST(Traits, relational) { ...@@ -108,6 +113,42 @@ TEST(Traits, relational) {
EXPECT_FALSE((folly::greater_than<uint8_t, 255u, uint8_t>(254u))); EXPECT_FALSE((folly::greater_than<uint8_t, 255u, uint8_t>(254u)));
} }
template <typename T, typename... Args>
void testIsRelocatable(Args&&... args) {
if (!IsRelocatable<T>::value) return;
// We use placement new on zeroed memory to avoid garbage subsections
char vsrc[sizeof(T)] = { 0 };
char vdst[sizeof(T)] = { 0 };
char vcpy[sizeof(T)];
T* src = new (vsrc) T(std::forward<Args>(args)...);
SCOPE_EXIT { src->~T(); };
std::memcpy(vcpy, vsrc, sizeof(T));
T deep(*src);
T* dst = new (vdst) T(std::move(*src));
SCOPE_EXIT { dst->~T(); };
EXPECT_EQ(deep, *dst);
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
EXPECT_EQ(deep, *reinterpret_cast<T*>(vcpy));
#pragma GCC diagnostic pop
// This test could technically fail; however, this is what relocation
// almost always means, so it's a good test to have
EXPECT_EQ(std::memcmp(vcpy, vdst, sizeof(T)), 0);
}
TEST(Traits, actuallyRelocatable) {
// Ensure that we test stack and heap allocation for strings with in-situ
// capacity
testIsRelocatable<std::string>("1");
testIsRelocatable<std::string>(sizeof(std::string) + 1, 'x');
testIsRelocatable<std::vector<char>>(5, 'g');
}
struct membership_no {}; struct membership_no {};
struct membership_yes { using x = void; }; struct membership_yes { using x = void; };
FOLLY_CREATE_HAS_MEMBER_TYPE_TRAITS(has_member_type_x, x); FOLLY_CREATE_HAS_MEMBER_TYPE_TRAITS(has_member_type_x, x);
......
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