Merge branch 'gerrit' to 'master'
diff --git a/src/google/protobuf/arena.cc b/src/google/protobuf/arena.cc index bda3741..f7059d2 100755 --- a/src/google/protobuf/arena.cc +++ b/src/google/protobuf/arena.cc
@@ -29,6 +29,7 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include <google/protobuf/arena.h> +#include <google/protobuf/stubs/common.h> #ifdef ADDRESS_SANITIZER #include <sanitizer/asan_interface.h> @@ -43,6 +44,12 @@ static GOOGLE_THREAD_LOCAL ThreadCache thread_cache_ = { -1, NULL }; return thread_cache_; } +#elif defined(GOOGLE_PROTOBUF_OS_ANDROID) || defined(GOOGLE_PROTOBUF_OS_IPHONE) +Arena::ThreadCache& Arena::thread_cache() { + static internal::ThreadLocalStorage<ThreadCache>* thread_cache_ = + new internal::ThreadLocalStorage<ThreadCache>(); + return *thread_cache_->Get(); +} #else GOOGLE_THREAD_LOCAL Arena::ThreadCache Arena::thread_cache_ = { -1, NULL }; #endif
diff --git a/src/google/protobuf/arena.h b/src/google/protobuf/arena.h index bb15e80..b48bef9 100644 --- a/src/google/protobuf/arena.h +++ b/src/google/protobuf/arena.h
@@ -373,6 +373,11 @@ // Thread local variables cannot be exposed through DLL interface but we can // wrap them in static functions. static ThreadCache& thread_cache(); +#elif defined(GOOGLE_PROTOBUF_OS_ANDROID) || defined(GOOGLE_PROTOBUF_OS_IPHONE) + // Android ndk does not support __thread keyword so we use a custom thread + // local storage class we implemented. + // iOS also does not support the __thread keyword. + static ThreadCache& thread_cache(); #else static GOOGLE_THREAD_LOCAL ThreadCache thread_cache_; static ThreadCache& thread_cache() { return thread_cache_; }
diff --git a/src/google/protobuf/compiler/command_line_interface_unittest.cc b/src/google/protobuf/compiler/command_line_interface_unittest.cc index a2cbbdc..e284c79 100644 --- a/src/google/protobuf/compiler/command_line_interface_unittest.cc +++ b/src/google/protobuf/compiler/command_line_interface_unittest.cc
@@ -288,6 +288,7 @@ if (!disallow_plugins_) { cli_.AllowPlugins("prefix-"); +#ifndef GOOGLE_THIRD_PARTY_PROTOBUF const char* possible_paths[] = { // When building with shared libraries, libtool hides the real executable // in .libs and puts a fake wrapper in the current directory. @@ -316,6 +317,11 @@ } if (plugin_path.empty()) { +#else + string plugin_path = "third_party/protobuf/test_plugin"; + + if (access(plugin_path.c_str(), F_OK) != 0) { +#endif // GOOGLE_THIRD_PARTY_PROTOBUF GOOGLE_LOG(ERROR) << "Plugin executable not found. Plugin tests are likely to fail."; } else {
diff --git a/src/google/protobuf/compiler/cpp/cpp_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_unittest.cc index cc758cf..9d14a92 100644 --- a/src/google/protobuf/compiler/cpp/cpp_unittest.cc +++ b/src/google/protobuf/compiler/cpp/cpp_unittest.cc
@@ -1392,6 +1392,12 @@ case unittest::TestOneof2::kFooString: EXPECT_TRUE(message.has_foo_string()); break; + case unittest::TestOneof2::kFooCord: + EXPECT_TRUE(message.has_foo_cord()); + break; + case unittest::TestOneof2::kFooStringPiece: + EXPECT_TRUE(message.has_foo_string_piece()); + break; case unittest::TestOneof2::kFooBytes: EXPECT_TRUE(message.has_foo_bytes()); break; @@ -1404,6 +1410,9 @@ case unittest::TestOneof2::kFoogroup: EXPECT_TRUE(message.has_foogroup()); break; + case unittest::TestOneof2::kFooLazyMessage: + EXPECT_TRUE(message.has_foo_lazy_message()); + break; case unittest::TestOneof2::FOO_NOT_SET: break; }
diff --git a/src/google/protobuf/descriptor.h b/src/google/protobuf/descriptor.h index 0e264f5..c0a48ce 100644 --- a/src/google/protobuf/descriptor.h +++ b/src/google/protobuf/descriptor.h
@@ -59,6 +59,10 @@ #include <vector> #include <google/protobuf/stubs/common.h> +// TYPE_BOOL is defined in the MacOS's ConditionalMacros.h. +#ifdef TYPE_BOOL +#undef TYPE_BOOL +#endif // TYPE_BOOL namespace google { namespace protobuf {
diff --git a/src/google/protobuf/preserve_unknown_enum_test.cc b/src/google/protobuf/preserve_unknown_enum_test.cc index 9f8703a..1673e8a 100644 --- a/src/google/protobuf/preserve_unknown_enum_test.cc +++ b/src/google/protobuf/preserve_unknown_enum_test.cc
@@ -246,8 +246,6 @@ protobuf_unittest::TestAllTypes message; // proto2 message const google::protobuf::Reflection* r = message.GetReflection(); const google::protobuf::Descriptor* d = message.GetDescriptor(); - const google::protobuf::FieldDescriptor* singular_field = - d->FindFieldByName("optional_nested_enum"); const google::protobuf::FieldDescriptor* repeated_field = d->FindFieldByName("repeated_nested_enum"); // Add one element to the repeated field so that we can test @@ -258,6 +256,8 @@ r->AddEnum(&message, repeated_field, enum_value); #ifdef PROTOBUF_HAS_DEATH_TEST + const google::protobuf::FieldDescriptor* singular_field = + d->FindFieldByName("optional_nested_enum"); // Enum-field integer-based setters GOOGLE_DCHECK-fail on invalid values, in order to // remain consistent with proto2 generated code. EXPECT_DEBUG_DEATH({
diff --git a/src/google/protobuf/repeated_field.h b/src/google/protobuf/repeated_field.h index f5f5d3f..7bfdc40 100644 --- a/src/google/protobuf/repeated_field.h +++ b/src/google/protobuf/repeated_field.h
@@ -626,7 +626,7 @@ DECLARE_SPECIALIZATIONS_FOR_BASE_PROTO_TYPES(Message); -#undef DECLARE_SPECIALIZATIONS_FOR_BASE_CLASSES +#undef DECLARE_SPECIALIZATIONS_FOR_BASE_PROTO_TYPES template <> inline const MessageLite& GenericTypeHandler<MessageLite>::default_instance() {
diff --git a/src/google/protobuf/stubs/atomicops_internals_pnacl.h b/src/google/protobuf/stubs/atomicops_internals_pnacl.h index b10ac02..3b314fd 100644 --- a/src/google/protobuf/stubs/atomicops_internals_pnacl.h +++ b/src/google/protobuf/stubs/atomicops_internals_pnacl.h
@@ -33,39 +33,197 @@ #ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_PNACL_H_ #define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_PNACL_H_ +#include <atomic> + namespace google { namespace protobuf { namespace internal { +// This implementation is transitional and maintains the original API for +// atomicops.h. This requires casting memory locations to the atomic types, and +// assumes that the API and the C++11 implementation are layout-compatible, +// which isn't true for all implementations or hardware platforms. The static +// assertion should detect this issue, were it to fire then this header +// shouldn't be used. +// +// TODO(jfb) If this header manages to stay committed then the API should be +// modified, and all call sites updated. +typedef volatile std::atomic<Atomic32>* AtomicLocation32; +static_assert(sizeof(*(AtomicLocation32) nullptr) == sizeof(Atomic32), + "incompatible 32-bit atomic layout"); + +inline void MemoryBarrier() { +#if defined(__GLIBCXX__) + // Work around libstdc++ bug 51038 where atomic_thread_fence was declared but + // not defined, leading to the linker complaining about undefined references. + __atomic_thread_fence(std::memory_order_seq_cst); +#else + std::atomic_thread_fence(std::memory_order_seq_cst); +#endif +} + inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, Atomic32 old_value, Atomic32 new_value) { - return __sync_val_compare_and_swap(ptr, old_value, new_value); + ((AtomicLocation32)ptr) + ->compare_exchange_strong(old_value, + new_value, + std::memory_order_relaxed, + std::memory_order_relaxed); + return old_value; } -inline void MemoryBarrier() { - __sync_synchronize(); +inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, + Atomic32 new_value) { + return ((AtomicLocation32)ptr) + ->exchange(new_value, std::memory_order_relaxed); +} + +inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, + Atomic32 increment) { + return increment + + ((AtomicLocation32)ptr) + ->fetch_add(increment, std::memory_order_relaxed); +} + +inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, + Atomic32 increment) { + return increment + ((AtomicLocation32)ptr)->fetch_add(increment); } inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, Atomic32 old_value, Atomic32 new_value) { - Atomic32 ret = NoBarrier_CompareAndSwap(ptr, old_value, new_value); + ((AtomicLocation32)ptr) + ->compare_exchange_strong(old_value, + new_value, + std::memory_order_acquire, + std::memory_order_acquire); + return old_value; +} + +inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + ((AtomicLocation32)ptr) + ->compare_exchange_strong(old_value, + new_value, + std::memory_order_release, + std::memory_order_relaxed); + return old_value; +} + +inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) { + ((AtomicLocation32)ptr)->store(value, std::memory_order_relaxed); +} + +inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) { + ((AtomicLocation32)ptr)->store(value, std::memory_order_relaxed); MemoryBarrier(); - return ret; } inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) { - MemoryBarrier(); - *ptr = value; + ((AtomicLocation32)ptr)->store(value, std::memory_order_release); +} + +inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) { + return ((AtomicLocation32)ptr)->load(std::memory_order_relaxed); } inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) { - Atomic32 value = *ptr; - MemoryBarrier(); - return value; + return ((AtomicLocation32)ptr)->load(std::memory_order_acquire); } +inline Atomic32 Release_Load(volatile const Atomic32* ptr) { + MemoryBarrier(); + return ((AtomicLocation32)ptr)->load(std::memory_order_relaxed); +} + +#if defined(GOOGLE_PROTOBUF_ARCH_64_BIT) + +typedef volatile std::atomic<Atomic64>* AtomicLocation64; +static_assert(sizeof(*(AtomicLocation64) nullptr) == sizeof(Atomic64), + "incompatible 64-bit atomic layout"); + +inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) { + ((AtomicLocation64)ptr) + ->compare_exchange_strong(old_value, + new_value, + std::memory_order_relaxed, + std::memory_order_relaxed); + return old_value; +} + +inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, + Atomic64 new_value) { + return ((AtomicLocation64)ptr) + ->exchange(new_value, std::memory_order_relaxed); +} + +inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr, + Atomic64 increment) { + return increment + + ((AtomicLocation64)ptr) + ->fetch_add(increment, std::memory_order_relaxed); +} + +inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr, + Atomic64 increment) { + return increment + ((AtomicLocation64)ptr)->fetch_add(increment); +} + +inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) { + ((AtomicLocation64)ptr) + ->compare_exchange_strong(old_value, + new_value, + std::memory_order_acquire, + std::memory_order_acquire); + return old_value; +} + +inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) { + ((AtomicLocation64)ptr) + ->compare_exchange_strong(old_value, + new_value, + std::memory_order_release, + std::memory_order_relaxed); + return old_value; +} + +inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) { + ((AtomicLocation64)ptr)->store(value, std::memory_order_relaxed); +} + +inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) { + ((AtomicLocation64)ptr)->store(value, std::memory_order_relaxed); + MemoryBarrier(); +} + +inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) { + ((AtomicLocation64)ptr)->store(value, std::memory_order_release); +} + +inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) { + return ((AtomicLocation64)ptr)->load(std::memory_order_relaxed); +} + +inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) { + return ((AtomicLocation64)ptr)->load(std::memory_order_acquire); +} + +inline Atomic64 Release_Load(volatile const Atomic64* ptr) { + MemoryBarrier(); + return ((AtomicLocation64)ptr)->load(std::memory_order_relaxed); +} + +#endif // defined(GOOGLE_PROTOBUF_ARCH_64_BIT) + } // namespace internal } // namespace protobuf } // namespace google
diff --git a/src/google/protobuf/stubs/common.h b/src/google/protobuf/stubs/common.h index c3f735a..37123c7 100644 --- a/src/google/protobuf/stubs/common.h +++ b/src/google/protobuf/stubs/common.h
@@ -62,6 +62,14 @@ #include <exception> #endif +#if defined(__APPLE__) +#include <TargetConditionals.h> // for TARGET_OS_IPHONE +#endif + +#if defined(__ANDROID__) || defined(GOOGLE_PROTOBUF_OS_ANDROID) || (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) || defined(GOOGLE_PROTOBUF_OS_IPHONE) +#include <pthread.h> +#endif + #if defined(_WIN32) && defined(GetMessage) // Allow GetMessage to be used as a valid method name in protobuf classes. // windows.h defines GetMessage() as a macro. Let's re-define it as an inline @@ -157,7 +165,7 @@ typedef unsigned int uint; #ifdef _MSC_VER -typedef __int8 int8; +typedef signed __int8 int8; typedef __int16 int16; typedef __int32 int32; typedef __int64 int64; @@ -1158,6 +1166,38 @@ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MutexLockMaybe); }; +#if defined(__ANDROID__) || defined(GOOGLE_PROTOBUF_OS_ANDROID) || (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) || defined(GOOGLE_PROTOBUF_OS_IPHONE) +// Android ndk does not support the __thread keyword very well yet. Here +// we use pthread_key_create()/pthread_getspecific()/... methods for +// TLS support on android. +// iOS also does not support the __thread keyword. +template<typename T> +class ThreadLocalStorage { + public: + ThreadLocalStorage() { + pthread_key_create(&key_, &ThreadLocalStorage::Delete); + } + ~ThreadLocalStorage() { + pthread_key_delete(key_); + } + T* Get() { + T* result = static_cast<T*>(pthread_getspecific(key_)); + if (result == NULL) { + result = new T(); + pthread_setspecific(key_, result); + } + return result; + } + private: + static void Delete(void* value) { + delete static_cast<T*>(value); + } + pthread_key_t key_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ThreadLocalStorage); +}; +#endif + } // namespace internal // We made these internal so that they would show up as such in the docs,
diff --git a/src/google/protobuf/stubs/hash.h b/src/google/protobuf/stubs/hash.h index 82d5052..11bc2b3 100755 --- a/src/google/protobuf/stubs/hash.h +++ b/src/google/protobuf/stubs/hash.h
@@ -172,6 +172,13 @@ } }; +template<> +struct hash<bool> { + size_t operator()(bool x) const { + return static_cast<size_t>(x); + } +}; + template <typename Key, typename Data, typename HashFcn = hash<Key>, typename EqualKey = std::equal_to<Key>, @@ -204,7 +211,7 @@ static const size_t bucket_size = 4; static const size_t min_buckets = 8; - inline size_t operator()(const string& a, const string& b) const { + inline bool operator()(const string& a, const string& b) const { return a < b; } }; @@ -222,7 +229,7 @@ static const size_t bucket_size = 4; static const size_t min_buckets = 8; - inline size_t operator()(const pair<First, Second>& a, + inline bool operator()(const pair<First, Second>& a, const pair<First, Second>& b) const { return a < b; }
diff --git a/src/google/protobuf/stubs/platform_macros.h b/src/google/protobuf/stubs/platform_macros.h index 1ff09b8..2ce7fc8 100644 --- a/src/google/protobuf/stubs/platform_macros.h +++ b/src/google/protobuf/stubs/platform_macros.h
@@ -95,12 +95,18 @@ #if defined(__APPLE__) #define GOOGLE_PROTOBUF_OS_APPLE +#include <TargetConditionals.h> +#if TARGET_OS_IPHONE +#define GOOGLE_PROTOBUF_OS_IPHONE +#endif #elif defined(__native_client__) #define GOOGLE_PROTOBUF_OS_NACL #elif defined(sun) #define GOOGLE_PROTOBUF_OS_SOLARIS #elif defined(_AIX) #define GOOGLE_PROTOBUF_OS_AIX +#elif defined(__ANDROID__) +#define GOOGLE_PROTOBUF_OS_ANDROID #endif #undef GOOGLE_PROTOBUF_PLATFORM_ERROR
diff --git a/src/google/protobuf/stubs/type_traits.h b/src/google/protobuf/stubs/type_traits.h index b58cae3..36a8f3b 100644 --- a/src/google/protobuf/stubs/type_traits.h +++ b/src/google/protobuf/stubs/type_traits.h
@@ -73,6 +73,10 @@ typedef char (&yes)[1]; typedef char (&no)[2]; + // BEGIN GOOGLE LOCAL MODIFICATION -- check is a #define on Mac. + #undef check + // END GOOGLE LOCAL MODIFICATION + static yes check(const B*); static no check(const void*);
diff --git a/src/google/protobuf/testing/googletest.cc b/src/google/protobuf/testing/googletest.cc index d72fa5c..5f6a199 100644 --- a/src/google/protobuf/testing/googletest.cc +++ b/src/google/protobuf/testing/googletest.cc
@@ -65,6 +65,7 @@ #endif string TestSourceDir() { +#ifndef GOOGLE_THIRD_PARTY_PROTOBUF #ifdef _MSC_VER // Look for the "src" directory. string prefix = "."; @@ -88,6 +89,9 @@ return result; } #endif +#else + return "third_party/protobuf/src"; +#endif // GOOGLE_THIRD_PARTY_PROTOBUF } namespace {