Переглянути джерело

Merge branch 'gerrit' to 'master'

Feng Xiao 10 роки тому
батько
коміт
de5d45500c

+ 7 - 0
src/google/protobuf/arena.cc

@@ -29,6 +29,7 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
 #include <google/protobuf/arena.h>
 #include <google/protobuf/arena.h>
+#include <google/protobuf/stubs/common.h>
 
 
 #ifdef ADDRESS_SANITIZER
 #ifdef ADDRESS_SANITIZER
 #include <sanitizer/asan_interface.h>
 #include <sanitizer/asan_interface.h>
@@ -43,6 +44,12 @@ Arena::ThreadCache& Arena::thread_cache() {
   static GOOGLE_THREAD_LOCAL ThreadCache thread_cache_ = { -1, NULL };
   static GOOGLE_THREAD_LOCAL ThreadCache thread_cache_ = { -1, NULL };
   return thread_cache_;
   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
 #else
 GOOGLE_THREAD_LOCAL Arena::ThreadCache Arena::thread_cache_ = { -1, NULL };
 GOOGLE_THREAD_LOCAL Arena::ThreadCache Arena::thread_cache_ = { -1, NULL };
 #endif
 #endif

+ 5 - 0
src/google/protobuf/arena.h

@@ -373,6 +373,11 @@ class LIBPROTOBUF_EXPORT Arena {
   // Thread local variables cannot be exposed through DLL interface but we can
   // Thread local variables cannot be exposed through DLL interface but we can
   // wrap them in static functions.
   // wrap them in static functions.
   static ThreadCache& thread_cache();
   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
 #else
   static GOOGLE_THREAD_LOCAL ThreadCache thread_cache_;
   static GOOGLE_THREAD_LOCAL ThreadCache thread_cache_;
   static ThreadCache& thread_cache() { return thread_cache_; }
   static ThreadCache& thread_cache() { return thread_cache_; }

+ 6 - 0
src/google/protobuf/compiler/command_line_interface_unittest.cc

@@ -288,6 +288,7 @@ void CommandLineInterfaceTest::Run(const string& command) {
 
 
   if (!disallow_plugins_) {
   if (!disallow_plugins_) {
     cli_.AllowPlugins("prefix-");
     cli_.AllowPlugins("prefix-");
+#ifndef GOOGLE_THIRD_PARTY_PROTOBUF
     const char* possible_paths[] = {
     const char* possible_paths[] = {
       // When building with shared libraries, libtool hides the real executable
       // When building with shared libraries, libtool hides the real executable
       // in .libs and puts a fake wrapper in the current directory.
       // in .libs and puts a fake wrapper in the current directory.
@@ -316,6 +317,11 @@ void CommandLineInterfaceTest::Run(const string& command) {
     }
     }
 
 
     if (plugin_path.empty()) {
     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)
       GOOGLE_LOG(ERROR)
           << "Plugin executable not found.  Plugin tests are likely to fail.";
           << "Plugin executable not found.  Plugin tests are likely to fail.";
     } else {
     } else {

+ 9 - 0
src/google/protobuf/compiler/cpp/cpp_unittest.cc

@@ -1392,6 +1392,12 @@ class OneofTest : public testing::Test {
       case unittest::TestOneof2::kFooString:
       case unittest::TestOneof2::kFooString:
         EXPECT_TRUE(message.has_foo_string());
         EXPECT_TRUE(message.has_foo_string());
         break;
         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:
       case unittest::TestOneof2::kFooBytes:
         EXPECT_TRUE(message.has_foo_bytes());
         EXPECT_TRUE(message.has_foo_bytes());
         break;
         break;
@@ -1404,6 +1410,9 @@ class OneofTest : public testing::Test {
       case unittest::TestOneof2::kFoogroup:
       case unittest::TestOneof2::kFoogroup:
         EXPECT_TRUE(message.has_foogroup());
         EXPECT_TRUE(message.has_foogroup());
         break;
         break;
+      case unittest::TestOneof2::kFooLazyMessage:
+        EXPECT_TRUE(message.has_foo_lazy_message());
+        break;
       case unittest::TestOneof2::FOO_NOT_SET:
       case unittest::TestOneof2::FOO_NOT_SET:
         break;
         break;
     }
     }

+ 4 - 0
src/google/protobuf/descriptor.h

@@ -59,6 +59,10 @@
 #include <vector>
 #include <vector>
 #include <google/protobuf/stubs/common.h>
 #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 google {
 namespace protobuf {
 namespace protobuf {

+ 2 - 2
src/google/protobuf/preserve_unknown_enum_test.cc

@@ -246,8 +246,6 @@ TEST(PreserveUnknownEnumTest, Proto2CatchesUnknownValues) {
   protobuf_unittest::TestAllTypes message;  // proto2 message
   protobuf_unittest::TestAllTypes message;  // proto2 message
   const google::protobuf::Reflection* r = message.GetReflection();
   const google::protobuf::Reflection* r = message.GetReflection();
   const google::protobuf::Descriptor* d = message.GetDescriptor();
   const google::protobuf::Descriptor* d = message.GetDescriptor();
-  const google::protobuf::FieldDescriptor* singular_field =
-      d->FindFieldByName("optional_nested_enum");
   const google::protobuf::FieldDescriptor* repeated_field =
   const google::protobuf::FieldDescriptor* repeated_field =
       d->FindFieldByName("repeated_nested_enum");
       d->FindFieldByName("repeated_nested_enum");
   // Add one element to the repeated field so that we can test
   // Add one element to the repeated field so that we can test
@@ -258,6 +256,8 @@ TEST(PreserveUnknownEnumTest, Proto2CatchesUnknownValues) {
   r->AddEnum(&message, repeated_field, enum_value);
   r->AddEnum(&message, repeated_field, enum_value);
 
 
 #ifdef PROTOBUF_HAS_DEATH_TEST
 #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
   // Enum-field integer-based setters GOOGLE_DCHECK-fail on invalid values, in order to
   // remain consistent with proto2 generated code.
   // remain consistent with proto2 generated code.
   EXPECT_DEBUG_DEATH({
   EXPECT_DEBUG_DEATH({

+ 1 - 1
src/google/protobuf/repeated_field.h

@@ -626,7 +626,7 @@ DEFINE_SPECIALIZATIONS_FOR_BASE_PROTO_TYPES(inline, MessageLite);
 DECLARE_SPECIALIZATIONS_FOR_BASE_PROTO_TYPES(Message);
 DECLARE_SPECIALIZATIONS_FOR_BASE_PROTO_TYPES(Message);
 
 
 
 
-#undef DECLARE_SPECIALIZATIONS_FOR_BASE_CLASSES
+#undef DECLARE_SPECIALIZATIONS_FOR_BASE_PROTO_TYPES
 
 
 template <>
 template <>
 inline const MessageLite& GenericTypeHandler<MessageLite>::default_instance() {
 inline const MessageLite& GenericTypeHandler<MessageLite>::default_instance() {

+ 167 - 9
src/google/protobuf/stubs/atomicops_internals_pnacl.h

@@ -33,39 +33,197 @@
 #ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_PNACL_H_
 #ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_PNACL_H_
 #define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_PNACL_H_
 #define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_PNACL_H_
 
 
+#include <atomic>
+
 namespace google {
 namespace google {
 namespace protobuf {
 namespace protobuf {
 namespace internal {
 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,
 inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
                                          Atomic32 old_value,
                                          Atomic32 old_value,
                                          Atomic32 new_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,
 inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
                                        Atomic32 old_value,
                                        Atomic32 old_value,
                                        Atomic32 new_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();
   MemoryBarrier();
-  return ret;
 }
 }
 
 
 inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
 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) {
 inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
-  Atomic32 value = *ptr;
+  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();
   MemoryBarrier();
-  return value;
 }
 }
 
 
+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 internal
 }  // namespace protobuf
 }  // namespace protobuf
 }  // namespace google
 }  // namespace google

+ 41 - 1
src/google/protobuf/stubs/common.h

@@ -62,6 +62,14 @@
 #include <exception>
 #include <exception>
 #endif
 #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)
 #if defined(_WIN32) && defined(GetMessage)
 // Allow GetMessage to be used as a valid method name in protobuf classes.
 // 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
 // windows.h defines GetMessage() as a macro.  Let's re-define it as an inline
@@ -157,7 +165,7 @@ std::string LIBPROTOBUF_EXPORT VersionString(int version);
 typedef unsigned int uint;
 typedef unsigned int uint;
 
 
 #ifdef _MSC_VER
 #ifdef _MSC_VER
-typedef __int8  int8;
+typedef signed __int8  int8;
 typedef __int16 int16;
 typedef __int16 int16;
 typedef __int32 int32;
 typedef __int32 int32;
 typedef __int64 int64;
 typedef __int64 int64;
@@ -1158,6 +1166,38 @@ class LIBPROTOBUF_EXPORT MutexLockMaybe {
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MutexLockMaybe);
   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
 }  // namespace internal
 
 
 // We made these internal so that they would show up as such in the docs,
 // We made these internal so that they would show up as such in the docs,

+ 9 - 2
src/google/protobuf/stubs/hash.h

@@ -172,6 +172,13 @@ struct hash<const char*> {
   }
   }
 };
 };
 
 
+template<>
+struct hash<bool> {
+  size_t operator()(bool x) const {
+    return static_cast<size_t>(x);
+  }
+};
+
 template <typename Key, typename Data,
 template <typename Key, typename Data,
           typename HashFcn = hash<Key>,
           typename HashFcn = hash<Key>,
           typename EqualKey = std::equal_to<Key>,
           typename EqualKey = std::equal_to<Key>,
@@ -204,7 +211,7 @@ struct hash<string> {
 
 
   static const size_t bucket_size = 4;
   static const size_t bucket_size = 4;
   static const size_t min_buckets = 8;
   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;
     return a < b;
   }
   }
 };
 };
@@ -222,7 +229,7 @@ struct hash<pair<First, Second> > {
 
 
   static const size_t bucket_size = 4;
   static const size_t bucket_size = 4;
   static const size_t min_buckets = 8;
   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 {
                            const pair<First, Second>& b) const {
     return a < b;
     return a < b;
   }
   }

+ 6 - 0
src/google/protobuf/stubs/platform_macros.h

@@ -95,12 +95,18 @@ GOOGLE_PROTOBUF_PLATFORM_ERROR
 
 
 #if defined(__APPLE__)
 #if defined(__APPLE__)
 #define GOOGLE_PROTOBUF_OS_APPLE
 #define GOOGLE_PROTOBUF_OS_APPLE
+#include <TargetConditionals.h>
+#if TARGET_OS_IPHONE
+#define GOOGLE_PROTOBUF_OS_IPHONE
+#endif
 #elif defined(__native_client__)
 #elif defined(__native_client__)
 #define GOOGLE_PROTOBUF_OS_NACL
 #define GOOGLE_PROTOBUF_OS_NACL
 #elif defined(sun)
 #elif defined(sun)
 #define GOOGLE_PROTOBUF_OS_SOLARIS
 #define GOOGLE_PROTOBUF_OS_SOLARIS
 #elif defined(_AIX)
 #elif defined(_AIX)
 #define GOOGLE_PROTOBUF_OS_AIX
 #define GOOGLE_PROTOBUF_OS_AIX
+#elif defined(__ANDROID__)
+#define GOOGLE_PROTOBUF_OS_ANDROID
 #endif
 #endif
 
 
 #undef GOOGLE_PROTOBUF_PLATFORM_ERROR
 #undef GOOGLE_PROTOBUF_PLATFORM_ERROR

+ 4 - 0
src/google/protobuf/stubs/type_traits.h

@@ -73,6 +73,10 @@ struct is_base_of {
   typedef char (&yes)[1];
   typedef char (&yes)[1];
   typedef char (&no)[2];
   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 yes check(const B*);
   static no check(const void*);
   static no check(const void*);
 
 

+ 4 - 0
src/google/protobuf/testing/googletest.cc

@@ -65,6 +65,7 @@ namespace protobuf {
 #endif
 #endif
 
 
 string TestSourceDir() {
 string TestSourceDir() {
+#ifndef GOOGLE_THIRD_PARTY_PROTOBUF
 #ifdef _MSC_VER
 #ifdef _MSC_VER
   // Look for the "src" directory.
   // Look for the "src" directory.
   string prefix = ".";
   string prefix = ".";
@@ -88,6 +89,9 @@ string TestSourceDir() {
     return result;
     return result;
   }
   }
 #endif
 #endif
+#else
+  return "third_party/protobuf/src";
+#endif  // GOOGLE_THIRD_PARTY_PROTOBUF
 }
 }
 
 
 namespace {
 namespace {