Răsfoiți Sursa

Merge branch 'sync-piper' into sync-stage

Joshua Haberman 5 ani în urmă
părinte
comite
1119531bb2

+ 7 - 4
python/google/protobuf/internal/json_format_test.py

@@ -239,16 +239,19 @@ class JsonFormatTest(JsonFormatBase):
     golden_dict = {
         'messageSet': {
             '[protobuf_unittest.'
-            'TestMessageSetExtension1.messageSetExtension]': {
+            'TestMessageSetExtension1.message_set_extension]': {
                 'i': 23,
             },
             '[protobuf_unittest.'
-            'TestMessageSetExtension2.messageSetExtension]': {
+            'TestMessageSetExtension2.message_set_extension]': {
                 'str': u'foo',
             },
         },
     }
     self.assertEqual(golden_dict, message_dict)
+    parsed_msg = unittest_mset_pb2.TestMessageSetContainer()
+    json_format.ParseDict(golden_dict, parsed_msg)
+    self.assertEqual(message, parsed_msg)
 
   def testExtensionSerializationDictMatchesProto3SpecMore(self):
     """See go/proto3-json-spec for spec.
@@ -279,9 +282,9 @@ class JsonFormatTest(JsonFormatBase):
         message
     )
     ext1_text = ('protobuf_unittest.TestMessageSetExtension1.'
-                 'messageSetExtension')
+                 'message_set_extension')
     ext2_text = ('protobuf_unittest.TestMessageSetExtension2.'
-                 'messageSetExtension')
+                 'message_set_extension')
     golden_text = ('{"messageSet": {'
                    '    "[%s]": {'
                    '        "i": 23'

+ 1 - 2
python/google/protobuf/json_format.py

@@ -246,8 +246,7 @@ class _Printer(object):
           js[name] = [self._FieldToJsonObject(field, k)
                       for k in value]
         elif field.is_extension:
-          full_qualifier = field.full_name[:-len(field.name)]
-          name = '[%s%s]' % (full_qualifier, name)
+          name = '[%s]' % field.full_name
           js[name] = self._FieldToJsonObject(field, value)
         else:
           js[name] = self._FieldToJsonObject(field, value)

+ 3 - 2
src/google/protobuf/arena.cc

@@ -59,11 +59,12 @@ ArenaImpl::ThreadCache& ArenaImpl::thread_cache() {
 }
 #elif defined(PROTOBUF_USE_DLLS)
 ArenaImpl::ThreadCache& ArenaImpl::thread_cache() {
-  static GOOGLE_THREAD_LOCAL ThreadCache thread_cache_ = {-1, NULL};
+  static PROTOBUF_THREAD_LOCAL ThreadCache thread_cache_ = {-1, NULL};
   return thread_cache_;
 }
 #else
-GOOGLE_THREAD_LOCAL ArenaImpl::ThreadCache ArenaImpl::thread_cache_ = {-1, NULL};
+PROTOBUF_THREAD_LOCAL ArenaImpl::ThreadCache ArenaImpl::thread_cache_ = {-1,
+                                                                         NULL};
 #endif
 
 void ArenaImpl::Init() {

+ 3 - 3
src/google/protobuf/arena_impl.h

@@ -288,16 +288,16 @@ class PROTOBUF_EXPORT ArenaImpl {
   };
   static std::atomic<LifecycleId> lifecycle_id_generator_;
 #if defined(GOOGLE_PROTOBUF_NO_THREADLOCAL)
-  // Android ndk does not support GOOGLE_THREAD_LOCAL keyword so we use a custom thread
+  // Android ndk does not support __thread keyword so we use a custom thread
   // local storage class we implemented.
-  // iOS also does not support the GOOGLE_THREAD_LOCAL keyword.
+  // iOS also does not support the __thread keyword.
   static ThreadCache& thread_cache();
 #elif defined(PROTOBUF_USE_DLLS)
   // Thread local variables cannot be exposed through DLL interface but we can
   // wrap them in static functions.
   static ThreadCache& thread_cache();
 #else
-  static GOOGLE_THREAD_LOCAL ThreadCache thread_cache_;
+  static PROTOBUF_THREAD_LOCAL ThreadCache thread_cache_;
   static ThreadCache& thread_cache() { return thread_cache_; }
 #endif
 

+ 4 - 9
src/google/protobuf/compiler/cpp/cpp_string_field.cc

@@ -754,6 +754,10 @@ void StringOneofFieldGenerator::GenerateInlineAccessorDefinitions(
         "  if ($name$ != nullptr) {\n"
         "    set_has_$name$();\n"
         "    $field_member$.UnsafeSetDefault($name$);\n"
+        "    ::$proto_ns$::Arena* arena = GetArena();\n"
+        "    if (arena != nullptr) {\n"
+        "      arena->Own($name$);\n"
+        "    }\n"
         "  }\n"
         "  // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
         "}\n");
@@ -917,15 +921,6 @@ void StringOneofFieldGenerator::GenerateConstructorCode(
       "    $default_variable$);\n");
 }
 
-void StringOneofFieldGenerator::GenerateDestructorCode(
-    io::Printer* printer) const {
-  Formatter format(printer, variables_);
-  format(
-      "if (_internal_has_$name$()) {\n"
-      "  $field_member$.DestroyNoArena($default_variable$);\n"
-      "}\n");
-}
-
 // ===================================================================
 
 RepeatedStringFieldGenerator::RepeatedStringFieldGenerator(

+ 0 - 1
src/google/protobuf/compiler/cpp/cpp_string_field.h

@@ -95,7 +95,6 @@ class StringOneofFieldGenerator : public StringFieldGenerator {
   void GenerateMessageClearingCode(io::Printer* printer) const;
   void GenerateSwappingCode(io::Printer* printer) const;
   void GenerateConstructorCode(io::Printer* printer) const;
-  void GenerateDestructorCode(io::Printer* printer) const;
 
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringOneofFieldGenerator);

+ 20 - 0
src/google/protobuf/compiler/cpp/cpp_unittest.inc

@@ -1683,6 +1683,26 @@ TEST_F(OneofTest, SetAllocatedString) {
   EXPECT_EQ(kHello, message.foo_string());
 }
 
+TEST_F(OneofTest, ArenaSetAllocatedString) {
+  // Check that set_allocated_foo() works for strings.
+  Arena arena;
+  UNITTEST::TestOneof2* message =
+      Arena::CreateMessage<UNITTEST::TestOneof2>(&arena);
+
+  EXPECT_FALSE(message->has_foo_string());
+  const std::string kHello("hello");
+  message->set_foo_string(kHello);
+  EXPECT_TRUE(message->has_foo_string());
+
+  message->set_allocated_foo_string(NULL);
+  EXPECT_FALSE(message->has_foo_string());
+  EXPECT_EQ("", message->foo_string());
+
+  message->set_allocated_foo_string(new std::string(kHello));
+  EXPECT_TRUE(message->has_foo_string());
+  EXPECT_EQ(kHello, message->foo_string());
+}
+
 
 TEST_F(OneofTest, SetMessage) {
   // Check that setting a message field works

+ 1 - 1
src/google/protobuf/descriptor.cc

@@ -3522,7 +3522,7 @@ class DescriptorBuilder {
     return pool->enforce_weak_;
   }
   static inline bool get_is_placeholder(const Descriptor* descriptor) {
-    return descriptor->is_placeholder_;
+    return descriptor != nullptr && descriptor->is_placeholder_;
   }
   static inline void assert_mutex_held(const DescriptorPool* pool) {
     if (pool->mutex_ != nullptr) {

+ 5 - 7
src/google/protobuf/descriptor_unittest.cc

@@ -2592,11 +2592,9 @@ TEST_F(MiscTest, DefaultValues) {
   ASSERT_TRUE(message->field(10)->has_default_value());
 
   EXPECT_EQ(-1, message->field(0)->default_value_int32());
-  EXPECT_EQ(-PROTOBUF_ULONGLONG(1000000000000),
-            message->field(1)->default_value_int64());
+  EXPECT_EQ(int64{-1000000000000}, message->field(1)->default_value_int64());
   EXPECT_EQ(42, message->field(2)->default_value_uint32());
-  EXPECT_EQ(PROTOBUF_ULONGLONG(2000000000000),
-            message->field(3)->default_value_uint64());
+  EXPECT_EQ(uint64{2000000000000}, message->field(3)->default_value_uint64());
   EXPECT_EQ(4.5, message->field(4)->default_value_float());
   EXPECT_EQ(10e100, message->field(5)->default_value_double());
   EXPECT_TRUE(message->field(6)->default_value_bool());
@@ -3009,11 +3007,11 @@ TEST(CustomOptions, OptionLocations) {
       file->FindServiceByName("TestServiceWithCustomOptions");
   const MethodDescriptor* method = service->FindMethodByName("Foo");
 
-  EXPECT_EQ(PROTOBUF_LONGLONG(9876543210),
+  EXPECT_EQ(int64{9876543210},
             file->options().GetExtension(protobuf_unittest::file_opt1));
   EXPECT_EQ(-56,
             message->options().GetExtension(protobuf_unittest::message_opt1));
-  EXPECT_EQ(PROTOBUF_LONGLONG(8765432109),
+  EXPECT_EQ(int64{8765432109},
             field->options().GetExtension(protobuf_unittest::field_opt1));
   EXPECT_EQ(42,  // Check that we get the default for an option we don't set.
             field->options().GetExtension(protobuf_unittest::field_opt2));
@@ -3021,7 +3019,7 @@ TEST(CustomOptions, OptionLocations) {
   EXPECT_EQ(-789, enm->options().GetExtension(protobuf_unittest::enum_opt1));
   EXPECT_EQ(123, enm->value(1)->options().GetExtension(
                      protobuf_unittest::enum_value_opt1));
-  EXPECT_EQ(PROTOBUF_LONGLONG(-9876543210),
+  EXPECT_EQ(int64{-9876543210},
             service->options().GetExtension(protobuf_unittest::service_opt1));
   EXPECT_EQ(protobuf_unittest::METHODOPT1_VAL2,
             method->options().GetExtension(protobuf_unittest::method_opt1));

+ 2 - 1
src/google/protobuf/map.h

@@ -37,6 +37,7 @@
 #ifndef GOOGLE_PROTOBUF_MAP_H__
 #define GOOGLE_PROTOBUF_MAP_H__
 
+#include <functional>
 #include <initializer_list>
 #include <iterator>
 #include <limits>  // To support Visual Studio 2008
@@ -268,7 +269,7 @@ class Map {
   using const_reference = const value_type&;
 
   using size_type = size_t;
-  using hasher = hash<Key>;
+  using hasher = std::hash<Key>;
 
   Map() : arena_(nullptr), default_enum_value_(0) { Init(); }
   explicit Map(Arena* arena) : arena_(arena), default_enum_value_(0) { Init(); }

+ 21 - 12
src/google/protobuf/map_field.h

@@ -32,6 +32,7 @@
 #define GOOGLE_PROTOBUF_MAP_FIELD_H__
 
 #include <atomic>
+#include <functional>
 
 #include <google/protobuf/arena.h>
 #include <google/protobuf/descriptor.h>
@@ -796,7 +797,7 @@ class PROTOBUF_EXPORT MapIterator {
 }  // namespace protobuf
 }  // namespace google
 
-GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_START
+namespace std {
 template <>
 struct hash<::PROTOBUF_NAMESPACE_ID::MapKey> {
   size_t operator()(const ::PROTOBUF_NAMESPACE_ID::MapKey& map_key) const {
@@ -809,16 +810,25 @@ struct hash<::PROTOBUF_NAMESPACE_ID::MapKey> {
         break;
       case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_STRING:
         return hash<std::string>()(map_key.GetStringValue());
-      case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_INT64:
-        return hash<int64>()(map_key.GetInt64Value());
-      case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_INT32:
-        return hash<int32>()(map_key.GetInt32Value());
-      case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_UINT64:
-        return hash<uint64>()(map_key.GetUInt64Value());
-      case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_UINT32:
-        return hash<uint32>()(map_key.GetUInt32Value());
-      case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_BOOL:
+      case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_INT64: {
+        auto value = map_key.GetInt64Value();
+        return hash<decltype(value)>()(value);
+      }
+      case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_INT32: {
+        auto value = map_key.GetInt32Value();
+        return hash<decltype(value)>()(map_key.GetInt32Value());
+      }
+      case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_UINT64: {
+        auto value = map_key.GetUInt64Value();
+        return hash<decltype(value)>()(map_key.GetUInt64Value());
+      }
+      case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_UINT32: {
+        auto value = map_key.GetUInt32Value();
+        return hash<decltype(value)>()(map_key.GetUInt32Value());
+      }
+      case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_BOOL: {
         return hash<bool>()(map_key.GetBoolValue());
+      }
     }
     GOOGLE_LOG(FATAL) << "Can't get here.";
     return 0;
@@ -828,8 +838,7 @@ struct hash<::PROTOBUF_NAMESPACE_ID::MapKey> {
     return map_key1 < map_key2;
   }
 };
-GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_END
-
+}  // namespace std
 #include <google/protobuf/port_undef.inc>
 
 #endif  // GOOGLE_PROTOBUF_MAP_FIELD_H__

+ 4 - 2
src/google/protobuf/message.h

@@ -1011,8 +1011,10 @@ class PROTOBUF_EXPORT Reflection final {
                              const OneofDescriptor* oneof_descriptor) const;
   inline uint32* MutableOneofCase(
       Message* message, const OneofDescriptor* oneof_descriptor) const;
-  inline const internal::ExtensionSet& GetExtensionSet(
-      const Message& message) const;
+  inline bool HasExtensionSet(const Message& message) const {
+    return schema_.HasExtensionSet();
+  }
+  const internal::ExtensionSet& GetExtensionSet(const Message& message) const;
   internal::ExtensionSet* MutableExtensionSet(Message* message) const;
   inline Arena* GetArena(Message* message) const;
 

+ 6 - 0
src/google/protobuf/port_def.inc

@@ -634,3 +634,9 @@ PROTOBUF_EXPORT_TEMPLATE_TEST(DEFAULT, __declspec(dllimport));
 #endif
 
 #define PROTOBUF_FINAL final
+
+#if defined(_MSC_VER)
+#define PROTOBUF_THREAD_LOCAL __declspec(thread)
+#else
+#define PROTOBUF_THREAD_LOCAL __thread
+#endif

+ 1 - 0
src/google/protobuf/port_undef.inc

@@ -83,6 +83,7 @@
 #undef PROTOBUF_EXPORT_TEMPLATE_STYLE_MATCH_DECLSPEC_dllexport
 #undef PROTOBUF_EXPORT_TEMPLATE_STYLE_MATCH_DECLSPEC_dllimport
 #undef PROTOBUF_FINAL
+#undef PROTOBUF_THREAD_LOCAL
 
 // Restore macro that may have been #undef'd in port_def.inc.
 #ifdef _MSC_VER

+ 62 - 0
src/google/protobuf/reflection_ops.cc

@@ -188,6 +188,68 @@ void ReflectionOps::Clear(Message* message) {
   reflection->MutableUnknownFields(message)->Clear();
 }
 
+bool ReflectionOps::IsInitialized(const Message& message, bool check_fields,
+                                  bool check_descendants) {
+  const Descriptor* descriptor = message.GetDescriptor();
+  const Reflection* reflection = GetReflectionOrDie(message);
+  if (const int field_count = descriptor->field_count()) {
+    const FieldDescriptor* begin = descriptor->field(0);
+    const FieldDescriptor* end = begin + field_count;
+    GOOGLE_DCHECK_EQ(descriptor->field(field_count - 1), end - 1);
+
+    if (check_fields) {
+      // Check required fields of this message.
+      for (const FieldDescriptor* field = begin; field != end; ++field) {
+        if (field->is_required() && !reflection->HasField(message, field)) {
+          return false;
+        }
+      }
+    }
+
+    if (check_descendants) {
+      for (const FieldDescriptor* field = begin; field != end; ++field) {
+        if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+          const Descriptor* message_type = field->message_type();
+          if (PROTOBUF_PREDICT_FALSE(message_type->options().map_entry())) {
+            if (message_type->field(1)->cpp_type() ==
+                FieldDescriptor::CPPTYPE_MESSAGE) {
+              const MapFieldBase* map_field =
+                  reflection->GetMapData(message, field);
+              if (map_field->IsMapValid()) {
+                MapIterator it(const_cast<Message*>(&message), field);
+                MapIterator end(const_cast<Message*>(&message), field);
+                for (map_field->MapBegin(&it), map_field->MapEnd(&end);
+                     it != end; ++it) {
+                  if (!it.GetValueRef().GetMessageValue().IsInitialized()) {
+                    return false;
+                  }
+                }
+              }
+            }
+          } else if (field->is_repeated()) {
+            const int size = reflection->FieldSize(message, field);
+            for (int j = 0; j < size; j++) {
+              if (!reflection->GetRepeatedMessage(message, field, j)
+                       .IsInitialized()) {
+                return false;
+              }
+            }
+          } else if (reflection->HasField(message, field)) {
+            if (!reflection->GetMessage(message, field).IsInitialized()) {
+              return false;
+            }
+          }
+        }
+      }
+    }
+  }
+  if (check_descendants && reflection->HasExtensionSet(message) &&
+      !reflection->GetExtensionSet(message).IsInitialized()) {
+    return false;
+  }
+  return true;
+}
+
 bool ReflectionOps::IsInitialized(const Message& message) {
   const Descriptor* descriptor = message.GetDescriptor();
   const Reflection* reflection = GetReflectionOrDie(message);

+ 2 - 0
src/google/protobuf/reflection_ops.h

@@ -66,6 +66,8 @@ class PROTOBUF_EXPORT ReflectionOps {
   static void Merge(const Message& from, Message* to);
   static void Clear(Message* message);
   static bool IsInitialized(const Message& message);
+  static bool IsInitialized(const Message& message, bool check_fields,
+                            bool check_descendants);
   static void DiscardUnknownFields(Message* message);
 
   // Finds all unset required fields in the message and adds their full

+ 37 - 0
src/google/protobuf/reflection_ops_unittest.cc

@@ -340,12 +340,20 @@ TEST(ReflectionOpsTest, IsInitialized) {
   unittest::TestRequired message;
 
   EXPECT_FALSE(ReflectionOps::IsInitialized(message));
+  EXPECT_FALSE(ReflectionOps::IsInitialized(message, true, false));
+  EXPECT_TRUE(ReflectionOps::IsInitialized(message, false, true));
   message.set_a(1);
   EXPECT_FALSE(ReflectionOps::IsInitialized(message));
+  EXPECT_FALSE(ReflectionOps::IsInitialized(message, true, true));
+  EXPECT_TRUE(ReflectionOps::IsInitialized(message, false, true));
   message.set_b(2);
   EXPECT_FALSE(ReflectionOps::IsInitialized(message));
+  EXPECT_FALSE(ReflectionOps::IsInitialized(message, true, true));
+  EXPECT_TRUE(ReflectionOps::IsInitialized(message, false, true));
   message.set_c(3);
   EXPECT_TRUE(ReflectionOps::IsInitialized(message));
+  EXPECT_TRUE(ReflectionOps::IsInitialized(message, true, false));
+  EXPECT_TRUE(ReflectionOps::IsInitialized(message, false, true));
 }
 
 TEST(ReflectionOpsTest, ForeignIsInitialized) {
@@ -354,26 +362,35 @@ TEST(ReflectionOpsTest, ForeignIsInitialized) {
   // Starts out initialized because the foreign message is itself an optional
   // field.
   EXPECT_TRUE(ReflectionOps::IsInitialized(message));
+  EXPECT_TRUE(ReflectionOps::IsInitialized(message, false, true));
 
   // Once we create that field, the message is no longer initialized.
   message.mutable_optional_message();
   EXPECT_FALSE(ReflectionOps::IsInitialized(message));
+  EXPECT_TRUE(ReflectionOps::IsInitialized(message, true, false));
+  EXPECT_FALSE(ReflectionOps::IsInitialized(message, false, true));
 
   // Initialize it.  Now we're initialized.
   message.mutable_optional_message()->set_a(1);
   message.mutable_optional_message()->set_b(2);
   message.mutable_optional_message()->set_c(3);
   EXPECT_TRUE(ReflectionOps::IsInitialized(message));
+  EXPECT_TRUE(ReflectionOps::IsInitialized(message, true, false));
+  EXPECT_TRUE(ReflectionOps::IsInitialized(message, false, true));
 
   // Add a repeated version of the message.  No longer initialized.
   unittest::TestRequired* sub_message = message.add_repeated_message();
   EXPECT_FALSE(ReflectionOps::IsInitialized(message));
+  EXPECT_TRUE(ReflectionOps::IsInitialized(message, true, false));
+  EXPECT_FALSE(ReflectionOps::IsInitialized(message, false, true));
 
   // Initialize that repeated version.
   sub_message->set_a(1);
   sub_message->set_b(2);
   sub_message->set_c(3);
   EXPECT_TRUE(ReflectionOps::IsInitialized(message));
+  EXPECT_TRUE(ReflectionOps::IsInitialized(message, true, false));
+  EXPECT_TRUE(ReflectionOps::IsInitialized(message, false, true));
 }
 
 TEST(ReflectionOpsTest, ExtensionIsInitialized) {
@@ -382,42 +399,62 @@ TEST(ReflectionOpsTest, ExtensionIsInitialized) {
   // Starts out initialized because the foreign message is itself an optional
   // field.
   EXPECT_TRUE(ReflectionOps::IsInitialized(message));
+  EXPECT_TRUE(ReflectionOps::IsInitialized(message, true, false));
+  EXPECT_TRUE(ReflectionOps::IsInitialized(message, false, true));
 
   // Once we create that field, the message is no longer initialized.
   message.MutableExtension(unittest::TestRequired::single);
   EXPECT_FALSE(ReflectionOps::IsInitialized(message));
+  EXPECT_TRUE(ReflectionOps::IsInitialized(message, true, false));
+  EXPECT_FALSE(ReflectionOps::IsInitialized(message, false, true));
 
   // Initialize it.  Now we're initialized.
   message.MutableExtension(unittest::TestRequired::single)->set_a(1);
   message.MutableExtension(unittest::TestRequired::single)->set_b(2);
   message.MutableExtension(unittest::TestRequired::single)->set_c(3);
   EXPECT_TRUE(ReflectionOps::IsInitialized(message));
+  EXPECT_TRUE(ReflectionOps::IsInitialized(message, true, false));
+  EXPECT_TRUE(ReflectionOps::IsInitialized(message, false, true));
 
   // Add a repeated version of the message.  No longer initialized.
   message.AddExtension(unittest::TestRequired::multi);
   EXPECT_FALSE(ReflectionOps::IsInitialized(message));
+  EXPECT_TRUE(ReflectionOps::IsInitialized(message, true, false));
+  EXPECT_FALSE(ReflectionOps::IsInitialized(message, false, true));
 
   // Initialize that repeated version.
   message.MutableExtension(unittest::TestRequired::multi, 0)->set_a(1);
   message.MutableExtension(unittest::TestRequired::multi, 0)->set_b(2);
   message.MutableExtension(unittest::TestRequired::multi, 0)->set_c(3);
   EXPECT_TRUE(ReflectionOps::IsInitialized(message));
+  EXPECT_TRUE(ReflectionOps::IsInitialized(message, true, false));
+  EXPECT_TRUE(ReflectionOps::IsInitialized(message, false, true));
 }
 
 TEST(ReflectionOpsTest, OneofIsInitialized) {
   unittest::TestRequiredOneof message;
   EXPECT_TRUE(ReflectionOps::IsInitialized(message));
+  EXPECT_TRUE(ReflectionOps::IsInitialized(message, true, false));
+  EXPECT_TRUE(ReflectionOps::IsInitialized(message, false, true));
 
   message.mutable_foo_message();
   EXPECT_FALSE(ReflectionOps::IsInitialized(message));
+  EXPECT_TRUE(ReflectionOps::IsInitialized(message, true, false));
+  EXPECT_FALSE(ReflectionOps::IsInitialized(message, false, true));
 
   message.set_foo_int(1);
   EXPECT_TRUE(ReflectionOps::IsInitialized(message));
+  EXPECT_TRUE(ReflectionOps::IsInitialized(message, true, false));
+  EXPECT_TRUE(ReflectionOps::IsInitialized(message, false, true));
 
   message.mutable_foo_message();
   EXPECT_FALSE(ReflectionOps::IsInitialized(message));
+  EXPECT_TRUE(ReflectionOps::IsInitialized(message, true, false));
+  EXPECT_FALSE(ReflectionOps::IsInitialized(message, false, true));
   message.mutable_foo_message()->set_required_double(0.1);
   EXPECT_TRUE(ReflectionOps::IsInitialized(message));
+  EXPECT_TRUE(ReflectionOps::IsInitialized(message, true, false));
+  EXPECT_TRUE(ReflectionOps::IsInitialized(message, false, true));
 }
 
 static std::string FindInitializationErrors(const Message& message) {

+ 4 - 0
src/google/protobuf/struct.pb.h

@@ -911,6 +911,10 @@ inline void Value::set_allocated_string_value(std::string* string_value) {
   if (string_value != nullptr) {
     set_has_string_value();
     kind_.string_value_.UnsafeSetDefault(string_value);
+    ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena();
+    if (arena != nullptr) {
+      arena->Own(string_value);
+    }
   }
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.Value.string_value)
 }

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

@@ -225,12 +225,6 @@ inline void GOOGLE_UNALIGNED_STORE64(void *p, uint64 v) {
 # define GOOGLE_PROTOBUF_USE_PORTABLE_LOG2
 #endif
 
-#if defined(_MSC_VER)
-#define GOOGLE_THREAD_LOCAL __declspec(thread)
-#else
-#define GOOGLE_THREAD_LOCAL __thread
-#endif
-
 // The following guarantees declaration of the byte swap functions.
 #ifdef _MSC_VER
 #define bswap_16(x) _byteswap_ushort(x)

+ 16 - 1
src/google/protobuf/text_format.cc

@@ -258,6 +258,7 @@ class TextFormat::Parser::ParserImpl {
         allow_unknown_enum_(allow_unknown_enum),
         allow_field_number_(allow_field_number),
         allow_partial_(allow_partial),
+        initial_recursion_limit_(recursion_limit),
         recursion_limit_(recursion_limit),
         had_errors_(false) {
     // For backwards-compatibility with proto1, we need to allow the 'f' suffix
@@ -636,7 +637,10 @@ class TextFormat::Parser::ParserImpl {
   bool ConsumeFieldMessage(Message* message, const Reflection* reflection,
                            const FieldDescriptor* field) {
     if (--recursion_limit_ < 0) {
-      ReportError("Message is too deep");
+      ReportError(
+          StrCat("Message is too deep, the parser exceeded the "
+                       "configured recursion limit of ",
+                       initial_recursion_limit_, "."));
       return false;
     }
     // If the parse information tree is not nullptr, create a nested one
@@ -668,12 +672,22 @@ class TextFormat::Parser::ParserImpl {
   // Skips the whole body of a message including the beginning delimiter and
   // the ending delimiter.
   bool SkipFieldMessage() {
+    if (--recursion_limit_ < 0) {
+      ReportError(
+          StrCat("Message is too deep, the parser exceeded the "
+                       "configured recursion limit of ",
+                       initial_recursion_limit_, "."));
+      return false;
+    }
+
     std::string delimiter;
     DO(ConsumeMessageDelimiter(&delimiter));
     while (!LookingAt(">") && !LookingAt("}")) {
       DO(SkipField());
     }
     DO(Consume(delimiter));
+
+    ++recursion_limit_;
     return true;
   }
 
@@ -1192,6 +1206,7 @@ class TextFormat::Parser::ParserImpl {
   const bool allow_unknown_enum_;
   const bool allow_field_number_;
   const bool allow_partial_;
+  const int initial_recursion_limit_;
   int recursion_limit_;
   bool had_errors_;
 };

+ 28 - 2
src/google/protobuf/text_format_unittest.cc

@@ -55,9 +55,9 @@
 #include <google/protobuf/io/tokenizer.h>
 #include <google/protobuf/io/zero_copy_stream_impl.h>
 #include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/stubs/substitute.h>
 #include <google/protobuf/testing/googletest.h>
 #include <gtest/gtest.h>
+#include <google/protobuf/stubs/substitute.h>
 
 
 #include <google/protobuf/port_def.inc>
@@ -1911,7 +1911,33 @@ TEST_F(TextFormatParserTest, SetRecursionLimit) {
 
   input = strings::Substitute(format, input);
   parser_.SetRecursionLimit(100);
-  ExpectMessage(input, "Message is too deep", 1, 908, &message, false);
+  ExpectMessage(input,
+                "Message is too deep, the parser exceeded the configured "
+                "recursion limit of 100.",
+                1, 908, &message, false);
+
+  parser_.SetRecursionLimit(101);
+  ExpectSuccessAndTree(input, &message, nullptr);
+}
+
+TEST_F(TextFormatParserTest, SetRecursionLimitUnknownField) {
+  const char* format = "unknown_child: { $0 }";
+  std::string input;
+  for (int i = 0; i < 100; ++i) input = strings::Substitute(format, input);
+
+  parser_.AllowUnknownField(true);
+
+  unittest::NestedTestAllTypes message;
+  ExpectSuccessAndTree(input, &message, nullptr);
+
+  input = strings::Substitute(format, input);
+  parser_.SetRecursionLimit(100);
+  ExpectMessage(
+      input,
+      "WARNING:Message type \"protobuf_unittest.NestedTestAllTypes\" has no "
+      "field named \"unknown_child\".\n1:1716: Message is too deep, the parser "
+      "exceeded the configured recursion limit of 100.",
+      1, 14, &message, false);
 
   parser_.SetRecursionLimit(101);
   ExpectSuccessAndTree(input, &message, nullptr);

+ 1 - 1
src/google/protobuf/util/internal/default_value_objectwriter.h

@@ -201,7 +201,7 @@ class PROTOBUF_EXPORT DefaultValueObjectWriter : public ObjectWriter {
     // Returns the Value Type of a map given the Type of the map entry and a
     // TypeInfo instance.
     const google::protobuf::Type* GetMapValueType(
-        const google::protobuf::Type& entry_type, const TypeInfo* typeinfo);
+        const google::protobuf::Type& found_type, const TypeInfo* typeinfo);
 
     // Calls WriteTo() on every child in children_.
     void WriteChildren(ObjectWriter* ow);

+ 1 - 1
src/google/protobuf/util/internal/json_stream_parser.h

@@ -130,7 +130,7 @@ class PROTOBUF_EXPORT JsonStreamParser {
   };
 
   // Parses a single chunk of JSON, returning an error if the JSON was invalid.
-  util::Status ParseChunk(StringPiece json);
+  util::Status ParseChunk(StringPiece chunk);
 
   // Runs the parser based on stack_ and p_, until the stack is empty or p_ runs
   // out of data. If we unexpectedly run out of p_ we push the latest back onto

+ 4 - 4
src/google/protobuf/util/internal/json_stream_parser_test.cc

@@ -235,7 +235,7 @@ TEST_F(JsonStreamParserTest, SimpleInt) {
 TEST_F(JsonStreamParserTest, SimpleNegativeInt) {
   StringPiece str = "-79497823553162765";
   for (int i = 0; i <= str.length(); ++i) {
-    ow_.RenderInt64("", -79497823553162765LL);
+    ow_.RenderInt64("", int64{-79497823553162765});
     DoTest(str, i);
   }
 }
@@ -243,7 +243,7 @@ TEST_F(JsonStreamParserTest, SimpleNegativeInt) {
 TEST_F(JsonStreamParserTest, SimpleUnsignedInt) {
   StringPiece str = "11779497823553162765";
   for (int i = 0; i <= str.length(); ++i) {
-    ow_.RenderUint64("", 11779497823553162765ULL);
+    ow_.RenderUint64("", uint64{11779497823553162765u});
     DoTest(str, i);
   }
 }
@@ -378,7 +378,7 @@ TEST_F(JsonStreamParserTest, ArrayComplexValues) {
         ->RenderInt64("", -127)
         ->RenderDouble("", 45.3)
         ->RenderDouble("", -1056.4)
-        ->RenderUint64("", 11779497823553162765ULL)
+        ->RenderUint64("", uint64{11779497823553162765u})
         ->EndList()
         ->StartObject("")
         ->RenderBool("key", true)
@@ -406,7 +406,7 @@ TEST_F(JsonStreamParserTest, ObjectValues) {
         ->RenderInt64("ni", -127)
         ->RenderDouble("pd", 45.3)
         ->RenderDouble("nd", -1056.4)
-        ->RenderUint64("pl", 11779497823553162765ULL)
+        ->RenderUint64("pl", uint64{11779497823553162765u})
         ->StartList("l")
         ->StartList("")
         ->EndList()

+ 1 - 1
src/google/protobuf/util/internal/protostream_objectsource.h

@@ -131,7 +131,7 @@ class PROTOBUF_EXPORT ProtoStreamObjectSource : public ObjectSource {
   // nested messages (end with 0) and nested groups (end with group end tag).
   // The include_start_and_end parameter allows this method to be called when
   // already inside of an object, and skip calling StartObject and EndObject.
-  virtual util::Status WriteMessage(const google::protobuf::Type& descriptor,
+  virtual util::Status WriteMessage(const google::protobuf::Type& type,
                                       StringPiece name,
                                       const uint32 end_tag,
                                       bool include_start_and_end,

+ 7 - 7
src/google/protobuf/util/internal/protostream_objectsource_test.cc

@@ -152,13 +152,13 @@ class ProtostreamObjectSourceTest
         ->RenderInt32("", 3208)
         ->EndList()
         ->StartList("repFix64")
-        ->RenderUint64("", bit_cast<uint64>(6401LL))
-        ->RenderUint64("", bit_cast<uint64>(0LL))
+        ->RenderUint64("", bit_cast<uint64>(int64{6401}))
+        ->RenderUint64("", bit_cast<uint64>(int64{0}))
         ->EndList()
         ->StartList("repU64")
-        ->RenderUint64("", bit_cast<uint64>(0LL))
-        ->RenderUint64("", bit_cast<uint64>(6402LL))
-        ->RenderUint64("", bit_cast<uint64>(6403LL))
+        ->RenderUint64("", bit_cast<uint64>(int64{0}))
+        ->RenderUint64("", bit_cast<uint64>(int64{6402}))
+        ->RenderUint64("", bit_cast<uint64>(int64{6403}))
         ->EndList()
         ->StartList("repI64")
         ->RenderInt64("", 6404L)
@@ -325,8 +325,8 @@ TEST_P(ProtostreamObjectSourceTest, Primitives) {
       ->RenderInt32("i32", 3203)
       ->RenderInt32("sf32", 3204)
       ->RenderInt32("s32", 3205)
-      ->RenderUint64("fix64", bit_cast<uint64>(6401LL))
-      ->RenderUint64("u64", bit_cast<uint64>(6402LL))
+      ->RenderUint64("fix64", bit_cast<uint64>(int64{6401}))
+      ->RenderUint64("u64", bit_cast<uint64>(int64{6402}))
       ->RenderInt64("i64", 6403L)
       ->RenderInt64("sf64", 6404L)
       ->RenderInt64("s64", 6405L)