Sfoglia il codice sorgente

Down integrate to GitHub

Rafi Kamal 6 anni fa
parent
commit
4f02f056b5
100 ha cambiato i file con 2722 aggiunte e 3118 eliminazioni
  1. 154 182
      conformance/binary_json_conformance_suite.cc
  2. 0 26
      conformance/conformance_cpp.cc
  3. 2 2
      conformance/conformance_objc.m
  4. 8 11
      conformance/conformance_test.cc
  5. 16 10
      conformance/conformance_test.h
  6. 15 8
      conformance/conformance_test_runner.cc
  7. BIN
      csharp/src/Google.Protobuf.Test/testprotos.pb
  8. 9 0
      java/core/src/main/java/com/google/protobuf/AbstractMessageLite.java
  9. 10 0
      java/core/src/main/java/com/google/protobuf/GeneratedMessageV3.java
  10. 318 0
      java/core/src/main/java/com/google/protobuf/UnsafeUtil.java
  11. 2 2
      java/util/src/main/java/com/google/protobuf/util/FieldMaskUtil.java
  12. 10 2
      java/util/src/test/java/com/google/protobuf/util/FieldMaskTreeTest.java
  13. 44 163
      js/binary/decoder.js
  14. 89 0
      js/binary/decoder_test.js
  15. 18 4
      js/binary/encoder.js
  16. 35 1
      js/binary/reader.js
  17. 10 0
      js/binary/reader_test.js
  18. 53 14
      js/binary/utils.js
  19. 47 0
      js/binary/utils_test.js
  20. 119 11
      js/binary/writer.js
  21. 120 2
      js/binary/writer_test.js
  22. 3 3
      js/compatibility_tests/v3.0.0/binary/proto_test.js
  23. 3 3
      js/compatibility_tests/v3.0.0/binary/utils_test.js
  24. 3 2
      js/compatibility_tests/v3.0.0/message_test.js
  25. 1 1
      js/compatibility_tests/v3.0.0/proto3_test.js
  26. 3 3
      js/compatibility_tests/v3.1.0/binary/proto_test.js
  27. 3 3
      js/compatibility_tests/v3.1.0/binary/utils_test.js
  28. 3 2
      js/compatibility_tests/v3.1.0/message_test.js
  29. 1 1
      js/compatibility_tests/v3.1.0/proto3_test.js
  30. 16 6
      js/map.js
  31. 78 2
      js/maps_test.js
  32. 0 10
      js/message.js
  33. 5 5
      js/package.json
  34. 50 0
      js/testbinary.proto
  35. 49 0
      python/google/protobuf/descriptor_pool.py
  36. 21 1
      python/google/protobuf/internal/decoder.py
  37. 2 1
      python/google/protobuf/internal/descriptor_test.py
  38. 3 0
      python/google/protobuf/internal/extension_dict.py
  39. 2 3
      python/google/protobuf/internal/python_message.py
  40. 39 0
      python/google/protobuf/internal/reflection_test.py
  41. 11 10
      python/google/protobuf/internal/text_format_test.py
  42. 24 1
      python/google/protobuf/internal/unknown_fields_test.py
  43. 4 0
      python/google/protobuf/pyext/extension_dict.cc
  44. 68 59
      python/google/protobuf/pyext/message.cc
  45. 6 15
      python/google/protobuf/pyext/message.h
  46. 13 4
      python/google/protobuf/symbol_database.py
  47. 5 2
      python/google/protobuf/text_format.py
  48. 0 58
      src/google/protobuf/any.pb.cc
  49. 0 5
      src/google/protobuf/any.pb.h
  50. 35 345
      src/google/protobuf/api.pb.cc
  51. 142 40
      src/google/protobuf/api.pb.h
  52. 1 1
      src/google/protobuf/arena.h
  53. 21 13
      src/google/protobuf/compiler/command_line_interface.cc
  54. 74 1
      src/google/protobuf/compiler/command_line_interface_unittest.cc
  55. 10 11
      src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc
  56. 61 57
      src/google/protobuf/compiler/cpp/cpp_enum_field.cc
  57. 0 1
      src/google/protobuf/compiler/cpp/cpp_enum_field.h
  58. 0 11
      src/google/protobuf/compiler/cpp/cpp_field.cc
  59. 0 13
      src/google/protobuf/compiler/cpp/cpp_field.h
  60. 1 12
      src/google/protobuf/compiler/cpp/cpp_file.cc
  61. 14 16
      src/google/protobuf/compiler/cpp/cpp_helpers.cc
  62. 1 6
      src/google/protobuf/compiler/cpp/cpp_helpers.h
  63. 27 81
      src/google/protobuf/compiler/cpp/cpp_map_field.cc
  64. 0 1
      src/google/protobuf/compiler/cpp/cpp_map_field.h
  65. 43 331
      src/google/protobuf/compiler/cpp/cpp_message.cc
  66. 74 73
      src/google/protobuf/compiler/cpp/cpp_message_field.cc
  67. 0 2
      src/google/protobuf/compiler/cpp/cpp_message_field.h
  68. 66 68
      src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
  69. 0 4
      src/google/protobuf/compiler/cpp/cpp_primitive_field.h
  70. 31 123
      src/google/protobuf/compiler/cpp/cpp_string_field.cc
  71. 0 3
      src/google/protobuf/compiler/cpp/cpp_string_field.h
  72. 2 1
      src/google/protobuf/compiler/cpp/cpp_unittest.inc
  73. 1 1
      src/google/protobuf/compiler/importer_unittest.cc
  74. 2 1
      src/google/protobuf/compiler/java/java_file.cc
  75. 2 1
      src/google/protobuf/compiler/java/java_helpers.cc
  76. 1 1
      src/google/protobuf/compiler/java/java_helpers.h
  77. 7 3
      src/google/protobuf/compiler/java/java_message.cc
  78. 3 4
      src/google/protobuf/compiler/java/java_message_lite.cc
  79. 2 1
      src/google/protobuf/compiler/java/java_string_field.cc
  80. 7 0
      src/google/protobuf/compiler/js/js_generator.cc
  81. 3 2
      src/google/protobuf/compiler/mock_code_generator.cc
  82. 2 1
      src/google/protobuf/compiler/parser.cc
  83. 4 5
      src/google/protobuf/compiler/parser_unittest.cc
  84. 22 329
      src/google/protobuf/compiler/plugin.pb.cc
  85. 121 48
      src/google/protobuf/compiler/plugin.pb.h
  86. 3 3
      src/google/protobuf/compiler/python/python_generator.cc
  87. 20 28
      src/google/protobuf/descriptor.cc
  88. 63 576
      src/google/protobuf/descriptor.pb.cc
  89. 304 75
      src/google/protobuf/descriptor.pb.h
  90. 11 7
      src/google/protobuf/descriptor_unittest.cc
  91. 6 64
      src/google/protobuf/duration.pb.cc
  92. 24 9
      src/google/protobuf/duration.pb.h
  93. 0 27
      src/google/protobuf/empty.pb.cc
  94. 0 5
      src/google/protobuf/empty.pb.h
  95. 0 3
      src/google/protobuf/extension_set.cc
  96. 2 9
      src/google/protobuf/extension_set.h
  97. 0 3
      src/google/protobuf/extension_set_heavy.cc
  98. 0 2
      src/google/protobuf/extension_set_inl.h
  99. 2 51
      src/google/protobuf/field_mask.pb.cc
  100. 12 7
      src/google/protobuf/field_mask.pb.h

+ 154 - 182
conformance/binary_json_conformance_suite.cc

@@ -157,16 +157,16 @@ enum class Packed {
   FALSE = 2,
 };
 
-const FieldDescriptor* GetFieldForType(
-    FieldDescriptor::Type type, bool repeated, bool is_proto3,
-    Packed packed = Packed::UNSPECIFIED) {
+const FieldDescriptor* GetFieldForType(FieldDescriptor::Type type,
+                                       bool repeated, bool is_proto3,
+                                       Packed packed = Packed::UNSPECIFIED) {
   const Descriptor* d = is_proto3 ?
       TestAllTypesProto3().GetDescriptor() : TestAllTypesProto2().GetDescriptor();
   for (int i = 0; i < d->field_count(); i++) {
     const FieldDescriptor* f = d->field(i);
     if (f->type() == type && f->is_repeated() == repeated) {
-      if (packed == Packed::TRUE && !f->is_packed() ||
-          packed == Packed::FALSE && f->is_packed()) {
+      if ((packed == Packed::TRUE && !f->is_packed()) ||
+          (packed == Packed::FALSE && f->is_packed())) {
         continue;
       }
       return f;
@@ -183,10 +183,8 @@ const FieldDescriptor* GetFieldForType(
     packed_string = "Unpacked ";
   }
   GOOGLE_LOG(FATAL) << "Couldn't find field with type: "
-                    << repeated_string.c_str()
-                    << packed_string.c_str()
-                    << FieldDescriptor::TypeName(type)
-                    << " for "
+                    << repeated_string.c_str() << packed_string.c_str()
+                    << FieldDescriptor::TypeName(type) << " for "
                     << proto_string.c_str();
   return nullptr;
 }
@@ -396,14 +394,13 @@ void BinaryAndJsonConformanceSuite::RunValidProtobufTest(
 void BinaryAndJsonConformanceSuite::RunValidBinaryProtobufTest(
     const string& test_name, ConformanceLevel level,
     const string& input_protobuf, bool is_proto3) {
-  RunValidBinaryProtobufTest(
-      test_name, level, input_protobuf, input_protobuf, is_proto3);
+  RunValidBinaryProtobufTest(test_name, level, input_protobuf, input_protobuf,
+                             is_proto3);
 }
 
 void BinaryAndJsonConformanceSuite::RunValidBinaryProtobufTest(
     const string& test_name, ConformanceLevel level,
-    const string& input_protobuf,
-    const string& expected_protobuf,
+    const string& input_protobuf, const string& expected_protobuf,
     bool is_proto3) {
   std::unique_ptr<Message> prototype = NewTestMessage(is_proto3);
   ConformanceRequestSetting setting(
@@ -625,8 +622,7 @@ void BinaryAndJsonConformanceSuite::TestValidDataForType(
 
     // Test singular data for singular fields.
     for (size_t i = 0; i < values.size(); i++) {
-      string proto =
-          cat(tag(field->number(), wire_type), values[i].first);
+      string proto = cat(tag(field->number(), wire_type), values[i].first);
       string expected_proto =
           cat(tag(field->number(), wire_type), values[i].second);
       std::unique_ptr<Message> test_message = NewTestMessage(is_proto3);
@@ -690,18 +686,15 @@ void BinaryAndJsonConformanceSuite::TestValidDataForType(
         unpacked_proto_expected +=
             cat(tag(unpacked_field->number(), wire_type), values[i].second);
       }
-      default_proto_packed =
-          cat(tag(rep_field->number(),
-                  WireFormatLite::WIRETYPE_LENGTH_DELIMITED),
-              delim(default_proto_packed));
-      default_proto_packed_expected =
-          cat(tag(rep_field->number(),
-                  WireFormatLite::WIRETYPE_LENGTH_DELIMITED),
-              delim(default_proto_packed_expected));
-      packed_proto_packed =
-          cat(tag(packed_field->number(),
-                  WireFormatLite::WIRETYPE_LENGTH_DELIMITED),
-              delim(packed_proto_packed));
+      default_proto_packed = cat(
+          tag(rep_field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED),
+          delim(default_proto_packed));
+      default_proto_packed_expected = cat(
+          tag(rep_field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED),
+          delim(default_proto_packed_expected));
+      packed_proto_packed = cat(tag(packed_field->number(),
+                                    WireFormatLite::WIRETYPE_LENGTH_DELIMITED),
+                                delim(packed_proto_packed));
       packed_proto_expected =
           cat(tag(packed_field->number(),
                   WireFormatLite::WIRETYPE_LENGTH_DELIMITED),
@@ -711,60 +704,44 @@ void BinaryAndJsonConformanceSuite::TestValidDataForType(
                   WireFormatLite::WIRETYPE_LENGTH_DELIMITED),
               delim(unpacked_proto_packed));
 
-
       std::unique_ptr<Message> test_message = NewTestMessage(is_proto3);
       test_message->MergeFromString(default_proto_packed_expected);
       string text = test_message->DebugString();
 
       // Ensures both packed and unpacked data can be parsed.
       RunValidProtobufTest(
-          StrCat("ValidDataRepeated", type_name, ".UnpackedInput"),
-          REQUIRED, default_proto_unpacked, text, is_proto3);
+          StrCat("ValidDataRepeated", type_name, ".UnpackedInput"), REQUIRED,
+          default_proto_unpacked, text, is_proto3);
       RunValidProtobufTest(
-          StrCat("ValidDataRepeated", type_name, ".PackedInput"),
-          REQUIRED, default_proto_packed, text, is_proto3);
+          StrCat("ValidDataRepeated", type_name, ".PackedInput"), REQUIRED,
+          default_proto_packed, text, is_proto3);
 
       // proto2 should encode as unpacked by default and proto3 should encode as
       // packed by default.
-      string expected_proto =
-          rep_field->is_packed() ? default_proto_packed_expected :
-                                   default_proto_unpacked_expected;
-      RunValidBinaryProtobufTest(
-          StrCat("ValidDataRepeated", type_name,
-                 ".UnpackedInput.DefaultOutput"),
-          RECOMMENDED,
-          default_proto_unpacked,
-          expected_proto, is_proto3);
+      string expected_proto = rep_field->is_packed()
+                                  ? default_proto_packed_expected
+                                  : default_proto_unpacked_expected;
+      RunValidBinaryProtobufTest(StrCat("ValidDataRepeated", type_name,
+                                        ".UnpackedInput.DefaultOutput"),
+                                 RECOMMENDED, default_proto_unpacked,
+                                 expected_proto, is_proto3);
       RunValidBinaryProtobufTest(
-          StrCat("ValidDataRepeated", type_name,
-                 ".PackedInput.DefaultOutput"),
-          RECOMMENDED,
-          default_proto_packed,
-          expected_proto, is_proto3);
+          StrCat("ValidDataRepeated", type_name, ".PackedInput.DefaultOutput"),
+          RECOMMENDED, default_proto_packed, expected_proto, is_proto3);
       RunValidBinaryProtobufTest(
-          StrCat("ValidDataRepeated", type_name,
-                 ".UnpackedInput.PackedOutput"),
-          RECOMMENDED,
-          packed_proto_unpacked,
-          packed_proto_expected, is_proto3);
+          StrCat("ValidDataRepeated", type_name, ".UnpackedInput.PackedOutput"),
+          RECOMMENDED, packed_proto_unpacked, packed_proto_expected, is_proto3);
       RunValidBinaryProtobufTest(
-          StrCat("ValidDataRepeated", type_name,
-                 ".PackedInput.PackedOutput"),
-          RECOMMENDED,
-          packed_proto_packed,
-          packed_proto_expected, is_proto3);
+          StrCat("ValidDataRepeated", type_name, ".PackedInput.PackedOutput"),
+          RECOMMENDED, packed_proto_packed, packed_proto_expected, is_proto3);
+      RunValidBinaryProtobufTest(StrCat("ValidDataRepeated", type_name,
+                                        ".UnpackedInput.UnpackedOutput"),
+                                 RECOMMENDED, unpacked_proto_unpacked,
+                                 unpacked_proto_expected, is_proto3);
       RunValidBinaryProtobufTest(
-          StrCat("ValidDataRepeated", type_name,
-                 ".UnpackedInput.UnpackedOutput"),
-          RECOMMENDED,
-          unpacked_proto_unpacked,
-          unpacked_proto_expected, is_proto3);
-      RunValidBinaryProtobufTest(
-          StrCat("ValidDataRepeated", type_name,
-                 ".PackedInput.UnpackedOutput"),
-          RECOMMENDED,
-          unpacked_proto_packed,
-          unpacked_proto_expected, is_proto3);
+          StrCat("ValidDataRepeated", type_name, ".PackedInput.UnpackedOutput"),
+          RECOMMENDED, unpacked_proto_packed, unpacked_proto_expected,
+          is_proto3);
     } else {
       string proto;
       string expected_proto;
@@ -777,27 +754,24 @@ void BinaryAndJsonConformanceSuite::TestValidDataForType(
       test_message->MergeFromString(expected_proto);
       string text = test_message->DebugString();
 
-      RunValidProtobufTest(
-          StrCat("ValidDataRepeated", type_name),
-          REQUIRED, proto, text, is_proto3);
+      RunValidProtobufTest(StrCat("ValidDataRepeated", type_name), REQUIRED,
+                           proto, text, is_proto3);
     }
   }
 }
 
 void BinaryAndJsonConformanceSuite::TestValidDataForRepeatedScalarMessage() {
   std::vector<std::string> values = {
-      delim(cat(tag(2, WireFormatLite::WIRETYPE_LENGTH_DELIMITED),
-                delim(cat(
-                    tag(1, WireFormatLite::WIRETYPE_VARINT), varint(1234),
+      delim(cat(
+          tag(2, WireFormatLite::WIRETYPE_LENGTH_DELIMITED),
+          delim(cat(tag(1, WireFormatLite::WIRETYPE_VARINT), varint(1234),
                     tag(2, WireFormatLite::WIRETYPE_VARINT), varint(1234),
-                    tag(31, WireFormatLite::WIRETYPE_VARINT), varint(1234)
-                )))),
-      delim(cat(tag(2, WireFormatLite::WIRETYPE_LENGTH_DELIMITED),
-                delim(cat(
-                    tag(1, WireFormatLite::WIRETYPE_VARINT), varint(4321),
+                    tag(31, WireFormatLite::WIRETYPE_VARINT), varint(1234))))),
+      delim(cat(
+          tag(2, WireFormatLite::WIRETYPE_LENGTH_DELIMITED),
+          delim(cat(tag(1, WireFormatLite::WIRETYPE_VARINT), varint(4321),
                     tag(3, WireFormatLite::WIRETYPE_VARINT), varint(4321),
-                    tag(31, WireFormatLite::WIRETYPE_VARINT), varint(4321)
-                )))),
+                    tag(31, WireFormatLite::WIRETYPE_VARINT), varint(4321))))),
   };
 
   const std::string expected =
@@ -820,9 +794,8 @@ void BinaryAndJsonConformanceSuite::TestValidDataForRepeatedScalarMessage() {
               values[i]);
     }
 
-    RunValidProtobufTest(
-        "RepeatedScalarMessageMerge", REQUIRED, proto,
-        field->name() + ": " + expected, is_proto3);
+    RunValidProtobufTest("RepeatedScalarMessageMerge", REQUIRED, proto,
+                         field->name() + ": " + expected, is_proto3);
   }
 }
 
@@ -920,107 +893,106 @@ void BinaryAndJsonConformanceSuite::RunSuiteImpl() {
   int32 kInt32Min = -2147483648;
   uint32 kUint32Max = 4294967295UL;
 
-  TestValidDataForType(FieldDescriptor::TYPE_DOUBLE, {
-    {dbl(0.1), dbl(0.1)},
-    {dbl(1.7976931348623157e+308), dbl(1.7976931348623157e+308)},
-    {dbl(2.22507385850720138309e-308), dbl(2.22507385850720138309e-308)}
-  });
-  TestValidDataForType(FieldDescriptor::TYPE_FLOAT, {
-    {flt(0.1), flt(0.1)},
-    {flt(1.00000075e-36), flt(1.00000075e-36)},
-    {flt(3.402823e+38), flt(3.402823e+38)},  // 3.40282347e+38
-    {flt(1.17549435e-38f), flt(1.17549435e-38)}
-  });
-  TestValidDataForType(FieldDescriptor::TYPE_INT64, {
-    {varint(12345), varint(12345)},
-    {varint(kInt64Max), varint(kInt64Max)},
-    {varint(kInt64Min), varint(kInt64Min)}
-  });
-  TestValidDataForType(FieldDescriptor::TYPE_UINT64, {
-    {varint(12345), varint(12345)},
-    {varint(kUint64Max), varint(kUint64Max)},
-    {varint(0), varint(0)}
-  });
-  TestValidDataForType(FieldDescriptor::TYPE_INT32, {
-    {varint(12345), varint(12345)},
-    {longvarint(12345, 2), varint(12345)},
-    {longvarint(12345, 7), varint(12345)},
-    {varint(kInt32Max), varint(kInt32Max)},
-    {varint(kInt32Min), varint(kInt32Min)},
-    {varint(1LL << 33), varint(0)},
-    {varint((1LL << 33) - 1), varint(-1)},
-  });
-  TestValidDataForType(FieldDescriptor::TYPE_UINT32, {
-    {varint(12345), varint(12345)},
-    {longvarint(12345, 2), varint(12345)},
-    {longvarint(12345, 7), varint(12345)},
-    {varint(kUint32Max), varint(kUint32Max)},  // UINT32_MAX
-    {varint(0), varint(0)},
-    {varint(1LL << 33), varint(0)},
-    {varint((1LL << 33) - 1), varint((1LL << 32) - 1)},
-  });
-  TestValidDataForType(FieldDescriptor::TYPE_FIXED64, {
-    {u64(12345), u64(12345)},
-    {u64(kUint64Max), u64(kUint64Max)},
-    {u64(0), u64(0)}
-  });
-  TestValidDataForType(FieldDescriptor::TYPE_FIXED32, {
-    {u32(12345), u32(12345)},
-    {u32(kUint32Max), u32(kUint32Max)},  // UINT32_MAX
-    {u32(0), u32(0)}
-  });
-  TestValidDataForType(FieldDescriptor::TYPE_SFIXED64, {
-    {u64(12345), u64(12345)},
-    {u64(kInt64Max), u64(kInt64Max)},
-    {u64(kInt64Min), u64(kInt64Min)}
-  });
-  TestValidDataForType(FieldDescriptor::TYPE_SFIXED32, {
-    {u32(12345), u32(12345)},
-    {u32(kInt32Max), u32(kInt32Max)},
-    {u32(kInt32Min), u32(kInt32Min)}
-  });
-  TestValidDataForType(FieldDescriptor::TYPE_BOOL, {
-    {varint(1), varint(1)},
-    {varint(0), varint(0)},
-    {varint(12345678), varint(1)}
-  });
-  TestValidDataForType(FieldDescriptor::TYPE_SINT32, {
-    {zz32(12345), zz32(12345)},
-    {zz32(kInt32Max), zz32(kInt32Max)},
-    {zz32(kInt32Min), zz32(kInt32Min)}
-  });
-  TestValidDataForType(FieldDescriptor::TYPE_SINT64, {
-    {zz64(12345), zz64(12345)},
-    {zz64(kInt64Max), zz64(kInt64Max)},
-    {zz64(kInt64Min), zz64(kInt64Min)}
-  });
-  TestValidDataForType(FieldDescriptor::TYPE_STRING, {
-    {delim("Hello world!"), delim("Hello world!")},
-    {delim("\'\"\?\\\a\b\f\n\r\t\v"),
-     delim("\'\"\?\\\a\b\f\n\r\t\v")},  // escape
-    {delim("谷歌"), delim("谷歌")},  // Google in Chinese
-    {delim("\u8C37\u6B4C"), delim("谷歌")},  // unicode escape
-    {delim("\u8c37\u6b4c"), delim("谷歌")},  // lowercase unicode
-    {delim("\xF0\x9F\x98\x81"), delim("\xF0\x9F\x98\x81")},  // emoji: 😁
-    {delim(""), delim("")},
-  });
-  TestValidDataForType(FieldDescriptor::TYPE_BYTES, {
-    {delim("\x01\x02"), delim("\x01\x02")},
-    {delim("\xfb"), delim("\xfb")},
-    {delim(""), delim("")},
-  });
+  TestValidDataForType(
+      FieldDescriptor::TYPE_DOUBLE,
+      {{dbl(0.1), dbl(0.1)},
+       {dbl(1.7976931348623157e+308), dbl(1.7976931348623157e+308)},
+       {dbl(2.22507385850720138309e-308), dbl(2.22507385850720138309e-308)}});
+  TestValidDataForType(
+      FieldDescriptor::TYPE_FLOAT,
+      {{flt(0.1), flt(0.1)},
+       {flt(1.00000075e-36), flt(1.00000075e-36)},
+       {flt(3.402823e+38), flt(3.402823e+38)},  // 3.40282347e+38
+       {flt(1.17549435e-38f), flt(1.17549435e-38)}});
+  TestValidDataForType(FieldDescriptor::TYPE_INT64,
+                       {{varint(12345), varint(12345)},
+                        {varint(kInt64Max), varint(kInt64Max)},
+                        {varint(kInt64Min), varint(kInt64Min)}});
+  TestValidDataForType(FieldDescriptor::TYPE_UINT64,
+                       {{varint(12345), varint(12345)},
+                        {varint(kUint64Max), varint(kUint64Max)},
+                        {varint(0), varint(0)}});
+  TestValidDataForType(FieldDescriptor::TYPE_INT32,
+                       {
+                           {varint(12345), varint(12345)},
+                           {longvarint(12345, 2), varint(12345)},
+                           {longvarint(12345, 7), varint(12345)},
+                           {varint(kInt32Max), varint(kInt32Max)},
+                           {varint(kInt32Min), varint(kInt32Min)},
+                           {varint(1LL << 33), varint(0)},
+                           {varint((1LL << 33) - 1), varint(-1)},
+                       });
+  TestValidDataForType(
+      FieldDescriptor::TYPE_UINT32,
+      {
+          {varint(12345), varint(12345)},
+          {longvarint(12345, 2), varint(12345)},
+          {longvarint(12345, 7), varint(12345)},
+          {varint(kUint32Max), varint(kUint32Max)},  // UINT32_MAX
+          {varint(0), varint(0)},
+          {varint(1LL << 33), varint(0)},
+          {varint((1LL << 33) - 1), varint((1LL << 32) - 1)},
+      });
+  TestValidDataForType(FieldDescriptor::TYPE_FIXED64,
+                       {{u64(12345), u64(12345)},
+                        {u64(kUint64Max), u64(kUint64Max)},
+                        {u64(0), u64(0)}});
+  TestValidDataForType(FieldDescriptor::TYPE_FIXED32,
+                       {{u32(12345), u32(12345)},
+                        {u32(kUint32Max), u32(kUint32Max)},  // UINT32_MAX
+                        {u32(0), u32(0)}});
+  TestValidDataForType(FieldDescriptor::TYPE_SFIXED64,
+                       {{u64(12345), u64(12345)},
+                        {u64(kInt64Max), u64(kInt64Max)},
+                        {u64(kInt64Min), u64(kInt64Min)}});
+  TestValidDataForType(FieldDescriptor::TYPE_SFIXED32,
+                       {{u32(12345), u32(12345)},
+                        {u32(kInt32Max), u32(kInt32Max)},
+                        {u32(kInt32Min), u32(kInt32Min)}});
+  TestValidDataForType(FieldDescriptor::TYPE_BOOL,
+                       {{varint(1), varint(1)},
+                        {varint(0), varint(0)},
+                        {varint(12345678), varint(1)}});
+  TestValidDataForType(FieldDescriptor::TYPE_SINT32,
+                       {{zz32(12345), zz32(12345)},
+                        {zz32(kInt32Max), zz32(kInt32Max)},
+                        {zz32(kInt32Min), zz32(kInt32Min)}});
+  TestValidDataForType(FieldDescriptor::TYPE_SINT64,
+                       {{zz64(12345), zz64(12345)},
+                        {zz64(kInt64Max), zz64(kInt64Max)},
+                        {zz64(kInt64Min), zz64(kInt64Min)}});
+  TestValidDataForType(
+      FieldDescriptor::TYPE_STRING,
+      {
+          {delim("Hello world!"), delim("Hello world!")},
+          {delim("\'\"\?\\\a\b\f\n\r\t\v"),
+           delim("\'\"\?\\\a\b\f\n\r\t\v")},       // escape
+          {delim("谷歌"), delim("谷歌")},          // Google in Chinese
+          {delim("\u8C37\u6B4C"), delim("谷歌")},  // unicode escape
+          {delim("\u8c37\u6b4c"), delim("谷歌")},  // lowercase unicode
+          {delim("\xF0\x9F\x98\x81"), delim("\xF0\x9F\x98\x81")},  // emoji: 😁
+          {delim(""), delim("")},
+      });
+  TestValidDataForType(FieldDescriptor::TYPE_BYTES,
+                       {
+                           {delim("\x01\x02"), delim("\x01\x02")},
+                           {delim("\xfb"), delim("\xfb")},
+                           {delim(""), delim("")},
+                       });
   TestValidDataForType(FieldDescriptor::TYPE_ENUM, {
-    {varint(0), varint(0)},
-    {varint(1), varint(1)},
-    {varint(2), varint(2)},
-    {varint(-1), varint(-1)},
-  });
+                                                       {varint(0), varint(0)},
+                                                       {varint(1), varint(1)},
+                                                       {varint(2), varint(2)},
+                                                       {varint(-1), varint(-1)},
+                                                   });
   TestValidDataForRepeatedScalarMessage();
-  TestValidDataForType(FieldDescriptor::TYPE_MESSAGE, {
-    {delim(cat(tag(1, WireFormatLite::WIRETYPE_VARINT), varint(1234))),
-     delim(cat(tag(1, WireFormatLite::WIRETYPE_VARINT), varint(1234)))},
-    {delim(""), delim("")},
-  });
+  TestValidDataForType(
+      FieldDescriptor::TYPE_MESSAGE,
+      {
+          {delim(cat(tag(1, WireFormatLite::WIRETYPE_VARINT), varint(1234))),
+           delim(cat(tag(1, WireFormatLite::WIRETYPE_VARINT), varint(1234)))},
+          {delim(""), delim("")},
+      });
 
   // TODO(haberman):
   // TestValidDataForType(FieldDescriptor::TYPE_GROUP

+ 0 - 26
conformance/conformance_cpp.cc

@@ -60,32 +60,6 @@ using std::string;
 static const char kTypeUrlPrefix[] = "type.googleapis.com";
 
 const char* kFailures[] = {
-#if !GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
-    "Required.Proto2.ProtobufInput."
-    "PrematureEofInDelimitedDataForKnownNonRepeatedValue.MESSAGE",
-    "Required.Proto2.ProtobufInput."
-    "PrematureEofInDelimitedDataForKnownRepeatedValue.MESSAGE",
-    "Required.Proto2.ProtobufInput.PrematureEofInPackedField.BOOL",
-    "Required.Proto2.ProtobufInput.PrematureEofInPackedField.ENUM",
-    "Required.Proto2.ProtobufInput.PrematureEofInPackedField.INT32",
-    "Required.Proto2.ProtobufInput.PrematureEofInPackedField.INT64",
-    "Required.Proto2.ProtobufInput.PrematureEofInPackedField.SINT32",
-    "Required.Proto2.ProtobufInput.PrematureEofInPackedField.SINT64",
-    "Required.Proto2.ProtobufInput.PrematureEofInPackedField.UINT32",
-    "Required.Proto2.ProtobufInput.PrematureEofInPackedField.UINT64",
-    "Required.Proto3.ProtobufInput."
-    "PrematureEofInDelimitedDataForKnownNonRepeatedValue.MESSAGE",
-    "Required.Proto3.ProtobufInput."
-    "PrematureEofInDelimitedDataForKnownRepeatedValue.MESSAGE",
-    "Required.Proto3.ProtobufInput.PrematureEofInPackedField.BOOL",
-    "Required.Proto3.ProtobufInput.PrematureEofInPackedField.ENUM",
-    "Required.Proto3.ProtobufInput.PrematureEofInPackedField.INT32",
-    "Required.Proto3.ProtobufInput.PrematureEofInPackedField.INT64",
-    "Required.Proto3.ProtobufInput.PrematureEofInPackedField.SINT32",
-    "Required.Proto3.ProtobufInput.PrematureEofInPackedField.SINT64",
-    "Required.Proto3.ProtobufInput.PrematureEofInPackedField.UINT32",
-    "Required.Proto3.ProtobufInput.PrematureEofInPackedField.UINT64",
-#endif
 };
 
 static string GetTypeUrl(const Descriptor* message) {

+ 2 - 2
conformance/conformance_objc.m

@@ -80,8 +80,8 @@ static ConformanceResponse *DoTest(ConformanceRequest *request) {
         msgClass = [TestAllTypesProto2 class];
       } else {
         response.runtimeError =
-            [NSString stringWithFormat:
-                @"Protobuf request had an unknown message_type: %@", request.messageType];
+            [NSString stringWithFormat:@"Protobuf request had an unknown message_type: %@",
+                                       request.messageType];
         break;
       }
       NSError *error = nil;

+ 8 - 11
conformance/conformance_test.cc

@@ -71,7 +71,7 @@ static string ToOctString(const string& binary_string) {
   return oct_string;
 }
 
-}
+}  // namespace
 
 namespace google {
 namespace protobuf {
@@ -239,21 +239,18 @@ void ConformanceTestSuite::RunValidInputTest(
 
 void ConformanceTestSuite::RunValidBinaryInputTest(
     const ConformanceRequestSetting& setting,
-    const string& equivalent_wire_format,
-    bool require_same_wire_format) {
+    const string& equivalent_wire_format, bool require_same_wire_format) {
   const ConformanceRequest& request = setting.GetRequest();
   ConformanceResponse response;
   RunTest(setting.GetTestName(), request, &response);
-  VerifyResponse(setting, equivalent_wire_format, response,
-                 true, require_same_wire_format);
+  VerifyResponse(setting, equivalent_wire_format, response, true,
+                 require_same_wire_format);
 }
 
 void ConformanceTestSuite::VerifyResponse(
     const ConformanceRequestSetting& setting,
-    const string& equivalent_wire_format,
-    const ConformanceResponse& response,
-    bool need_report_success,
-    bool require_same_wire_format) {
+    const string& equivalent_wire_format, const ConformanceResponse& response,
+    bool need_report_success, bool require_same_wire_format) {
   Message* test_message = setting.GetTestMessage();
   const ConformanceRequest& request = setting.GetRequest();
   const string& test_name = setting.GetTestName();
@@ -296,8 +293,8 @@ void ConformanceTestSuite::VerifyResponse(
 
   if (require_same_wire_format) {
     GOOGLE_DCHECK_EQ(response.result_case(),
-                    ConformanceResponse::kProtobufPayload);
-    const string& protobuf_payload =  response.protobuf_payload();
+                     ConformanceResponse::kProtobufPayload);
+    const string& protobuf_payload = response.protobuf_payload();
     check = equivalent_wire_format == protobuf_payload;
     differences = StrCat("Expect: ", ToOctString(equivalent_wire_format),
                          ", but got: ", ToOctString(protobuf_payload));

+ 16 - 10
conformance/conformance_test.h

@@ -38,14 +38,15 @@
 #ifndef CONFORMANCE_CONFORMANCE_TEST_H
 #define CONFORMANCE_CONFORMANCE_TEST_H
 
-#include <functional>
-#include <string>
-
 #include <google/protobuf/descriptor.h>
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/util/type_resolver.h>
 #include <google/protobuf/wire_format_lite.h>
 
+#include <functional>
+#include <string>
+#include <vector>
+
 #include "conformance.pb.h"
 
 namespace conformance {
@@ -88,7 +89,13 @@ class ForkPipeRunner : public ConformanceTestRunner {
   static int Run(int argc, char *argv[],
                  const std::vector<ConformanceTestSuite*>& suites);
 
-  ForkPipeRunner(const std::string &executable)
+  ForkPipeRunner(const std::string& executable,
+                 const std::vector<string>& executable_args)
+      : child_pid_(-1),
+        executable_(executable),
+        executable_args_(executable_args) {}
+
+  explicit ForkPipeRunner(const std::string& executable)
       : child_pid_(-1), executable_(executable) {}
 
   virtual ~ForkPipeRunner() {}
@@ -108,6 +115,7 @@ class ForkPipeRunner : public ConformanceTestRunner {
   int read_fd_;
   pid_t child_pid_;
   std::string executable_;
+  const std::vector<string> executable_args_;
   std::string current_test_name_;
 };
 
@@ -257,12 +265,10 @@ class ConformanceTestSuite {
       const ConformanceRequestSetting& setting,
       Message* test_message) = 0;
 
-  void VerifyResponse(
-      const ConformanceRequestSetting& setting,
-      const string& equivalent_wire_format,
-      const conformance::ConformanceResponse& response,
-      bool need_report_success,
-      bool require_same_wire_format);
+  void VerifyResponse(const ConformanceRequestSetting& setting,
+                      const string& equivalent_wire_format,
+                      const conformance::ConformanceResponse& response,
+                      bool need_report_success, bool require_same_wire_format);
 
   void ReportSuccess(const std::string& test_name);
   void ReportFailure(const string& test_name,

+ 15 - 8
conformance/conformance_test_runner.cc

@@ -195,7 +195,8 @@ int ForkPipeRunner::Run(
   }
   bool all_ok = true;
   for (ConformanceTestSuite* suite : suites) {
-    char *program;
+    string program;
+    std::vector<string> program_args;
     string failure_list_filename;
     conformance::FailureSet failure_list;
 
@@ -221,15 +222,15 @@ int ForkPipeRunner::Run(
           UsageError();
         }
       } else {
-        if (arg != argc - 1) {
-          fprintf(stderr, "Too many arguments.\n");
-          UsageError();
+        program += argv[arg];
+        while (arg < argc) {
+          program_args.push_back(argv[arg]);
+          arg++;
         }
-        program = argv[arg];
       }
     }
 
-    ForkPipeRunner runner(program);
+    ForkPipeRunner runner(program, program_args);
 
     std::string output;
     all_ok = all_ok &&
@@ -295,8 +296,14 @@ void ForkPipeRunner::SpawnTestProgram() {
     memcpy(executable.get(), executable_.c_str(), executable_.size());
     executable[executable_.size()] = '\0';
 
-    char *const argv[] = {executable.get(), NULL};
-    CHECK_SYSCALL(execv(executable.get(), argv));  // Never returns.
+    std::vector<const char *> argv;
+    argv.push_back(executable.get());
+    for (int i = 0; i < executable_args_.size(); ++i) {
+      argv.push_back(executable_args_[i].c_str());
+    }
+    argv.push_back(nullptr);
+    // Never returns.
+    CHECK_SYSCALL(execv(executable.get(), const_cast<char **>(argv.data())));
   }
 }
 

BIN
csharp/src/Google.Protobuf.Test/testprotos.pb


+ 9 - 0
java/core/src/main/java/com/google/protobuf/AbstractMessageLite.java

@@ -146,6 +146,15 @@ public abstract class AbstractMessageLite<
     Builder.addAll(values, list);
   }
 
+  /** Interface for an enum which signifies which field in a {@code oneof} was specified. */
+  protected interface InternalOneOfEnum {
+    /**
+     * Retrieves the field number of the field which was set in this {@code oneof}, or {@code 0} if
+     * none were.
+     */
+    int getNumber();
+  }
+
   /**
    * A partial implementation of the {@link Message.Builder} interface which implements as many
    * methods of that interface as possible in terms of other methods.

+ 10 - 0
java/core/src/main/java/com/google/protobuf/GeneratedMessageV3.java

@@ -2365,6 +2365,11 @@ public abstract class GeneratedMessageV3 extends AbstractMessage
         }
         try {
           return new MethodHandleInvoker(accessor);
+        } catch (NoClassDefFoundError e) {
+          // Fall back to reflection if MethodHandleInvoker isn't available,
+          // allowing clients that don't want to use method handles to opt out
+          // by deleting the class.
+          return accessor;
         } catch (IllegalAccessException e) {
           throw new RuntimeException(e);
         }
@@ -2703,6 +2708,11 @@ public abstract class GeneratedMessageV3 extends AbstractMessage
         }
         try {
           return new MethodHandleInvoker(accessor);
+        } catch (NoClassDefFoundError e) {
+          // Fall back to reflection if MethodHandleInvoker isn't available,
+          // allowing clients that don't want to use method handles to opt out
+          // by deleting the class.
+          return accessor;
         } catch (IllegalAccessException e) {
           throw new RuntimeException(e);
         }

+ 318 - 0
java/core/src/main/java/com/google/protobuf/UnsafeUtil.java

@@ -43,6 +43,9 @@ import java.util.logging.Logger;
 final class UnsafeUtil {
   private static final Logger logger = Logger.getLogger(UnsafeUtil.class.getName());
   private static final sun.misc.Unsafe UNSAFE = getUnsafe();
+  private static final Class<?> MEMORY_CLASS = Android.getMemoryClass();
+  private static final boolean IS_ANDROID_64 = determineAndroidSupportByAddressSize(long.class);
+  private static final boolean IS_ANDROID_32 = determineAndroidSupportByAddressSize(int.class);
   private static final MemoryAccessor MEMORY_ACCESSOR = getMemoryAccessor();
   private static final boolean HAS_UNSAFE_BYTEBUFFER_OPERATIONS =
       supportsUnsafeByteBufferOperations();
@@ -89,6 +92,9 @@ final class UnsafeUtil {
     return HAS_UNSAFE_BYTEBUFFER_OPERATIONS;
   }
 
+  static boolean isAndroid64() {
+    return IS_ANDROID_64;
+  }
 
   @SuppressWarnings("unchecked") // safe by method contract
   static <T> T allocateInstance(Class<T> clazz) {
@@ -314,6 +320,16 @@ final class UnsafeUtil {
     if (UNSAFE == null) {
       return null;
     }
+    if (Android.isOnAndroidDevice()) {
+      if (IS_ANDROID_64) {
+        return new Android64MemoryAccessor(UNSAFE);
+      } else if (IS_ANDROID_32) {
+        return new Android32MemoryAccessor(UNSAFE);
+      } else {
+        return null;
+      }
+    }
+
     return new JvmMemoryAccessor(UNSAFE);
   }
 
@@ -333,6 +349,9 @@ final class UnsafeUtil {
       clazz.getMethod("putLong", Object.class, long.class, long.class);
       clazz.getMethod("getObject", Object.class, long.class);
       clazz.getMethod("putObject", Object.class, long.class, Object.class);
+      if (Android.isOnAndroidDevice()) {
+        return true;
+      }
       clazz.getMethod("getByte", Object.class, long.class);
       clazz.getMethod("putByte", Object.class, long.class, byte.class);
       clazz.getMethod("getBoolean", Object.class, long.class);
@@ -365,6 +384,9 @@ final class UnsafeUtil {
         return false;
       }
 
+      if (Android.isOnAndroidDevice()) {
+        return true;
+      }
       clazz.getMethod("getByte", long.class);
       clazz.getMethod("putByte", long.class, byte.class);
       clazz.getMethod("getInt", long.class);
@@ -382,9 +404,36 @@ final class UnsafeUtil {
     return false;
   }
 
+  private static boolean determineAndroidSupportByAddressSize(Class<?> addressClass) {
+    if (!Android.isOnAndroidDevice()) {
+      return false;
+    }
+    try {
+      Class<?> clazz = MEMORY_CLASS;
+      clazz.getMethod("peekLong", addressClass, boolean.class);
+      clazz.getMethod("pokeLong", addressClass, long.class, boolean.class);
+      clazz.getMethod("pokeInt", addressClass, int.class, boolean.class);
+      clazz.getMethod("peekInt", addressClass, boolean.class);
+      clazz.getMethod("pokeByte", addressClass, byte.class);
+      clazz.getMethod("peekByte", addressClass);
+      clazz.getMethod("pokeByteArray", addressClass, byte[].class, int.class, int.class);
+      clazz.getMethod("peekByteArray", addressClass, byte[].class, int.class, int.class);
+      return true;
+    } catch (Throwable t) {
+      return false;
+    }
+  }
 
   /** Finds the address field within a direct {@link Buffer}. */
   private static Field bufferAddressField() {
+    if (Android.isOnAndroidDevice()) {
+      // Old versions of Android had renamed the address field to 'effectiveDirectAddress', but
+      // recent versions of Android (>M?) use the OpenJDK implementation. Fall through in that case.
+      Field field = field(Buffer.class, "effectiveDirectAddress");
+      if (field != null) {
+        return field;
+      }
+    }
     Field field = field(Buffer.class, "address");
     return field != null && field.getType() == long.class ? field : null;
   }
@@ -656,4 +705,273 @@ final class UnsafeUtil {
     }
   }
 
+  private static final class Android64MemoryAccessor extends MemoryAccessor {
+
+    Android64MemoryAccessor(sun.misc.Unsafe unsafe) {
+      super(unsafe);
+    }
+
+    @Override
+    public byte getByte(long address) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void putByte(long address, byte value) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public int getInt(long address) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void putInt(long address, int value) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public long getLong(long address) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void putLong(long address, long value) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public byte getByte(Object target, long offset) {
+      if (IS_BIG_ENDIAN) {
+        return getByteBigEndian(target, offset);
+      } else {
+        return getByteLittleEndian(target, offset);
+      }
+    }
+
+    @Override
+    public void putByte(Object target, long offset, byte value) {
+      if (IS_BIG_ENDIAN) {
+        putByteBigEndian(target, offset, value);
+      } else {
+        putByteLittleEndian(target, offset, value);
+      }
+    }
+
+    @Override
+    public boolean getBoolean(Object target, long offset) {
+      if (IS_BIG_ENDIAN) {
+        return getBooleanBigEndian(target, offset);
+      } else {
+        return getBooleanLittleEndian(target, offset);
+      }
+    }
+
+    @Override
+    public void putBoolean(Object target, long offset, boolean value) {
+      if (IS_BIG_ENDIAN) {
+        putBooleanBigEndian(target, offset, value);
+      } else {
+        putBooleanLittleEndian(target, offset, value);
+      }
+    }
+
+    @Override
+    public float getFloat(Object target, long offset) {
+      return Float.intBitsToFloat(getInt(target, offset));
+    }
+
+    @Override
+    public void putFloat(Object target, long offset, float value) {
+      putInt(target, offset, Float.floatToIntBits(value));
+    }
+
+    @Override
+    public double getDouble(Object target, long offset) {
+      return Double.longBitsToDouble(getLong(target, offset));
+    }
+
+    @Override
+    public void putDouble(Object target, long offset, double value) {
+      putLong(target, offset, Double.doubleToLongBits(value));
+    }
+
+    @Override
+    public void copyMemory(long srcOffset, byte[] target, long targetIndex, long length) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void copyMemory(byte[] src, long srcIndex, long targetOffset, long length) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public Object getStaticObject(Field field) {
+      try {
+        return field.get(null);
+      } catch (IllegalAccessException e) {
+        return null;
+      }
+    }
+  }
+
+  private static final class Android32MemoryAccessor extends MemoryAccessor {
+
+    /** Mask used to convert a 64 bit memory address to a 32 bit address. */
+    private static final long SMALL_ADDRESS_MASK = 0x00000000FFFFFFFF;
+
+    /** Truncate a {@code long} address into a short {@code int} address. */
+    private static int smallAddress(long address) {
+      return (int) (SMALL_ADDRESS_MASK & address);
+    }
+
+    Android32MemoryAccessor(sun.misc.Unsafe unsafe) {
+      super(unsafe);
+    }
+
+    @Override
+    public byte getByte(long address) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void putByte(long address, byte value) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public int getInt(long address) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void putInt(long address, int value) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public long getLong(long address) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void putLong(long address, long value) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public byte getByte(Object target, long offset) {
+      if (IS_BIG_ENDIAN) {
+        return getByteBigEndian(target, offset);
+      } else {
+        return getByteLittleEndian(target, offset);
+      }
+    }
+
+    @Override
+    public void putByte(Object target, long offset, byte value) {
+      if (IS_BIG_ENDIAN) {
+        putByteBigEndian(target, offset, value);
+      } else {
+        putByteLittleEndian(target, offset, value);
+      }
+    }
+
+    @Override
+    public boolean getBoolean(Object target, long offset) {
+      if (IS_BIG_ENDIAN) {
+        return getBooleanBigEndian(target, offset);
+      } else {
+        return getBooleanLittleEndian(target, offset);
+      }
+    }
+
+    @Override
+    public void putBoolean(Object target, long offset, boolean value) {
+      if (IS_BIG_ENDIAN) {
+        putBooleanBigEndian(target, offset, value);
+      } else {
+        putBooleanLittleEndian(target, offset, value);
+      }
+    }
+
+    @Override
+    public float getFloat(Object target, long offset) {
+      return Float.intBitsToFloat(getInt(target, offset));
+    }
+
+    @Override
+    public void putFloat(Object target, long offset, float value) {
+      putInt(target, offset, Float.floatToIntBits(value));
+    }
+
+    @Override
+    public double getDouble(Object target, long offset) {
+      return Double.longBitsToDouble(getLong(target, offset));
+    }
+
+    @Override
+    public void putDouble(Object target, long offset, double value) {
+      putLong(target, offset, Double.doubleToLongBits(value));
+    }
+
+    @Override
+    public void copyMemory(long srcOffset, byte[] target, long targetIndex, long length) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void copyMemory(byte[] src, long srcIndex, long targetOffset, long length) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public Object getStaticObject(Field field) {
+      try {
+        return field.get(null);
+      } catch (IllegalAccessException e) {
+        return null;
+      }
+    }
+  }
+
+  private static byte getByteBigEndian(Object target, long offset) {
+    return (byte) ((getInt(target, offset & ~3) >>> ((~offset & 3) << 3)) & 0xFF);
+  }
+
+  private static byte getByteLittleEndian(Object target, long offset) {
+    return (byte) ((getInt(target, offset & ~3) >>> ((offset & 3) << 3)) & 0xFF);
+  }
+
+  private static void putByteBigEndian(Object target, long offset, byte value) {
+    int intValue = getInt(target, offset & ~3);
+    int shift = ((~(int) offset) & 3) << 3;
+    int output = (intValue & ~(0xFF << shift)) | ((0xFF & value) << shift);
+    putInt(target, offset & ~3, output);
+  }
+
+  private static void putByteLittleEndian(Object target, long offset, byte value) {
+    int intValue = getInt(target, offset & ~3);
+    int shift = (((int) offset) & 3) << 3;
+    int output = (intValue & ~(0xFF << shift)) | ((0xFF & value) << shift);
+    putInt(target, offset & ~3, output);
+  }
+
+  private static boolean getBooleanBigEndian(Object target, long offset) {
+    return getByteBigEndian(target, offset) != 0;
+  }
+
+  private static boolean getBooleanLittleEndian(Object target, long offset) {
+    return getByteLittleEndian(target, offset) != 0;
+  }
+
+  private static void putBooleanBigEndian(Object target, long offset, boolean value) {
+    putByteBigEndian(target, offset, (byte) (value ? 1 : 0));
+  }
+
+  private static void putBooleanLittleEndian(Object target, long offset, boolean value) {
+    putByteLittleEndian(target, offset, (byte) (value ? 1 : 0));
+  }
 }

+ 2 - 2
java/util/src/main/java/com/google/protobuf/util/FieldMaskUtil.java

@@ -345,8 +345,8 @@ public class FieldMaskUtil {
   }
 
   /**
-   * Merges fields specified by a FieldMask from one message to another with the
-   * specified merge options.
+   * Merges fields specified by a FieldMask from one message to another with the specified merge
+   * options. The destination will remain unchanged if an empty FieldMask is provided.
    */
   public static void merge(
       FieldMask mask, Message source, Message.Builder destination, MergeOptions options) {

+ 10 - 2
java/util/src/test/java/com/google/protobuf/util/FieldMaskTreeTest.java

@@ -182,11 +182,19 @@ public class FieldMaskTreeTest extends TestCase {
 
     FieldMaskUtil.MergeOptions options = new FieldMaskUtil.MergeOptions();
 
-    // Test merging each individual field.
+    // Test merging with an empty FieldMask.
     NestedTestAllTypes.Builder builder = NestedTestAllTypes.newBuilder();
+    builder.getPayloadBuilder().addRepeatedInt32(1000);
+    merge(new FieldMaskTree(), source, builder, options, useDynamicMessage);
+    NestedTestAllTypes.Builder expected = NestedTestAllTypes.newBuilder();
+    expected.getPayloadBuilder().addRepeatedInt32(1000);
+    assertEquals(expected.build(), builder.build());
+
+    // Test merging each individual field.
+    builder = NestedTestAllTypes.newBuilder();
     merge(new FieldMaskTree().addFieldPath("payload.optional_int32"),
         source, builder, options, useDynamicMessage);
-    NestedTestAllTypes.Builder expected = NestedTestAllTypes.newBuilder();
+    expected = NestedTestAllTypes.newBuilder();
     expected.getPayloadBuilder().setOptionalInt32(1234);
     assertEquals(expected.build(), builder.build());
 

+ 44 - 163
js/binary/decoder.js

@@ -44,7 +44,6 @@
  */
 
 goog.provide('jspb.BinaryDecoder');
-goog.provide('jspb.BinaryIterator');
 
 goog.require('goog.asserts');
 goog.require('goog.crypt');
@@ -52,164 +51,6 @@ goog.require('jspb.utils');
 
 
 
-/**
- * Simple helper class for traversing the contents of repeated scalar fields.
- * that may or may not have been packed into a wire-format blob.
- * @param {?jspb.BinaryDecoder=} opt_decoder
- * @param {?function(this:jspb.BinaryDecoder):(number|boolean|string)=}
- *     opt_next The decoder method to use for next().
- * @param {?Array<number|boolean|string>=} opt_elements
- * @constructor
- * @struct
- */
-jspb.BinaryIterator = function(opt_decoder, opt_next, opt_elements) {
-  /** @private {?jspb.BinaryDecoder} */
-  this.decoder_ = null;
-
-  /**
-   * The BinaryDecoder member function used when iterating over packed data.
-   * @private {?function(this:jspb.BinaryDecoder):(number|boolean|string)}
-   */
-  this.nextMethod_ = null;
-
-  /** @private {?Array<number|boolean|string>} */
-  this.elements_ = null;
-
-  /** @private {number} */
-  this.cursor_ = 0;
-
-  /** @private {number|boolean|string|null} */
-  this.nextValue_ = null;
-
-  /** @private {boolean} */
-  this.atEnd_ = true;
-
-  this.init_(opt_decoder, opt_next, opt_elements);
-};
-
-
-/**
- * @param {?jspb.BinaryDecoder=} opt_decoder
- * @param {?function(this:jspb.BinaryDecoder):(number|boolean|string)=}
- *     opt_next The decoder method to use for next().
- * @param {?Array<number|boolean|string>=} opt_elements
- * @private
- */
-jspb.BinaryIterator.prototype.init_ =
-    function(opt_decoder, opt_next, opt_elements) {
-  if (opt_decoder && opt_next) {
-    this.decoder_ = opt_decoder;
-    this.nextMethod_ = opt_next;
-  }
-  this.elements_ = opt_elements || null;
-  this.cursor_ = 0;
-  this.nextValue_ = null;
-  this.atEnd_ = !this.decoder_ && !this.elements_;
-
-  this.next();
-};
-
-
-/**
- * Global pool of BinaryIterator instances.
- * @private {!Array<!jspb.BinaryIterator>}
- */
-jspb.BinaryIterator.instanceCache_ = [];
-
-
-/**
- * Allocates a BinaryIterator from the cache, creating a new one if the cache
- * is empty.
- * @param {?jspb.BinaryDecoder=} opt_decoder
- * @param {?function(this:jspb.BinaryDecoder):(number|boolean|string)=}
- *     opt_next The decoder method to use for next().
- * @param {?Array<number|boolean|string>=} opt_elements
- * @return {!jspb.BinaryIterator}
- */
-jspb.BinaryIterator.alloc = function(opt_decoder, opt_next, opt_elements) {
-  if (jspb.BinaryIterator.instanceCache_.length) {
-    var iterator = jspb.BinaryIterator.instanceCache_.pop();
-    iterator.init_(opt_decoder, opt_next, opt_elements);
-    return iterator;
-  } else {
-    return new jspb.BinaryIterator(opt_decoder, opt_next, opt_elements);
-  }
-};
-
-
-/**
- * Puts this instance back in the instance cache.
- */
-jspb.BinaryIterator.prototype.free = function() {
-  this.clear();
-  if (jspb.BinaryIterator.instanceCache_.length < 100) {
-    jspb.BinaryIterator.instanceCache_.push(this);
-  }
-};
-
-
-/**
- * Clears the iterator.
- */
-jspb.BinaryIterator.prototype.clear = function() {
-  if (this.decoder_) {
-    this.decoder_.free();
-  }
-  this.decoder_ = null;
-  this.nextMethod_ = null;
-  this.elements_ = null;
-  this.cursor_ = 0;
-  this.nextValue_ = null;
-  this.atEnd_ = true;
-};
-
-
-/**
- * Returns the element at the iterator, or null if the iterator is invalid or
- * past the end of the decoder/array.
- * @return {number|boolean|string|null}
- */
-jspb.BinaryIterator.prototype.get = function() {
-  return this.nextValue_;
-};
-
-
-/**
- * Returns true if the iterator is at the end of the decoder/array.
- * @return {boolean}
- */
-jspb.BinaryIterator.prototype.atEnd = function() {
-  return this.atEnd_;
-};
-
-
-/**
- * Returns the element at the iterator and steps to the next element,
- * equivalent to '*pointer++' in C.
- * @return {number|boolean|string|null}
- */
-jspb.BinaryIterator.prototype.next = function() {
-  var lastValue = this.nextValue_;
-  if (this.decoder_) {
-    if (this.decoder_.atEnd()) {
-      this.nextValue_ = null;
-      this.atEnd_ = true;
-    } else {
-      this.nextValue_ = this.nextMethod_.call(this.decoder_);
-    }
-  } else if (this.elements_) {
-    if (this.cursor_ == this.elements_.length) {
-      this.nextValue_ = null;
-      this.atEnd_ = true;
-    } else {
-      this.nextValue_ = this.elements_[this.cursor_++];
-    }
-  }
-  return lastValue;
-};
-
-
-
 /**
  * BinaryDecoder implements the decoders for all the wire types specified in
  * https://developers.google.com/protocol-buffers/docs/encoding.
@@ -482,6 +323,32 @@ jspb.BinaryDecoder.prototype.readSplitVarint64 = function(convert) {
 };
 
 
+/**
+ * Reads a signed zigzag encoded varint from the binary stream and invokes
+ * the conversion function with the value in two signed 32 bit integers to
+ * produce the result. Since this does not convert the value to a number, no
+ * precision is lost.
+ *
+ * It's possible for an unsigned varint to be incorrectly encoded - more than
+ * 64 bits' worth of data could be present. If this happens, this method will
+ * throw an error.
+ *
+ * Zigzag encoding is a modification of varint encoding that reduces the
+ * storage overhead for small negative integers - for more details on the
+ * format, see https://developers.google.com/protocol-buffers/docs/encoding
+ *
+ * @param {function(number, number): T} convert Conversion function to produce
+ *     the result value, takes parameters (lowBits, highBits).
+ * @return {T}
+ * @template T
+ */
+jspb.BinaryDecoder.prototype.readSplitZigzagVarint64 = function(convert) {
+  return this.readSplitVarint64(function(low, high) {
+    return jspb.utils.fromZigzag64(low, high, convert);
+  });
+};
+
+
 /**
  * Reads a 64-bit fixed-width value from the stream and invokes the conversion
  * function with the value in two signed 32 bit integers to produce the result.
@@ -731,9 +598,25 @@ jspb.BinaryDecoder.prototype.readZigzagVarint64 = function() {
 };
 
 
+/**
+ * Reads a signed, zigzag-encoded 64-bit varint from the binary stream
+ * losslessly and returns it as an 8-character Unicode string for use as a hash
+ * table key.
+ *
+ * Zigzag encoding is a modification of varint encoding that reduces the
+ * storage overhead for small negative integers - for more details on the
+ * format, see https://developers.google.com/protocol-buffers/docs/encoding
+ *
+ * @return {string} The decoded zigzag varint in hash64 format.
+ */
+jspb.BinaryDecoder.prototype.readZigzagVarintHash64 = function() {
+  return this.readSplitZigzagVarint64(jspb.utils.joinHash64);
+};
+
+
 /**
  * Reads a signed, zigzag-encoded 64-bit varint from the binary stream and
- * returns its valud as a string.
+ * returns its value as a string.
  *
  * Zigzag encoding is a modification of varint encoding that reduces the
  * storage overhead for small negative integers - for more details on the
@@ -743,9 +626,7 @@ jspb.BinaryDecoder.prototype.readZigzagVarint64 = function() {
  * string.
  */
 jspb.BinaryDecoder.prototype.readZigzagVarint64String = function() {
-  // TODO(haberman): write lossless 64-bit zig-zag math.
-  var value = this.readZigzagVarint64();
-  return value.toString();
+  return this.readSplitZigzagVarint64(jspb.utils.joinSignedDecimalString);
 };
 
 

+ 89 - 0
js/binary/decoder_test.js

@@ -235,6 +235,95 @@ describe('binaryDecoderTest', function() {
     });
   });
 
+  describe('sint64', function() {
+    var /** !jspb.BinaryDecoder */ decoder;
+
+    var hashA =
+        String.fromCharCode(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
+    var hashB =
+        String.fromCharCode(0x12, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
+    var hashC =
+        String.fromCharCode(0x12, 0x34, 0x56, 0x78, 0x87, 0x65, 0x43, 0x21);
+    var hashD =
+        String.fromCharCode(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF);
+    beforeEach(function() {
+      var encoder = new jspb.BinaryEncoder();
+
+      encoder.writeZigzagVarintHash64(hashA);
+      encoder.writeZigzagVarintHash64(hashB);
+      encoder.writeZigzagVarintHash64(hashC);
+      encoder.writeZigzagVarintHash64(hashD);
+
+      decoder = jspb.BinaryDecoder.alloc(encoder.end());
+    });
+
+    it('reads 64-bit integers as decimal strings', function() {
+      const signed = true;
+      expect(decoder.readZigzagVarint64String())
+          .toEqual(jspb.utils.hash64ToDecimalString(hashA, signed));
+      expect(decoder.readZigzagVarint64String())
+          .toEqual(jspb.utils.hash64ToDecimalString(hashB, signed));
+      expect(decoder.readZigzagVarint64String())
+          .toEqual(jspb.utils.hash64ToDecimalString(hashC, signed));
+      expect(decoder.readZigzagVarint64String())
+          .toEqual(jspb.utils.hash64ToDecimalString(hashD, signed));
+    });
+
+    it('reads 64-bit integers as hash strings', function() {
+      expect(decoder.readZigzagVarintHash64()).toEqual(hashA);
+      expect(decoder.readZigzagVarintHash64()).toEqual(hashB);
+      expect(decoder.readZigzagVarintHash64()).toEqual(hashC);
+      expect(decoder.readZigzagVarintHash64()).toEqual(hashD);
+    });
+
+    it('reads split 64 bit zigzag integers', function() {
+      function hexJoin(bitsLow, bitsHigh) {
+        return `0x${(bitsHigh >>> 0).toString(16)}:0x${
+            (bitsLow >>> 0).toString(16)}`;
+      }
+      function hexJoinHash(hash64) {
+        jspb.utils.splitHash64(hash64);
+        return hexJoin(jspb.utils.split64Low, jspb.utils.split64High);
+      }
+
+      expect(decoder.readSplitZigzagVarint64(hexJoin))
+          .toEqual(hexJoinHash(hashA));
+      expect(decoder.readSplitZigzagVarint64(hexJoin))
+          .toEqual(hexJoinHash(hashB));
+      expect(decoder.readSplitZigzagVarint64(hexJoin))
+          .toEqual(hexJoinHash(hashC));
+      expect(decoder.readSplitZigzagVarint64(hexJoin))
+          .toEqual(hexJoinHash(hashD));
+    });
+
+    it('does zigzag encoding properly', function() {
+      // Test cases direcly from the protobuf dev guide.
+      // https://engdoc.corp.google.com/eng/howto/protocolbuffers/developerguide/encoding.shtml?cl=head#types
+      var testCases = [
+        {original: '0', zigzag: '0'},
+        {original: '-1', zigzag: '1'},
+        {original: '1', zigzag: '2'},
+        {original: '-2', zigzag: '3'},
+        {original: '2147483647', zigzag: '4294967294'},
+        {original: '-2147483648', zigzag: '4294967295'},
+        // 64-bit extremes, not in dev guide.
+        {original: '9223372036854775807', zigzag: '18446744073709551614'},
+        {original: '-9223372036854775808', zigzag: '18446744073709551615'},
+      ];
+      var encoder = new jspb.BinaryEncoder();
+      testCases.forEach(function(c) {
+        encoder.writeZigzagVarint64String(c.original);
+      });
+      var buffer = encoder.end();
+      var zigzagDecoder = jspb.BinaryDecoder.alloc(buffer);
+      var varintDecoder = jspb.BinaryDecoder.alloc(buffer);
+      testCases.forEach(function(c) {
+        expect(zigzagDecoder.readZigzagVarint64String()).toEqual(c.original);
+        expect(varintDecoder.readUnsignedVarint64String()).toEqual(c.zigzag);
+      });
+    });
+  });
+
   /**
    * Tests reading and writing large strings
    */

+ 18 - 4
js/binary/encoder.js

@@ -232,13 +232,27 @@ jspb.BinaryEncoder.prototype.writeZigzagVarint64 = function(value) {
  * @param {string} value The integer to convert.
  */
 jspb.BinaryEncoder.prototype.writeZigzagVarint64String = function(value) {
-  // TODO(haberman): write lossless 64-bit zig-zag math.
-  this.writeZigzagVarint64(parseInt(value, 10));
+  this.writeZigzagVarintHash64(jspb.utils.decimalStringToHash64(value));
 };
 
 
 /**
- * Writes a 8-bit unsigned integer to the buffer. Numbers outside the range
+ * Writes a 64-bit hash string (8 characters @ 8 bits of data each) to the
+ * buffer as a zigzag varint.
+ * @param {string} hash The hash to write.
+ */
+jspb.BinaryEncoder.prototype.writeZigzagVarintHash64 = function(hash) {
+  var self = this;
+  jspb.utils.splitHash64(hash);
+  jspb.utils.toZigzag64(
+      jspb.utils.split64Low, jspb.utils.split64High, function(lo, hi) {
+        self.writeSplitVarint64(lo >>> 0, hi >>> 0);
+      });
+};
+
+
+/**
+ * Writes an 8-bit unsigned integer to the buffer. Numbers outside the range
  * [0,2^8) will be truncated.
  * @param {number} value The value to write.
  */
@@ -294,7 +308,7 @@ jspb.BinaryEncoder.prototype.writeUint64 = function(value) {
 
 
 /**
- * Writes a 8-bit integer to the buffer. Numbers outside the range
+ * Writes an 8-bit integer to the buffer. Numbers outside the range
  * [-2^7,2^7) will be truncated.
  * @param {number} value The value to write.
  */

+ 35 - 1
js/binary/reader.js

@@ -49,6 +49,7 @@ goog.provide('jspb.BinaryReader');
 goog.require('goog.asserts');
 goog.require('jspb.BinaryConstants');
 goog.require('jspb.BinaryDecoder');
+goog.require('jspb.utils');
 
 
 
@@ -941,7 +942,7 @@ jspb.BinaryReader.prototype.readBytes = function() {
 
 
 /**
- * Reads a 64-bit varint or fixed64 field from the stream and returns it as a
+ * Reads a 64-bit varint or fixed64 field from the stream and returns it as an
  * 8-character Unicode string for use as a hash table key, or throws an error
  * if the next field in the stream is not of the correct wire type.
  *
@@ -954,6 +955,20 @@ jspb.BinaryReader.prototype.readVarintHash64 = function() {
 };
 
 
+/**
+ * Reads an sint64 field from the stream and returns it as an 8-character
+ * Unicode string for use as a hash table key, or throws an error if the next
+ * field in the stream is not of the correct wire type.
+ *
+ * @return {string} The hash value.
+ */
+jspb.BinaryReader.prototype.readSintHash64 = function() {
+  goog.asserts.assert(
+      this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT);
+  return this.decoder_.readZigzagVarintHash64();
+};
+
+
 /**
  * Reads a 64-bit varint field from the stream and invokes `convert` to produce
  * the return value, or throws an error if the next field in the stream is not
@@ -971,6 +986,25 @@ jspb.BinaryReader.prototype.readSplitVarint64 = function(convert) {
 };
 
 
+/**
+ * Reads a 64-bit zig-zag varint field from the stream and invokes `convert` to
+ * produce the return value, or throws an error if the next field in the stream
+ * is not of the correct wire type.
+ *
+ * @param {function(number, number): T} convert Conversion function to produce
+ *     the result value, takes parameters (lowBits, highBits).
+ * @return {T}
+ * @template T
+ */
+jspb.BinaryReader.prototype.readSplitZigzagVarint64 = function(convert) {
+  goog.asserts.assert(
+      this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT);
+  return this.decoder_.readSplitVarint64(function(lowBits, highBits) {
+    return jspb.utils.fromZigzag64(lowBits, highBits, convert);
+  });
+};
+
+
 /**
  * Reads a 64-bit varint or fixed64 field from the stream and returns it as a
  * 8-character Unicode string for use as a hash table key, or throws an error

+ 10 - 0
js/binary/reader_test.js

@@ -414,6 +414,7 @@ describe('binaryReaderTest', function() {
     var writer = new jspb.BinaryWriter();
     writer.writeInt64String(1, '4294967296');
     writer.writeSfixed64String(2, '4294967298');
+    writer.writeInt64String(3, '3');  // 3 is the zig-zag encoding of -2.
     var reader = jspb.BinaryReader.alloc(writer.getResultBuffer());
 
     function rejoin(lowBits, highBits) {
@@ -426,6 +427,10 @@ describe('binaryReaderTest', function() {
     reader.nextField();
     expect(reader.getFieldNumber()).toEqual(2);
     expect(reader.readSplitFixed64(rejoin)).toEqual(0x100000002);
+
+    reader.nextField();
+    expect(reader.getFieldNumber()).toEqual(3);
+    expect(reader.readSplitZigzagVarint64(rejoin)).toEqual(-2);
   });
 
   /**
@@ -490,6 +495,11 @@ describe('binaryReaderTest', function() {
         jspb.BinaryReader.prototype.readSint64,
         jspb.BinaryWriter.prototype.writeSint64,
         1, -Math.pow(2, 63), Math.pow(2, 63) - 513, Math.round);
+
+    doTestSignedField_(
+        jspb.BinaryReader.prototype.readSintHash64,
+        jspb.BinaryWriter.prototype.writeSintHash64, 1, -Math.pow(2, 63),
+        Math.pow(2, 63) - 513, jspb.utils.numberToHash64);
   });
 
 

+ 53 - 14
js/binary/utils.js

@@ -296,7 +296,7 @@ jspb.utils.splitHash64 = function(hash) {
  * @return {number}
  */
 jspb.utils.joinUint64 = function(bitsLow, bitsHigh) {
-  return bitsHigh * jspb.BinaryConstants.TWO_TO_32 + bitsLow;
+  return bitsHigh * jspb.BinaryConstants.TWO_TO_32 + (bitsLow >>> 0);
 };
 
 
@@ -322,6 +322,33 @@ jspb.utils.joinInt64 = function(bitsLow, bitsHigh) {
   return sign ? -result : result;
 };
 
+/**
+ * Converts split 64-bit values from standard two's complement encoding to
+ * zig-zag encoding. Invokes the provided function to produce final result.
+ *
+ * @param {number} bitsLow
+ * @param {number} bitsHigh
+ * @param {function(number, number): T} convert Conversion function to produce
+ *     the result value, takes parameters (lowBits, highBits).
+ * @return {T}
+ * @template T
+ */
+jspb.utils.toZigzag64 = function(bitsLow, bitsHigh, convert) {
+  // See
+  // https://engdoc.corp.google.com/eng/howto/protocolbuffers/developerguide/encoding.shtml?cl=head#types
+  // 64-bit math is: (n << 1) ^ (n >> 63)
+  //
+  // To do this in 32 bits, we can get a 32-bit sign-flipping mask from the
+  // high word.
+  // Then we can operate on each word individually, with the addition of the
+  // "carry" to get the most significant bit from the low word into the high
+  // word.
+  var signFlipMask = bitsHigh >> 31;
+  bitsHigh = (bitsHigh << 1 | bitsLow >>> 31) ^ signFlipMask;
+  bitsLow = (bitsLow << 1) ^ signFlipMask;
+  return convert(bitsLow, bitsHigh);
+};
+
 
 /**
  * Joins two 32-bit values into a 64-bit unsigned integer and applies zigzag
@@ -331,21 +358,33 @@ jspb.utils.joinInt64 = function(bitsLow, bitsHigh) {
  * @return {number}
  */
 jspb.utils.joinZigzag64 = function(bitsLow, bitsHigh) {
-  // Extract the sign bit and shift right by one.
-  var sign = bitsLow & 1;
-  bitsLow = ((bitsLow >>> 1) | (bitsHigh << 31)) >>> 0;
-  bitsHigh = bitsHigh >>> 1;
+  return jspb.utils.fromZigzag64(bitsLow, bitsHigh, jspb.utils.joinInt64);
+};
 
-  // Increment the split value if the sign bit was set.
-  if (sign) {
-    bitsLow = (bitsLow + 1) >>> 0;
-    if (bitsLow == 0) {
-      bitsHigh = (bitsHigh + 1) >>> 0;
-    }
-  }
 
-  var result = jspb.utils.joinUint64(bitsLow, bitsHigh);
-  return sign ? -result : result;
+/**
+ * Converts split 64-bit values from zigzag encoding to standard two's
+ * complement encoding. Invokes the provided function to produce final result.
+ *
+ * @param {number} bitsLow
+ * @param {number} bitsHigh
+ * @param {function(number, number): T} convert Conversion function to produce
+ *     the result value, takes parameters (lowBits, highBits).
+ * @return {T}
+ * @template T
+ */
+jspb.utils.fromZigzag64 = function(bitsLow, bitsHigh, convert) {
+  // 64 bit math is:
+  //   signmask = (zigzag & 1) ? -1 : 0;
+  //   twosComplement = (zigzag >> 1) ^ signmask;
+  //
+  // To work with 32 bit, we can operate on both but "carry" the lowest bit
+  // from the high word by shifting it up 31 bits to be the most significant bit
+  // of the low word.
+  var signFlipMask = -(bitsLow & 1);
+  bitsLow = ((bitsLow >>> 1) | (bitsHigh << 31)) ^ signFlipMask;
+  bitsHigh = (bitsHigh >>> 1) ^ signFlipMask;
+  return convert(bitsLow, bitsHigh);
 };
 
 

+ 47 - 0
js/binary/utils_test.js

@@ -465,6 +465,53 @@ describe('binaryUtilsTest', function() {
     }
   });
 
+  /**
+   * Tests zigzag conversions.
+   */
+  it('can encode and decode zigzag 64', function() {
+    function stringToHiLoPair(str) {
+      jspb.utils.splitDecimalString(str);
+      return {
+        lo: jspb.utils.split64Low >>> 0,
+        hi: jspb.utils.split64High >>> 0
+      };
+    }
+    function makeHiLoPair(lo, hi) {
+      return {lo: lo >>> 0, hi: hi >>> 0};
+    }
+    // Test cases direcly from the protobuf dev guide.
+    // https://engdoc.corp.google.com/eng/howto/protocolbuffers/developerguide/encoding.shtml?cl=head#types
+    var testCases = [
+      {original: stringToHiLoPair('0'), zigzag: stringToHiLoPair('0')},
+      {original: stringToHiLoPair('-1'), zigzag: stringToHiLoPair('1')},
+      {original: stringToHiLoPair('1'), zigzag: stringToHiLoPair('2')},
+      {original: stringToHiLoPair('-2'), zigzag: stringToHiLoPair('3')},
+      {
+        original: stringToHiLoPair('2147483647'),
+        zigzag: stringToHiLoPair('4294967294')
+      },
+      {
+        original: stringToHiLoPair('-2147483648'),
+        zigzag: stringToHiLoPair('4294967295')
+      },
+      // 64-bit extremes
+      {
+        original: stringToHiLoPair('9223372036854775807'),
+        zigzag: stringToHiLoPair('18446744073709551614')
+      },
+      {
+        original: stringToHiLoPair('-9223372036854775808'),
+        zigzag: stringToHiLoPair('18446744073709551615')
+      },
+    ];
+    for (const c of testCases) {
+      expect(jspb.utils.toZigzag64(c.original.lo, c.original.hi, makeHiLoPair))
+          .toEqual(c.zigzag);
+      expect(jspb.utils.fromZigzag64(c.zigzag.lo, c.zigzag.hi, makeHiLoPair))
+          .toEqual(c.original);
+    }
+  });
+
 
   /**
    * Tests counting packed varints.

+ 119 - 11
js/binary/writer.js

@@ -236,12 +236,11 @@ jspb.BinaryWriter.prototype.getResultBuffer = function() {
 
 /**
  * Converts the encoded data into a base64-encoded string.
- * @param {boolean=} opt_webSafe True indicates we should use a websafe
- *     alphabet, which does not require escaping for use in URLs.
+ * @param {!goog.crypt.base64.Alphabet=} alphabet Which flavor of base64 to use.
  * @return {string}
  */
-jspb.BinaryWriter.prototype.getResultBase64String = function(opt_webSafe) {
-  return goog.crypt.base64.encodeByteArray(this.getResultBuffer(), opt_webSafe);
+jspb.BinaryWriter.prototype.getResultBase64String = function(alphabet) {
+  return goog.crypt.base64.encodeByteArray(this.getResultBuffer(), alphabet);
 };
 
 
@@ -450,6 +449,19 @@ jspb.BinaryWriter.prototype.writeZigzagVarint64String_ = function(
 };
 
 
+/**
+ * Writes a zigzag varint field to the buffer without range checking.
+ * @param {number} field The field number.
+ * @param {string?} value The value to write.
+ * @private
+ */
+jspb.BinaryWriter.prototype.writeZigzagVarintHash64_ = function(field, value) {
+  if (value == null) return;
+  this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT);
+  this.encoder_.writeZigzagVarintHash64(value);
+};
+
+
 /**
  * Writes an int32 field to the buffer. Numbers outside the range [-2^31,2^31)
  * will be truncated.
@@ -563,7 +575,7 @@ jspb.BinaryWriter.prototype.writeUint64String = function(field, value) {
 
 
 /**
- * Writes a sint32 field to the buffer. Numbers outside the range [-2^31,2^31)
+ * Writes an sint32 field to the buffer. Numbers outside the range [-2^31,2^31)
  * will be truncated.
  * @param {number} field The field number.
  * @param {number?} value The value to write.
@@ -577,7 +589,7 @@ jspb.BinaryWriter.prototype.writeSint32 = function(field, value) {
 
 
 /**
- * Writes a sint64 field to the buffer. Numbers outside the range [-2^63,2^63)
+ * Writes an sint64 field to the buffer. Numbers outside the range [-2^63,2^63)
  * will be truncated.
  * @param {number} field The field number.
  * @param {number?} value The value to write.
@@ -591,15 +603,25 @@ jspb.BinaryWriter.prototype.writeSint64 = function(field, value) {
 
 
 /**
- * Writes a sint64 field to the buffer. Numbers outside the range [-2^63,2^63)
+ * Writes an sint64 field to the buffer from a hash64 encoded value. Numbers
+ * outside the range [-2^63,2^63) will be truncated.
+ * @param {number} field The field number.
+ * @param {string?} value The hash64 string to write.
+ */
+jspb.BinaryWriter.prototype.writeSintHash64 = function(field, value) {
+  if (value == null) return;
+  this.writeZigzagVarintHash64_(field, value);
+};
+
+
+/**
+ * Writes an sint64 field to the buffer. Numbers outside the range [-2^63,2^63)
  * will be truncated.
  * @param {number} field The field number.
  * @param {string?} value The decimal string to write.
  */
 jspb.BinaryWriter.prototype.writeSint64String = function(field, value) {
   if (value == null) return;
-  goog.asserts.assert((+value >= -jspb.BinaryConstants.TWO_TO_63) &&
-                      (+value < jspb.BinaryConstants.TWO_TO_63));
   this.writeZigzagVarint64String_(field, value);
 };
 
@@ -912,6 +934,22 @@ jspb.BinaryWriter.prototype.writeSplitVarint64 = function(
 };
 
 
+/**
+ * Writes a 64-bit field to the buffer as a zigzag encoded varint.
+ * @param {number} field The field number.
+ * @param {number} lowBits The low 32 bits.
+ * @param {number} highBits The high 32 bits.
+ */
+jspb.BinaryWriter.prototype.writeSplitZigzagVarint64 = function(
+    field, lowBits, highBits) {
+  this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT);
+  var encoder = this.encoder_;
+  jspb.utils.toZigzag64(lowBits, highBits, function(lowBits, highBits) {
+    encoder.writeSplitVarint64(lowBits >>> 0, highBits >>> 0);
+  });
+};
+
+
 /**
  * Writes an array of numbers to the buffer as a repeated 32-bit int field.
  * @param {number} field The field number.
@@ -986,6 +1024,23 @@ jspb.BinaryWriter.prototype.writeRepeatedSplitVarint64 = function(
 };
 
 
+/**
+ * Writes an array of 64-bit values to the buffer as a zigzag varint.
+ * @param {number} field The field number.
+ * @param {?Array<T>} value The value.
+ * @param {function(T): number} lo Function to get low bits.
+ * @param {function(T): number} hi Function to get high bits.
+ * @template T
+ */
+jspb.BinaryWriter.prototype.writeRepeatedSplitZigzagVarint64 = function(
+    field, value, lo, hi) {
+  if (value == null) return;
+  for (var i = 0; i < value.length; i++) {
+    this.writeSplitZigzagVarint64(field, lo(value[i]), hi(value[i]));
+  }
+};
+
+
 /**
  * Writes an array of numbers formatted as strings to the buffer as a repeated
  * 64-bit int field.
@@ -1095,6 +1150,20 @@ jspb.BinaryWriter.prototype.writeRepeatedSint64String = function(field, value) {
 };
 
 
+/**
+ * Writes an array of hash64 strings to the buffer as a repeated signed 64-bit
+ * int field.
+ * @param {number} field The field number.
+ * @param {?Array<string>} value The array of ints to write.
+ */
+jspb.BinaryWriter.prototype.writeRepeatedSintHash64 = function(field, value) {
+  if (value == null) return;
+  for (var i = 0; i < value.length; i++) {
+    this.writeZigzagVarintHash64_(field, value[i]);
+  }
+};
+
+
 /**
  * Writes an array of numbers to the buffer as a repeated fixed32 field. This
  * works for both signed and unsigned fixed32s.
@@ -1411,6 +1480,29 @@ jspb.BinaryWriter.prototype.writePackedSplitVarint64 = function(
 };
 
 
+/**
+ * Writes an array of 64-bit values to the buffer as a zigzag varint.
+ * @param {number} field The field number.
+ * @param {?Array<T>} value The value.
+ * @param {function(T): number} lo Function to get low bits.
+ * @param {function(T): number} hi Function to get high bits.
+ * @template T
+ */
+jspb.BinaryWriter.prototype.writePackedSplitZigzagVarint64 = function(
+    field, value, lo, hi) {
+  if (value == null) return;
+  var bookmark = this.beginDelimited_(field);
+  var encoder = this.encoder_;
+  for (var i = 0; i < value.length; i++) {
+    jspb.utils.toZigzag64(
+        lo(value[i]), hi(value[i]), function(bitsLow, bitsHigh) {
+          encoder.writeSplitVarint64(bitsLow >>> 0, bitsHigh >>> 0);
+        });
+  }
+  this.endDelimited_(bookmark);
+};
+
+
 /**
  * Writes an array of numbers represented as strings to the buffer as a packed
  * 64-bit int field.
@@ -1533,8 +1625,24 @@ jspb.BinaryWriter.prototype.writePackedSint64String = function(field, value) {
   if (value == null || !value.length) return;
   var bookmark = this.beginDelimited_(field);
   for (var i = 0; i < value.length; i++) {
-    // TODO(haberman): make lossless
-    this.encoder_.writeZigzagVarint64(parseInt(value[i], 10));
+    this.encoder_.writeZigzagVarintHash64(
+        jspb.utils.decimalStringToHash64(value[i]));
+  }
+  this.endDelimited_(bookmark);
+};
+
+
+/**
+ * Writes an array of hash 64 strings to the buffer as a packed signed 64-bit
+ * int field.
+ * @param {number} field The field number.
+ * @param {?Array<string>} value The array of decimal strings to write.
+ */
+jspb.BinaryWriter.prototype.writePackedSintHash64 = function(field, value) {
+  if (value == null || !value.length) return;
+  var bookmark = this.beginDelimited_(field);
+  for (var i = 0; i < value.length; i++) {
+    this.encoder_.writeZigzagVarintHash64(value[i]);
   }
   this.endDelimited_(bookmark);
 };

+ 120 - 2
js/binary/writer_test.js

@@ -42,6 +42,7 @@ goog.require('goog.crypt');
 goog.require('goog.testing.asserts');
 goog.require('jspb.BinaryReader');
 goog.require('jspb.BinaryWriter');
+goog.require('jspb.utils');
 
 
 /**
@@ -128,8 +129,13 @@ describe('binaryWriterTest', function() {
     var writer = new jspb.BinaryWriter();
     writer.writeBytes(1, new Uint8Array([127]));
     assertEquals('CgF/', writer.getResultBase64String());
-    assertEquals('CgF/', writer.getResultBase64String(false));
-    assertEquals('CgF_', writer.getResultBase64String(true));
+    assertEquals(
+        'CgF/',
+        writer.getResultBase64String(goog.crypt.base64.Alphabet.DEFAULT));
+    assertEquals(
+        'CgF_',
+        writer.getResultBase64String(
+            goog.crypt.base64.Alphabet.WEBSAFE_NO_PADDING));
   });
 
   it('writes split 64 fields', function() {
@@ -201,4 +207,116 @@ describe('binaryWriterTest', function() {
       String(4 * 2 ** 32 + 3),
     ]);
   });
+
+  it('writes zigzag 64 fields', function() {
+    // Test cases direcly from the protobuf dev guide.
+    // https://engdoc.corp.google.com/eng/howto/protocolbuffers/developerguide/encoding.shtml?cl=head#types
+    var testCases = [
+      {original: '0', zigzag: '0'},
+      {original: '-1', zigzag: '1'},
+      {original: '1', zigzag: '2'},
+      {original: '-2', zigzag: '3'},
+      {original: '2147483647', zigzag: '4294967294'},
+      {original: '-2147483648', zigzag: '4294967295'},
+      // 64-bit extremes, not in dev guide.
+      {original: '9223372036854775807', zigzag: '18446744073709551614'},
+      {original: '-9223372036854775808', zigzag: '18446744073709551615'},
+    ];
+    function decimalToLowBits(v) {
+      jspb.utils.splitDecimalString(v);
+      return jspb.utils.split64Low >>> 0;
+    }
+    function decimalToHighBits(v) {
+      jspb.utils.splitDecimalString(v);
+      return jspb.utils.split64High >>> 0;
+    }
+
+    var writer = new jspb.BinaryWriter();
+    testCases.forEach(function(c) {
+      writer.writeSint64String(1, c.original);
+      writer.writeSintHash64(1, jspb.utils.decimalStringToHash64(c.original));
+      jspb.utils.splitDecimalString(c.original);
+      writer.writeSplitZigzagVarint64(
+          1, jspb.utils.split64Low, jspb.utils.split64High);
+    });
+
+    writer.writeRepeatedSint64String(2, testCases.map(function(c) {
+      return c.original;
+    }));
+
+    writer.writeRepeatedSintHash64(3, testCases.map(function(c) {
+      return jspb.utils.decimalStringToHash64(c.original);
+    }));
+
+    writer.writeRepeatedSplitZigzagVarint64(
+        4, testCases.map(function(c) {
+          return c.original;
+        }),
+        decimalToLowBits, decimalToHighBits);
+
+    writer.writePackedSint64String(5, testCases.map(function(c) {
+      return c.original;
+    }));
+
+    writer.writePackedSintHash64(6, testCases.map(function(c) {
+      return jspb.utils.decimalStringToHash64(c.original);
+    }));
+
+    writer.writePackedSplitZigzagVarint64(
+        7, testCases.map(function(c) {
+          return c.original;
+        }),
+        decimalToLowBits, decimalToHighBits);
+
+    // Verify by reading the stream as normal int64 fields and checking with
+    // the canonical zigzag encoding of each value.
+    var reader = jspb.BinaryReader.alloc(writer.getResultBuffer());
+    testCases.forEach(function(c) {
+      reader.nextField();
+      expect(reader.getFieldNumber()).toEqual(1);
+      expect(reader.readUint64String()).toEqual(c.zigzag);
+      reader.nextField();
+      expect(reader.getFieldNumber()).toEqual(1);
+      expect(reader.readUint64String()).toEqual(c.zigzag);
+      reader.nextField();
+      expect(reader.getFieldNumber()).toEqual(1);
+      expect(reader.readUint64String()).toEqual(c.zigzag);
+    });
+
+    testCases.forEach(function(c) {
+      reader.nextField();
+      expect(reader.getFieldNumber()).toEqual(2);
+      expect(reader.readUint64String()).toEqual(c.zigzag);
+    });
+
+    testCases.forEach(function(c) {
+      reader.nextField();
+      expect(reader.getFieldNumber()).toEqual(3);
+      expect(reader.readUint64String()).toEqual(c.zigzag);
+    });
+
+    testCases.forEach(function(c) {
+      reader.nextField();
+      expect(reader.getFieldNumber()).toEqual(4);
+      expect(reader.readUint64String()).toEqual(c.zigzag);
+    });
+
+    reader.nextField();
+    expect(reader.getFieldNumber()).toEqual(5);
+    expect(reader.readPackedUint64String()).toEqual(testCases.map(function(c) {
+      return c.zigzag;
+    }));
+
+    reader.nextField();
+    expect(reader.getFieldNumber()).toEqual(6);
+    expect(reader.readPackedUint64String()).toEqual(testCases.map(function(c) {
+      return c.zigzag;
+    }));
+
+    reader.nextField();
+    expect(reader.getFieldNumber()).toEqual(7);
+    expect(reader.readPackedUint64String()).toEqual(testCases.map(function(c) {
+      return c.zigzag;
+    }));
+  });
 });

+ 3 - 3
js/compatibility_tests/v3.0.0/binary/proto_test.js

@@ -172,7 +172,7 @@ function fillAllFields(msg) {
  * @return {boolean}
  */
 function bytesCompare(arr, expected) {
-  if (goog.isString(arr)) {
+  if (typeof arr === 'string') {
     arr = goog.crypt.base64.decodeStringToUint8Array(arr);
   }
   if (arr.length != expected.length) {
@@ -477,8 +477,8 @@ describe('protoBinaryTest', function() {
     var msg = new proto.jspb.test.TestAllTypes();
 
     function assertGetters() {
-      assertTrue(goog.isString(msg.getRepeatedBytesList_asB64()[0]));
-      assertTrue(goog.isString(msg.getRepeatedBytesList_asB64()[1]));
+      assertTrue(typeof msg.getRepeatedBytesList_asB64()[0] === 'string');
+      assertTrue(typeof msg.getRepeatedBytesList_asB64()[1] === 'string');
       assertTrue(msg.getRepeatedBytesList_asU8()[0] instanceof Uint8Array);
       assertTrue(msg.getRepeatedBytesList_asU8()[1] instanceof Uint8Array);
 

+ 3 - 3
js/compatibility_tests/v3.0.0/binary/utils_test.js

@@ -355,7 +355,7 @@ describe('binaryUtilsTest', function() {
      */
     function test(x, opt_bits) {
       jspb.utils.splitFloat32(x);
-      if (goog.isDef(opt_bits)) {
+      if (opt_bits !== undefined) {
         if (opt_bits != jspb.utils.split64Low) throw 'fail!';
       }
       if (truncate(x) != jspb.utils.joinFloat32(jspb.utils.split64Low,
@@ -422,10 +422,10 @@ describe('binaryUtilsTest', function() {
      */
     function test(x, opt_highBits, opt_lowBits) {
       jspb.utils.splitFloat64(x);
-      if (goog.isDef(opt_highBits)) {
+      if (opt_highBits !== undefined) {
         if (opt_highBits != jspb.utils.split64High) throw 'fail!';
       }
-      if (goog.isDef(opt_lowBits)) {
+      if (opt_lowBits !== undefined) {
         if (opt_lowBits != jspb.utils.split64Low) throw 'fail!';
       }
       if (x != jspb.utils.joinFloat64(jspb.utils.split64Low,

+ 3 - 2
js/compatibility_tests/v3.0.0/message_test.js

@@ -1057,8 +1057,9 @@ describe('Message test suite', function() {
 
   it('testFloatingPointFieldsSupportNan', function() {
     var assertNan = function(x) {
-      assertTrue('Expected ' + x + ' (' + goog.typeOf(x) + ') to be NaN.',
-          goog.isNumber(x) && isNaN(x));
+      assertTrue(
+          'Expected ' + x + ' (' + goog.typeOf(x) + ') to be NaN.',
+          typeof x === 'number' && isNaN(x));
     };
 
     var message = new proto.jspb.test.FloatingPointFields([

+ 1 - 1
js/compatibility_tests/v3.0.0/proto3_test.js

@@ -50,7 +50,7 @@ var BYTES_B64 = goog.crypt.base64.encodeByteArray(BYTES);
  * @return {boolean}
  */
 function bytesCompare(arr, expected) {
-  if (goog.isString(arr)) {
+  if (typeof arr === 'string') {
     arr = goog.crypt.base64.decodeStringToUint8Array(arr);
   }
   if (arr.length != expected.length) {

+ 3 - 3
js/compatibility_tests/v3.1.0/binary/proto_test.js

@@ -172,7 +172,7 @@ function fillAllFields(msg) {
  * @return {boolean}
  */
 function bytesCompare(arr, expected) {
-  if (goog.isString(arr)) {
+  if (typeof arr === 'string') {
     arr = goog.crypt.base64.decodeStringToUint8Array(arr);
   }
   if (arr.length != expected.length) {
@@ -477,8 +477,8 @@ describe('protoBinaryTest', function() {
     var msg = new proto.jspb.test.TestAllTypes();
 
     function assertGetters() {
-      assertTrue(goog.isString(msg.getRepeatedBytesList_asB64()[0]));
-      assertTrue(goog.isString(msg.getRepeatedBytesList_asB64()[1]));
+      assertTrue(typeof msg.getRepeatedBytesList_asB64()[0] === 'string');
+      assertTrue(typeof msg.getRepeatedBytesList_asB64()[1] === 'string');
       assertTrue(msg.getRepeatedBytesList_asU8()[0] instanceof Uint8Array);
       assertTrue(msg.getRepeatedBytesList_asU8()[1] instanceof Uint8Array);
 

+ 3 - 3
js/compatibility_tests/v3.1.0/binary/utils_test.js

@@ -355,7 +355,7 @@ describe('binaryUtilsTest', function() {
      */
     function test(x, opt_bits) {
       jspb.utils.splitFloat32(x);
-      if (goog.isDef(opt_bits)) {
+      if (opt_bits !== undefined) {
         if (opt_bits != jspb.utils.split64Low) throw 'fail!';
       }
       if (truncate(x) != jspb.utils.joinFloat32(jspb.utils.split64Low,
@@ -422,10 +422,10 @@ describe('binaryUtilsTest', function() {
      */
     function test(x, opt_highBits, opt_lowBits) {
       jspb.utils.splitFloat64(x);
-      if (goog.isDef(opt_highBits)) {
+      if (opt_highBits !== undefined) {
         if (opt_highBits != jspb.utils.split64High) throw 'fail!';
       }
-      if (goog.isDef(opt_lowBits)) {
+      if (opt_lowBits !== undefined) {
         if (opt_lowBits != jspb.utils.split64Low) throw 'fail!';
       }
       if (x != jspb.utils.joinFloat64(jspb.utils.split64Low,

+ 3 - 2
js/compatibility_tests/v3.1.0/message_test.js

@@ -1009,8 +1009,9 @@ describe('Message test suite', function() {
 
   it('testFloatingPointFieldsSupportNan', function() {
     var assertNan = function(x) {
-      assertTrue('Expected ' + x + ' (' + goog.typeOf(x) + ') to be NaN.',
-          goog.isNumber(x) && isNaN(x));
+      assertTrue(
+          'Expected ' + x + ' (' + goog.typeOf(x) + ') to be NaN.',
+          typeof x === 'number' && isNaN(x));
     };
 
     var message = new proto.jspb.test.FloatingPointFields([

+ 1 - 1
js/compatibility_tests/v3.1.0/proto3_test.js

@@ -50,7 +50,7 @@ var BYTES_B64 = goog.crypt.base64.encodeByteArray(BYTES);
  * @return {boolean}
  */
 function bytesCompare(arr, expected) {
-  if (goog.isString(arr)) {
+  if (typeof arr === 'string') {
     arr = goog.crypt.base64.decodeStringToUint8Array(arr);
   }
   if (arr.length != expected.length) {

+ 16 - 6
js/map.js

@@ -461,15 +461,21 @@ jspb.Map.prototype.serializeBinary = function(
  *    The BinaryReader parsing callback for type V, if V is a message type
  *
  * @param {K=} opt_defaultKey
- *    The default value for the type of map keys. Accepting map
- *    entries with unset keys is required for maps to be backwards compatible
- *    with the repeated message representation described here: goo.gl/zuoLAC
+ *    The default value for the type of map keys. Accepting map entries with
+ *    unset keys is required for maps to be backwards compatible with the
+ *    repeated message representation described here: goo.gl/zuoLAC
+ *
+ * @param {V=} opt_defaultValue
+ *    The default value for the type of map values. Accepting map entries with
+ *    unset values is required for maps to be backwards compatible with the
+ *    repeated message representation described here: goo.gl/zuoLAC
  *
  */
 jspb.Map.deserializeBinary = function(map, reader, keyReaderFn, valueReaderFn,
-                                      opt_valueReaderCallback, opt_defaultKey) {
+                                      opt_valueReaderCallback, opt_defaultKey,
+                                      opt_defaultValue) {
   var key = opt_defaultKey;
-  var value = undefined;
+  var value = opt_defaultValue;
 
   while (reader.nextField()) {
     if (reader.isEndGroup()) {
@@ -484,7 +490,11 @@ jspb.Map.deserializeBinary = function(map, reader, keyReaderFn, valueReaderFn,
       // Value.
       if (map.valueCtor_) {
         goog.asserts.assert(opt_valueReaderCallback);
-        value = new map.valueCtor_();
+        if (!value) {
+          // Old generator still doesn't provide default value message.
+          // Need this for backward compatibility.
+          value = new map.valueCtor_();
+        }
         valueReaderFn.call(reader, value, opt_valueReaderCallback);
       } else {
         value =

+ 78 - 2
js/maps_test.js

@@ -36,10 +36,18 @@ goog.require('proto.jspb.test.MapValueEnum');
 goog.require('proto.jspb.test.MapValueMessage');
 goog.require('proto.jspb.test.TestMapFields');
 goog.require('proto.jspb.test.TestMapFieldsOptionalKeys');
+goog.require('proto.jspb.test.TestMapFieldsOptionalValues');
 goog.require('proto.jspb.test.MapEntryOptionalKeysStringKey');
 goog.require('proto.jspb.test.MapEntryOptionalKeysInt32Key');
 goog.require('proto.jspb.test.MapEntryOptionalKeysInt64Key');
 goog.require('proto.jspb.test.MapEntryOptionalKeysBoolKey');
+goog.require('proto.jspb.test.MapEntryOptionalValuesStringValue');
+goog.require('proto.jspb.test.MapEntryOptionalValuesInt32Value');
+goog.require('proto.jspb.test.MapEntryOptionalValuesInt64Value');
+goog.require('proto.jspb.test.MapEntryOptionalValuesBoolValue');
+goog.require('proto.jspb.test.MapEntryOptionalValuesDoubleValue');
+goog.require('proto.jspb.test.MapEntryOptionalValuesEnumValue');
+goog.require('proto.jspb.test.MapEntryOptionalValuesMessageValue');
 
 // CommonJS-LoadFromFile: test_pb proto.jspb.test
 goog.require('proto.jspb.test.MapValueMessageNoBinary');
@@ -54,7 +62,12 @@ function checkMapEquals(map, entries) {
   var arr = map.toArray();
   assertEquals(arr.length, entries.length);
   for (var i = 0; i < arr.length; i++) {
-    assertElementsEquals(arr[i], entries[i]);
+    if (Array.isArray(arr[i])) {
+      assertTrue(Array.isArray(entries[i]));
+      assertArrayEquals(arr[i], entries[i]);
+    } else {
+      assertElementsEquals(arr[i], entries[i]);
+    }
   }
 }
 
@@ -265,8 +278,10 @@ function makeTests(msgInfo, submessageCtor, suffix) {
       var decoded = msgInfo.deserializeBinary(serialized);
       checkMapFields(decoded);
     });
+
     /**
-     * Tests deserialization of undefined map keys go to default values in binary format.
+     * Tests deserialization of undefined map keys go to default values in
+     * binary format.
      */
     it('testMapDeserializationForUndefinedKeys', function() {
       var testMessageOptionalKeys = new proto.jspb.test.TestMapFieldsOptionalKeys();
@@ -298,6 +313,67 @@ function makeTests(msgInfo, submessageCtor, suffix) {
         [false, 'd']
       ]);
     });
+
+    /**
+     * Tests deserialization of undefined map values go to default values in
+     * binary format.
+     */
+    it('testMapDeserializationForUndefinedValues', function() {
+      var testMessageOptionalValues =
+          new proto.jspb.test.TestMapFieldsOptionalValues();
+      var mapEntryStringValue =
+          new proto.jspb.test.MapEntryOptionalValuesStringValue();
+      mapEntryStringValue.setKey("a");
+      testMessageOptionalValues.setMapStringString(mapEntryStringValue);
+      var mapEntryInt32Value =
+          new proto.jspb.test.MapEntryOptionalValuesInt32Value();
+      mapEntryInt32Value.setKey("b");
+      testMessageOptionalValues.setMapStringInt32(mapEntryInt32Value);
+      var mapEntryInt64Value =
+          new proto.jspb.test.MapEntryOptionalValuesInt64Value();
+      mapEntryInt64Value.setKey("c");
+      testMessageOptionalValues.setMapStringInt64(mapEntryInt64Value);
+      var mapEntryBoolValue =
+          new proto.jspb.test.MapEntryOptionalValuesBoolValue();
+      mapEntryBoolValue.setKey("d");
+      testMessageOptionalValues.setMapStringBool(mapEntryBoolValue);
+      var mapEntryDoubleValue =
+          new proto.jspb.test.MapEntryOptionalValuesDoubleValue();
+      mapEntryDoubleValue.setKey("e");
+      testMessageOptionalValues.setMapStringDouble(mapEntryDoubleValue);
+      var mapEntryEnumValue =
+          new proto.jspb.test.MapEntryOptionalValuesEnumValue();
+      mapEntryEnumValue.setKey("f");
+      testMessageOptionalValues.setMapStringEnum(mapEntryEnumValue);
+      var mapEntryMessageValue =
+          new proto.jspb.test.MapEntryOptionalValuesMessageValue();
+      mapEntryMessageValue.setKey("g");
+      testMessageOptionalValues.setMapStringMsg(mapEntryMessageValue);
+      var deserializedMessage = msgInfo.deserializeBinary(
+        testMessageOptionalValues.serializeBinary()
+       );
+      checkMapEquals(deserializedMessage.getMapStringStringMap(), [
+        ['a', '']
+      ]);
+      checkMapEquals(deserializedMessage.getMapStringInt32Map(), [
+        ['b', 0]
+      ]);
+      checkMapEquals(deserializedMessage.getMapStringInt64Map(), [
+        ['c', 0]
+      ]);
+      checkMapEquals(deserializedMessage.getMapStringBoolMap(), [
+        ['d', false]
+      ]);
+      checkMapEquals(deserializedMessage.getMapStringDoubleMap(), [
+        ['e', 0.0]
+      ]);
+      checkMapEquals(deserializedMessage.getMapStringEnumMap(), [
+        ['f', 0]
+      ]);
+      checkMapEquals(deserializedMessage.getMapStringMsgMap(), [
+        ['g', []]
+      ]);
+    });
   }
 
 

+ 0 - 10
js/message.js

@@ -1860,7 +1860,6 @@ jspb.Message.clone_ = function(obj) {
  * @param {Function} constructor The message constructor.
  */
 jspb.Message.registerMessageType = function(id, constructor) {
-  jspb.Message.registry_[id] = constructor;
   // This is needed so we can later access messageId directly on the contructor,
   // otherwise it is not available due to 'property collapsing' by the compiler.
   /**
@@ -1868,15 +1867,6 @@ jspb.Message.registerMessageType = function(id, constructor) {
    */
   constructor.messageId = id;
 };
-
-
-/**
- * The registry of message ids to message constructors.
- * @private
- */
-jspb.Message.registry_ = {};
-
-
 /**
  * The extensions registered on MessageSet. This is a map of extension
  * field number to field info object. This should be considered as a

+ 5 - 5
js/package.json

@@ -8,11 +8,11 @@
   ],
   "dependencies": {},
   "devDependencies": {
-    "glob": "~6.0.4",
-    "google-closure-compiler": "~20190301.0.0",
-    "google-closure-library": "~20190301.0.0",
-    "gulp": "~4.0.1",
-    "jasmine": "~2.4.1"
+    "glob": "~7.1.4",
+    "google-closure-compiler": "~20190819.0.0",
+    "google-closure-library": "~20190819.0.0",
+    "gulp": "~4.0.2",
+    "jasmine": "~3.4.0"
   },
   "scripts": {
     "test": "node ./node_modules/gulp/bin/gulp.js test"

+ 50 - 0
js/testbinary.proto

@@ -232,6 +232,56 @@ message TestMapFieldsOptionalKeys {
 
 // End mock-map entries
 
+// These proto are 'mock map' entries to test the above map deserializing with
+// undefined values. Make sure TestMapFieldsOptionalValues is written to be
+// deserialized by TestMapFields
+message MapEntryOptionalValuesStringValue {
+  optional string key = 1;
+  optional string value = 2;
+}
+
+message MapEntryOptionalValuesInt32Value {
+  optional string key = 1;
+  optional int32 value = 2;
+}
+
+message MapEntryOptionalValuesInt64Value {
+  optional string key = 1;
+  optional int64 value = 2;
+}
+
+message MapEntryOptionalValuesBoolValue {
+  optional string key = 1;
+  optional bool value = 2;
+}
+
+message MapEntryOptionalValuesDoubleValue {
+  optional string key = 1;
+  optional double value = 2;
+}
+
+message MapEntryOptionalValuesEnumValue {
+  optional string key = 1;
+  optional MapValueEnum value = 2;
+}
+
+message MapEntryOptionalValuesMessageValue {
+  optional string key = 1;
+  optional MapValueMessage value = 2;
+}
+
+message TestMapFieldsOptionalValues {
+  optional MapEntryOptionalValuesStringValue map_string_string = 1;
+  optional MapEntryOptionalValuesInt32Value map_string_int32 = 2;
+  optional MapEntryOptionalValuesInt64Value map_string_int64 = 3;
+  optional MapEntryOptionalValuesBoolValue map_string_bool = 4;
+  optional MapEntryOptionalValuesDoubleValue map_string_double = 5;
+  optional MapEntryOptionalValuesEnumValue map_string_enum = 6;
+  optional MapEntryOptionalValuesMessageValue map_string_msg = 7;
+}
+
+// End mock-map entries
+
 enum MapValueEnum {
   MAP_VALUE_FOO = 0;
   MAP_VALUE_BAR = 1;

+ 49 - 0
python/google/protobuf/descriptor_pool.py

@@ -68,6 +68,22 @@ from google.protobuf import text_encoding
 _USE_C_DESCRIPTORS = descriptor._USE_C_DESCRIPTORS  # pylint: disable=protected-access
 
 
+def _Deprecated(func):
+  """Mark functions as deprecated."""
+
+  def NewFunc(*args, **kwargs):
+    warnings.warn(
+        'Call to deprecated function %s(). Note: Do add unlinked descriptors '
+        'to descriptor_pool is wrong. Use Add() or AddSerializedFile() '
+        'instead.' % func.__name__,
+        category=DeprecationWarning)
+    return func(*args, **kwargs)
+  NewFunc.__name__ = func.__name__
+  NewFunc.__doc__ = func.__doc__
+  NewFunc.__dict__.update(func.__dict__)
+  return NewFunc
+
+
 def _NormalizeFullyQualifiedName(name):
   """Remove leading period from fully-qualified type name.
 
@@ -199,7 +215,14 @@ class DescriptorPool(object):
         serialized_file_desc_proto)
     self.Add(file_desc_proto)
 
+  # Add Descriptor to descriptor pool is dreprecated. Please use Add()
+  # or AddSerializedFile() to add a FileDescriptorProto instead.
+  @_Deprecated
   def AddDescriptor(self, desc):
+    self._AddDescriptor(desc)
+
+  # Never call this method. It is for internal usage only.
+  def _AddDescriptor(self, desc):
     """Adds a Descriptor to the pool, non-recursively.
 
     If the Descriptor contains nested messages or enums, the caller must
@@ -217,7 +240,14 @@ class DescriptorPool(object):
     self._descriptors[desc.full_name] = desc
     self._AddFileDescriptor(desc.file)
 
+  # Add EnumDescriptor to descriptor pool is dreprecated. Please use Add()
+  # or AddSerializedFile() to add a FileDescriptorProto instead.
+  @_Deprecated
   def AddEnumDescriptor(self, enum_desc):
+    self._AddEnumDescriptor(enum_desc)
+
+  # Never call this method. It is for internal usage only.
+  def _AddEnumDescriptor(self, enum_desc):
     """Adds an EnumDescriptor to the pool.
 
     This method also registers the FileDescriptor associated with the enum.
@@ -251,7 +281,14 @@ class DescriptorPool(object):
         self._top_enum_values[full_name] = enum_value
     self._AddFileDescriptor(enum_desc.file)
 
+  # Add ServiceDescriptor to descriptor pool is dreprecated. Please use Add()
+  # or AddSerializedFile() to add a FileDescriptorProto instead.
+  @_Deprecated
   def AddServiceDescriptor(self, service_desc):
+    self._AddServiceDescriptor(service_desc)
+
+  # Never call this method. It is for internal usage only.
+  def _AddServiceDescriptor(self, service_desc):
     """Adds a ServiceDescriptor to the pool.
 
     Args:
@@ -265,7 +302,14 @@ class DescriptorPool(object):
                                 service_desc.file.name)
     self._service_descriptors[service_desc.full_name] = service_desc
 
+  # Add ExtensionDescriptor to descriptor pool is dreprecated. Please use Add()
+  # or AddSerializedFile() to add a FileDescriptorProto instead.
+  @_Deprecated
   def AddExtensionDescriptor(self, extension):
+    self._AddExtensionDescriptor(extension)
+
+  # Never call this method. It is for internal usage only.
+  def _AddExtensionDescriptor(self, extension):
     """Adds a FieldDescriptor describing an extension to the pool.
 
     Args:
@@ -307,7 +351,12 @@ class DescriptorPool(object):
       self._extensions_by_name[extension.containing_type][
           extension.message_type.full_name] = extension
 
+  @_Deprecated
   def AddFileDescriptor(self, file_desc):
+    self._InternalAddFileDescriptor(file_desc)
+
+  # Never call this method. It is for internal usage only.
+  def _InternalAddFileDescriptor(self, file_desc):
     """Adds a FileDescriptor to the pool, non-recursively.
 
     If the FileDescriptor contains messages or enums, the caller must explicitly

+ 21 - 1
python/google/protobuf/internal/decoder.py

@@ -421,12 +421,19 @@ def EnumDecoder(field_number, is_repeated, is_packed, key, new_default):
 
           message._unknown_fields.append(
               (tag_bytes, buffer[value_start_pos:pos].tobytes()))
+          if message._unknown_field_set is None:
+            message._unknown_field_set = containers.UnknownFieldSet()
+          message._unknown_field_set._add(
+              field_number, wire_format.WIRETYPE_VARINT, element)
           # pylint: enable=protected-access
       if pos > endpoint:
         if element in enum_type.values_by_number:
           del value[-1]   # Discard corrupt value.
         else:
           del message._unknown_fields[-1]
+          # pylint: disable=protected-access
+          del message._unknown_field_set._values[-1]
+          # pylint: enable=protected-access
         raise _DecodeError('Packed element was truncated.')
       return pos
     return DecodePackedField
@@ -459,7 +466,11 @@ def EnumDecoder(field_number, is_repeated, is_packed, key, new_default):
             message._unknown_fields = []
           message._unknown_fields.append(
               (tag_bytes, buffer[pos:new_pos].tobytes()))
-          # pylint: enable=protected-access
+          if message._unknown_field_set is None:
+            message._unknown_field_set = containers.UnknownFieldSet()
+          message._unknown_field_set._add(
+              field_number, wire_format.WIRETYPE_VARINT, element)
+        # pylint: enable=protected-access
         # Predict that the next tag is another copy of the same repeated
         # field.
         pos = new_pos + tag_len
@@ -497,6 +508,10 @@ def EnumDecoder(field_number, is_repeated, is_packed, key, new_default):
                                      wire_format.WIRETYPE_VARINT)
         message._unknown_fields.append(
             (tag_bytes, buffer[value_start_pos:pos].tobytes()))
+        if message._unknown_field_set is None:
+          message._unknown_field_set = containers.UnknownFieldSet()
+        message._unknown_field_set._add(
+            field_number, wire_format.WIRETYPE_VARINT, enum_value)
         # pylint: enable=protected-access
       return pos
     return DecodeField
@@ -812,6 +827,11 @@ def MessageSetItemDecoder(descriptor):
         message._unknown_fields = []
       message._unknown_fields.append(
           (MESSAGE_SET_ITEM_TAG, buffer[message_set_item_start:pos].tobytes()))
+      if message._unknown_field_set is None:
+        message._unknown_field_set = containers.UnknownFieldSet()
+      message._unknown_field_set._add(type_id,
+                                      wire_format.WIRETYPE_LENGTH_DELIMITED,
+                                      buffer[message_start:message_end])
       # pylint: enable=protected-access
 
     return pos

+ 2 - 1
python/google/protobuf/internal/descriptor_test.py

@@ -655,7 +655,8 @@ class GeneratedDescriptorTest(unittest.TestCase):
     nested_message_descriptor = unittest_pb2.TestAllTypes.NestedMessage.DESCRIPTOR
     self.assertEqual(len(message_descriptor.nested_types), 3)
     self.assertFalse(None in message_descriptor.nested_types)
-    self.assertTrue(nested_message_descriptor in message_descriptor.nested_types)
+    self.assertTrue(
+        nested_message_descriptor in message_descriptor.nested_types)
 
   def testServiceDescriptor(self):
     service_descriptor = unittest_pb2.DESCRIPTOR.services_by_name['TestService']

+ 3 - 0
python/google/protobuf/internal/extension_dict.py

@@ -162,6 +162,9 @@ class _ExtensionDict(object):
         type_checker.CheckValue(value))
     self._extended_message._Modified()
 
+  def __delitem__(self, extension_handle):
+    self._extended_message.ClearExtension(extension_handle)
+
   def _FindExtensionByName(self, name):
     """Tries to find a known extension with the specified name.
 

+ 2 - 3
python/google/protobuf/internal/python_message.py

@@ -676,7 +676,6 @@ def _AddPropertiesForNonRepeatedScalarField(field, cls):
   property_name = _PropertyName(proto_field_name)
   type_checker = type_checkers.GetTypeChecker(field)
   default_value = field.default_value
-  valid_values = set()
   is_proto3 = field.containing_type.syntax == 'proto3'
 
   def getter(self):
@@ -785,7 +784,8 @@ def _AddStaticMethods(cls):
   def RegisterExtension(extension_handle):
     extension_handle.containing_type = cls.DESCRIPTOR
     # TODO(amauryfa): Use cls.MESSAGE_FACTORY.pool when available.
-    cls.DESCRIPTOR.file.pool.AddExtensionDescriptor(extension_handle)
+    # pylint: disable=protected-access
+    cls.DESCRIPTOR.file.pool._AddExtensionDescriptor(extension_handle)
     _AttachFieldHelpers(cls, extension_handle)
   cls.RegisterExtension = staticmethod(RegisterExtension)
 
@@ -1072,7 +1072,6 @@ def _AddSerializeToStringMethod(message_descriptor, cls):
 
   def SerializeToString(self, **kwargs):
     # Check if the message has all of its required fields set.
-    errors = []
     if not self.IsInitialized():
       raise message_mod.EncodeError(
           'Message %s is missing required fields: %s' % (

+ 39 - 0
python/google/protobuf/internal/reflection_test.py

@@ -506,6 +506,11 @@ class ReflectionTest(unittest.TestCase):
         (unittest_pb2.optional_fixed32_extension, 1),
         (unittest_pb2.optional_string_extension , 'foo') ],
       proto.ListFields())
+    del proto.Extensions[unittest_pb2.optional_fixed32_extension]
+    self.assertEqual(
+        [(unittest_pb2.optional_int32_extension, 5),
+         (unittest_pb2.optional_string_extension, 'foo')],
+        proto.ListFields())
 
   def testRepeatedListExtensions(self):
     proto = unittest_pb2.TestAllExtensions()
@@ -522,6 +527,12 @@ class ReflectionTest(unittest.TestCase):
         (unittest_pb2.repeated_fixed32_extension, [1]),
         (unittest_pb2.repeated_string_extension , ['foo', 'bar', 'baz']) ],
       proto.ListFields())
+    del proto.Extensions[unittest_pb2.repeated_int32_extension]
+    del proto.Extensions[unittest_pb2.repeated_string_extension]
+    self.assertEqual(
+        [(unittest_pb2.optional_int32_extension, 21),
+         (unittest_pb2.repeated_fixed32_extension, [1])],
+        proto.ListFields())
 
   def testListFieldsAndExtensions(self):
     proto = unittest_pb2.TestFieldOrderings()
@@ -583,6 +594,7 @@ class ReflectionTest(unittest.TestCase):
   def testClearFieldWithUnknownFieldName(self):
     proto = unittest_pb2.TestAllTypes()
     self.assertRaises(ValueError, proto.ClearField, 'nonexistent_field')
+    self.assertRaises(ValueError, proto.ClearField, b'nonexistent_field')
 
   def testClearRemovesChildren(self):
     # Make sure there aren't any implementation bugs that are only partially
@@ -1199,6 +1211,32 @@ class ReflectionTest(unittest.TestCase):
     self.assertEqual(prius.price, new_prius.price)
     self.assertEqual(prius.owners, new_prius.owners)
 
+  def testExtensionDelete(self):
+    extendee_proto = more_extensions_pb2.ExtendedMessage()
+
+    extension_int32 = more_extensions_pb2.optional_int_extension
+    extendee_proto.Extensions[extension_int32] = 23
+
+    extension_repeated = more_extensions_pb2.repeated_int_extension
+    extendee_proto.Extensions[extension_repeated].append(11)
+
+    extension_msg = more_extensions_pb2.optional_message_extension
+    extendee_proto.Extensions[extension_msg].foreign_message_int = 56
+
+    self.assertEqual(len(extendee_proto.Extensions), 3)
+    del extendee_proto.Extensions[extension_msg]
+    self.assertEqual(len(extendee_proto.Extensions), 2)
+    del extendee_proto.Extensions[extension_repeated]
+    self.assertEqual(len(extendee_proto.Extensions), 1)
+    # Delete a none exist extension. It is OK to "del m.Extensions[ext]"
+    # even if the extension is not present in the message; we don't
+    # raise KeyError. This is consistent with "m.Extensions[ext]"
+    # returning a default value even if we did not set anything.
+    del extendee_proto.Extensions[extension_repeated]
+    self.assertEqual(len(extendee_proto.Extensions), 1)
+    del extendee_proto.Extensions[extension_int32]
+    self.assertEqual(len(extendee_proto.Extensions), 0)
+
   def testExtensionIter(self):
     extendee_proto = more_extensions_pb2.ExtendedMessage()
 
@@ -1820,6 +1858,7 @@ class ReflectionTest(unittest.TestCase):
     proto = unittest_pb2.TestRequired()
     self.assertFalse(proto.IsInitialized(errors))
     self.assertEqual(errors, ['a', 'b', 'c'])
+    self.assertRaises(TypeError, proto.IsInitialized, 1, 2, 3)
 
   @unittest.skipIf(
       api_implementation.Type() != 'cpp' or api_implementation.Version() != 2,

+ 11 - 10
python/google/protobuf/internal/text_format_test.py

@@ -845,17 +845,18 @@ class OnlyWorksWithProto2RightNowTests(TextFormatBase):
     all_data = message.SerializeToString()
     empty_message = unittest_pb2.TestEmptyMessage()
     empty_message.ParseFromString(all_data)
-    self.assertEqual('1: 101\n'
-                     '12: 4636878028842991616\n'
-                     '14: "hello"\n'
-                     '15: "103"\n'
-                     '16 {\n'
-                     '  17: 104\n'
-                     '}\n'
-                     '18 {\n'
-                     '  1: 105\n'
-                     '}\n',
+    self.assertEqual('  1: 101\n'
+                     '  12: 4636878028842991616\n'
+                     '  14: "hello"\n'
+                     '  15: "103"\n'
+                     '  16 {\n'
+                     '    17: 104\n'
+                     '  }\n'
+                     '  18 {\n'
+                     '    1: 105\n'
+                     '  }\n',
                      text_format.MessageToString(empty_message,
+                                                 indent=2,
                                                  print_unknown_fields=True))
     self.assertEqual('1: 101 '
                      '12: 4636878028842991616 '

+ 24 - 1
python/google/protobuf/internal/unknown_fields_test.py

@@ -50,6 +50,7 @@ from google.protobuf.internal import missing_enum_values_pb2
 from google.protobuf.internal import test_util
 from google.protobuf.internal import testing_refleaks
 from google.protobuf.internal import type_checkers
+from google.protobuf.internal import wire_format
 from google.protobuf import descriptor
 
 
@@ -91,7 +92,7 @@ class UnknownFieldsTest(unittest.TestCase):
 
     # Add an unknown extension.
     item = raw.item.add()
-    item.type_id = 98418603
+    item.type_id = 98218603
     message1 = message_set_extensions_pb2.TestMessageSetExtension1()
     message1.i = 12345
     item.message = message1.SerializeToString()
@@ -102,6 +103,19 @@ class UnknownFieldsTest(unittest.TestCase):
     proto = message_set_extensions_pb2.TestMessageSet()
     proto.MergeFromString(serialized)
 
+    unknown_fields = proto.UnknownFields()
+    self.assertEqual(len(unknown_fields), 1)
+    # Unknown field should have wire format data which can be parsed back to
+    # original message.
+    self.assertEqual(unknown_fields[0].field_number, item.type_id)
+    self.assertEqual(unknown_fields[0].wire_type,
+                     wire_format.WIRETYPE_LENGTH_DELIMITED)
+    d = unknown_fields[0].data
+    message_new = message_set_extensions_pb2.TestMessageSetExtension1()
+    message_new.ParseFromString(d.tobytes() if isinstance(d, (
+        memoryview)) else d)
+    self.assertEqual(message1, message_new)
+
     # Verify that the unknown extension is serialized unchanged
     reserialized = proto.SerializeToString()
     new_raw = unittest_mset_pb2.RawMessageSet()
@@ -344,6 +358,7 @@ class UnknownFieldsAccessorsTest(unittest.TestCase):
   def testUnknownExtensions(self):
     message = unittest_pb2.TestEmptyMessageWithExtensions()
     message.ParseFromString(self.all_fields_data)
+    self.assertEqual(len(message.UnknownFields()), 97)
     self.assertEqual(message.SerializeToString(), self.all_fields_data)
 
 
@@ -378,12 +393,18 @@ class UnknownEnumValuesTest(unittest.TestCase):
   def CheckUnknownField(self, name, expected_value):
     field_descriptor = self.descriptor.fields_by_name[name]
     unknown_fields = self.missing_message.UnknownFields()
+    count = 0
     for field in unknown_fields:
       if field.field_number == field_descriptor.number:
+        count += 1
         if field_descriptor.label == descriptor.FieldDescriptor.LABEL_REPEATED:
           self.assertIn(field.data, expected_value)
         else:
           self.assertEqual(expected_value, field.data)
+    if field_descriptor.label == descriptor.FieldDescriptor.LABEL_REPEATED:
+      self.assertEqual(count, len(expected_value))
+    else:
+      self.assertEqual(count, 1)
 
   def testUnknownParseMismatchEnumValue(self):
     just_string = missing_enum_values_pb2.JustString()
@@ -413,6 +434,8 @@ class UnknownEnumValuesTest(unittest.TestCase):
     self.assertEqual([], self.missing_message.packed_nested_enum)
 
   def testCheckUnknownFieldValueForEnum(self):
+    unknown_fields = self.missing_message.UnknownFields()
+    self.assertEqual(len(unknown_fields), 5)
     self.CheckUnknownField('optional_nested_enum',
                            self.message.optional_nested_enum)
     self.CheckUnknownField('repeated_nested_enum',

+ 4 - 0
python/google/protobuf/pyext/extension_dict.cc

@@ -214,6 +214,10 @@ int ass_subscript(ExtensionDict* self, PyObject* key, PyObject* value) {
     return -1;
   }
 
+  if (value == nullptr) {
+    return cmessage::ClearFieldByDescriptor(self->parent, descriptor);
+  }
+
   if (descriptor->label() != FieldDescriptor::LABEL_OPTIONAL ||
       descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
     PyErr_SetString(PyExc_TypeError, "Extension is repeated and/or composite "

+ 68 - 59
python/google/protobuf/pyext/message.cc

@@ -66,7 +66,6 @@
 #include <google/protobuf/pyext/scoped_pyobject_ptr.h>
 #include <google/protobuf/pyext/unknown_fields.h>
 #include <google/protobuf/util/message_differencer.h>
-#include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/io/strtod.h>
 #include <google/protobuf/stubs/map_util.h>
 
@@ -1332,7 +1331,7 @@ static void Dealloc(CMessage* self) {
 
 PyObject* IsInitialized(CMessage* self, PyObject* args) {
   PyObject* errors = NULL;
-  if (PyArg_ParseTuple(args, "|O", &errors) < 0) {
+  if (!PyArg_ParseTuple(args, "|O", &errors)) {
     return NULL;
   }
   if (self->message->IsInitialized()) {
@@ -1360,20 +1359,18 @@ PyObject* IsInitialized(CMessage* self, PyObject* args) {
   Py_RETURN_FALSE;
 }
 
-PyObject* HasFieldByDescriptor(
-    CMessage* self, const FieldDescriptor* field_descriptor) {
+int HasFieldByDescriptor(CMessage* self,
+                         const FieldDescriptor* field_descriptor) {
   Message* message = self->message;
   if (!CheckFieldBelongsToMessage(field_descriptor, message)) {
-    return NULL;
+    return -1;
   }
   if (field_descriptor->label() == FieldDescriptor::LABEL_REPEATED) {
     PyErr_SetString(PyExc_KeyError,
                     "Field is repeated. A singular method is required.");
-    return NULL;
+    return -1;
   }
-  bool has_field =
-      message->GetReflection()->HasField(*message, field_descriptor);
-  return PyBool_FromLong(has_field ? 1 : 0);
+  return message->GetReflection()->HasField(*message, field_descriptor);
 }
 
 const FieldDescriptor* FindFieldWithOneofs(
@@ -1475,10 +1472,10 @@ PyObject* ClearExtension(CMessage* self, PyObject* extension) {
   if (descriptor == NULL) {
     return NULL;
   }
-  if (InternalReleaseFieldByDescriptor(self, descriptor) < 0) {
-    return NULL;
+  if (ClearFieldByDescriptor(self, descriptor) < 0) {
+    return nullptr;
   }
-  return ClearFieldByDescriptor(self, descriptor);
+  Py_RETURN_NONE;
 }
 
 PyObject* HasExtension(CMessage* self, PyObject* extension) {
@@ -1486,7 +1483,12 @@ PyObject* HasExtension(CMessage* self, PyObject* extension) {
   if (descriptor == NULL) {
     return NULL;
   }
-  return HasFieldByDescriptor(self, descriptor);
+  int has_field = HasFieldByDescriptor(self, descriptor);
+  if (has_field < 0) {
+    return nullptr;
+  } else {
+    return PyBool_FromLong(has_field);
+  }
 }
 
 // ---------------------------------------------------------------------
@@ -1597,57 +1599,45 @@ int InternalReleaseFieldByDescriptor(
                                 containers_to_release);
 }
 
-PyObject* ClearFieldByDescriptor(
-    CMessage* self,
-    const FieldDescriptor* field_descriptor) {
+int ClearFieldByDescriptor(CMessage* self,
+                           const FieldDescriptor* field_descriptor) {
   if (!CheckFieldBelongsToMessage(field_descriptor, self->message)) {
-    return NULL;
+    return -1;
+  }
+  if (InternalReleaseFieldByDescriptor(self, field_descriptor) < 0) {
+    return -1;
   }
   AssureWritable(self);
   Message* message = self->message;
   message->GetReflection()->ClearField(message, field_descriptor);
-  Py_RETURN_NONE;
+  return 0;
 }
 
 PyObject* ClearField(CMessage* self, PyObject* arg) {
-  if (!(PyString_Check(arg) || PyUnicode_Check(arg))) {
-    PyErr_SetString(PyExc_TypeError, "field name must be a string");
-    return NULL;
-  }
-#if PY_MAJOR_VERSION < 3
   char* field_name;
-  Py_ssize_t size;
-  if (PyString_AsStringAndSize(arg, &field_name, &size) < 0) {
+  Py_ssize_t field_size;
+  if (PyString_AsStringAndSize(arg, &field_name, &field_size) < 0) {
     return NULL;
   }
-#else
-  Py_ssize_t size;
-  const char* field_name = PyUnicode_AsUTF8AndSize(arg, &size);
-#endif
   AssureWritable(self);
-  Message* message = self->message;
-  ScopedPyObjectPtr arg_in_oneof;
   bool is_in_oneof;
-  const FieldDescriptor* field_descriptor =
-      FindFieldWithOneofs(message, string(field_name, size), &is_in_oneof);
+  const FieldDescriptor* field_descriptor = FindFieldWithOneofs(
+      self->message, string(field_name, field_size), &is_in_oneof);
   if (field_descriptor == NULL) {
-    if (!is_in_oneof) {
+    if (is_in_oneof) {
+      // We gave the name of a oneof, and none of its fields are set.
+      Py_RETURN_NONE;
+    } else {
       PyErr_Format(PyExc_ValueError,
                    "Protocol message has no \"%s\" field.", field_name);
       return NULL;
-    } else {
-      Py_RETURN_NONE;
     }
-  } else if (is_in_oneof) {
-    const string& name = field_descriptor->name();
-    arg_in_oneof.reset(PyString_FromStringAndSize(name.c_str(), name.size()));
-    arg = arg_in_oneof.get();
   }
 
-  if (InternalReleaseFieldByDescriptor(self, field_descriptor) < 0) {
-    return NULL;
+  if (ClearFieldByDescriptor(self, field_descriptor) < 0) {
+    return nullptr;
   }
-  return ClearFieldByDescriptor(self, field_descriptor);
+  Py_RETURN_NONE;
 }
 
 PyObject* Clear(CMessage* self) {
@@ -1750,6 +1740,15 @@ static PyObject* InternalSerializeToString(
   if (size == 0) {
     return PyBytes_FromString("");
   }
+
+  if (size > INT_MAX) {
+    PyErr_Format(PyExc_ValueError,
+                 "Message %s exceeds maximum protobuf "
+                 "size of 2GB: %zu",
+                 GetMessageName(self).c_str(), size);
+    return nullptr;
+  }
+
   PyObject* result = PyBytes_FromStringAndSize(NULL, size);
   if (result == NULL) {
     return NULL;
@@ -1935,32 +1934,42 @@ static PyObject* MergeFromString(CMessage* self, PyObject* arg) {
 
   AssureWritable(self);
 
-  io::CodedInputStream input(
-      reinterpret_cast<const uint8*>(data), data_length);
-  if (allow_oversize_protos) {
-    input.SetTotalBytesLimit(INT_MAX, INT_MAX);
-    input.SetRecursionLimit(INT_MAX);
-  }
   PyMessageFactory* factory = GetFactoryForMessage(self);
-  input.SetExtensionRegistry(factory->pool->pool, factory->message_factory);
-  bool success = self->message->MergePartialFromCodedStream(&input);
+  int depth = allow_oversize_protos
+                  ? INT_MAX
+                  : io::CodedInputStream::GetDefaultRecursionLimit();
+  const char* ptr;
+  internal::ParseContext ctx(
+      depth, false, &ptr,
+      StringPiece(static_cast<const char*>(data), data_length));
+  ctx.data().pool = factory->pool->pool;
+  ctx.data().factory = factory->message_factory;
+
+  ptr = self->message->_InternalParse(ptr, &ctx);
+
   // Child message might be lazily created before MergeFrom. Make sure they
   // are mutable at this point if child messages are really created.
   if (FixupMessageAfterMerge(self) < 0) {
     return NULL;
   }
 
-  if (success) {
-    if (!input.ConsumedEntireMessage()) {
-      // TODO(jieluo): Raise error and return NULL instead.
-      // b/27494216
-      PyErr_Warn(NULL, "Unexpected end-group tag: Not all data was converted");
-    }
-    return PyInt_FromLong(input.CurrentPosition());
-  } else {
+  // Python makes distinction in error message, between a general parse failure
+  // and in-correct ending on a terminating tag. Hence we need to be a bit more
+  // explicit in our correctness checks.
+  if (ptr == nullptr || ctx.BytesUntilLimit(ptr) < 0) {
+    // Parse error or the parser overshoot the limit.
     PyErr_Format(DecodeError_class, "Error parsing message");
     return NULL;
   }
+  // ctx has an explicit limit set (length of string_view), so we have to
+  // check we ended at that limit.
+  if (!ctx.EndedAtLimit()) {
+    // TODO(jieluo): Raise error and return NULL instead.
+    // b/27494216
+    PyErr_Warn(nullptr, "Unexpected end-group tag: Not all data was converted");
+    return PyInt_FromLong(data_length - ctx.BytesUntilLimit(ptr));
+  }
+  return PyInt_FromLong(data_length);
 }
 
 static PyObject* ParseFromString(CMessage* self, PyObject* arg) {

+ 6 - 15
python/google/protobuf/pyext/message.h

@@ -224,28 +224,19 @@ bool SetSubmessage(CMessage* self, CMessage* submessage);
 // Corresponds to message api method Clear.
 PyObject* Clear(CMessage* self);
 
-// Clears the data described by the given descriptor. Used to clear extensions
-// (which don't have names). Extension release is handled by ExtensionDict
-// class, not this function.
-// TODO(anuraag): Try to make this discrepancy in release semantics with
-//                ClearField less confusing.
+// Clears the data described by the given descriptor.
+// Returns -1 on error.
 //
 // Corresponds to reflection api method ClearField.
-PyObject* ClearFieldByDescriptor(
-    CMessage* self, const FieldDescriptor* descriptor);
-
-// Clears the data for the given field name. The message is released if there
-// are any external references.
-//
-// Corresponds to reflection api method ClearField.
-PyObject* ClearField(CMessage* self, PyObject* arg);
+int ClearFieldByDescriptor(CMessage* self, const FieldDescriptor* descriptor);
 
 // Checks if the message has the field described by the descriptor. Used for
 // extensions (which have no name).
+// Returns 1 if true, 0 if false, and -1 on error.
 //
 // Corresponds to reflection api method HasField
-PyObject* HasFieldByDescriptor(
-    CMessage* self, const FieldDescriptor* field_descriptor);
+int HasFieldByDescriptor(CMessage* self,
+                         const FieldDescriptor* field_descriptor);
 
 // Checks if the message has the named field.
 //

+ 13 - 4
python/google/protobuf/symbol_database.py

@@ -58,6 +58,7 @@ Example usage:
 """
 
 
+from google.protobuf.internal import api_implementation
 from google.protobuf import descriptor_pool
 from google.protobuf import message_factory
 
@@ -88,7 +89,9 @@ class SymbolDatabase(message_factory.MessageFactory):
     Args:
       message_descriptor: a descriptor.MessageDescriptor.
     """
-    self.pool.AddDescriptor(message_descriptor)
+    if api_implementation.Type() == 'python':
+      # pylint: disable=protected-access
+      self.pool._AddDescriptor(message_descriptor)
 
   def RegisterEnumDescriptor(self, enum_descriptor):
     """Registers the given enum descriptor in the local database.
@@ -99,7 +102,9 @@ class SymbolDatabase(message_factory.MessageFactory):
     Returns:
       The provided descriptor.
     """
-    self.pool.AddEnumDescriptor(enum_descriptor)
+    if api_implementation.Type() == 'python':
+      # pylint: disable=protected-access
+      self.pool._AddEnumDescriptor(enum_descriptor)
     return enum_descriptor
 
   def RegisterServiceDescriptor(self, service_descriptor):
@@ -111,7 +116,9 @@ class SymbolDatabase(message_factory.MessageFactory):
     Returns:
       The provided descriptor.
     """
-    self.pool.AddServiceDescriptor(service_descriptor)
+    if api_implementation.Type() == 'python':
+      # pylint: disable=protected-access
+      self.pool._AddServiceDescriptor(service_descriptor)
 
   def RegisterFileDescriptor(self, file_descriptor):
     """Registers the given file descriptor in the local database.
@@ -122,7 +129,9 @@ class SymbolDatabase(message_factory.MessageFactory):
     Returns:
       The provided descriptor.
     """
-    self.pool.AddFileDescriptor(file_descriptor)
+    if api_implementation.Type() == 'python':
+      # pylint: disable=protected-access
+      self.pool._InternalAddFileDescriptor(file_descriptor)
 
   def GetSymbol(self, symbol):
     """Tries to find a symbol in the local database.

+ 5 - 2
python/google/protobuf/text_format.py

@@ -42,6 +42,9 @@ Simple usage example:
 
 __author__ = 'kenton@google.com (Kenton Varda)'
 
+# TODO(b/129989314) Import thread contention leads to test failures.
+import encodings.raw_unicode_escape  # pylint: disable=unused-import
+import encodings.unicode_escape  # pylint: disable=unused-import
 import io
 import re
 
@@ -455,8 +458,8 @@ class _Printer(object):
         if self.as_one_line:
           out.write('} ')
         else:
-          out.write('}\n')
           self.indent -= 2
+          out.write(' ' * self.indent + '}\n')
       elif field.wire_type == WIRETYPE_LENGTH_DELIMITED:
         try:
           # If this field is parseable as a Message, it is probably
@@ -479,8 +482,8 @@ class _Printer(object):
           if self.as_one_line:
             out.write('} ')
           else:
-            out.write('}\n')
             self.indent -= 2
+            out.write(' ' * self.indent + '}\n')
         else:
           # A string or bytes field. self.as_utf8 may not work.
           out.write(': \"')

+ 0 - 58
src/google/protobuf/any.pb.cc

@@ -171,7 +171,6 @@ void Any::Clear() {
   _internal_metadata_.Clear();
 }
 
-#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 const char* Any::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   while (!ctx->Done(&ptr)) {
@@ -212,63 +211,6 @@ failure:
   goto success;
 #undef CHK_
 }
-#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
-bool Any::MergePartialFromCodedStream(
-    ::PROTOBUF_NAMESPACE_ID::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
-  ::PROTOBUF_NAMESPACE_ID::uint32 tag;
-  // @@protoc_insertion_point(parse_start:google.protobuf.Any)
-  for (;;) {
-    ::std::pair<::PROTOBUF_NAMESPACE_ID::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
-    tag = p.first;
-    if (!p.second) goto handle_unusual;
-    switch (::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::GetTagFieldNumber(tag)) {
-      // string type_url = 1;
-      case 1: {
-        if (static_cast< ::PROTOBUF_NAMESPACE_ID::uint8>(tag) == (10 & 0xFF)) {
-          DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::ReadString(
-                input, this->_internal_mutable_type_url()));
-          DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String(
-            this->_internal_type_url().data(), static_cast<int>(this->_internal_type_url().length()),
-            ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::PARSE,
-            "google.protobuf.Any.type_url"));
-        } else {
-          goto handle_unusual;
-        }
-        break;
-      }
-
-      // bytes value = 2;
-      case 2: {
-        if (static_cast< ::PROTOBUF_NAMESPACE_ID::uint8>(tag) == (18 & 0xFF)) {
-          DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::ReadBytes(
-                input, this->_internal_mutable_value()));
-        } else {
-          goto handle_unusual;
-        }
-        break;
-      }
-
-      default: {
-      handle_unusual:
-        if (tag == 0) {
-          goto success;
-        }
-        DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SkipField(
-              input, tag, _internal_metadata_.mutable_unknown_fields()));
-        break;
-      }
-    }
-  }
-success:
-  // @@protoc_insertion_point(parse_success:google.protobuf.Any)
-  return true;
-failure:
-  // @@protoc_insertion_point(parse_failure:google.protobuf.Any)
-  return false;
-#undef DO_
-}
-#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 
 ::PROTOBUF_NAMESPACE_ID::uint8* Any::InternalSerializeWithCachedSizesToArray(
     ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {

+ 0 - 5
src/google/protobuf/any.pb.h

@@ -151,12 +151,7 @@ class PROTOBUF_EXPORT Any :
   bool IsInitialized() const final;
 
   size_t ByteSizeLong() const final;
-  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
   const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
-  #else
-  bool MergePartialFromCodedStream(
-      ::PROTOBUF_NAMESPACE_ID::io::CodedInputStream* input) final;
-  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
   ::PROTOBUF_NAMESPACE_ID::uint8* InternalSerializeWithCachedSizesToArray(
       ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
   int GetCachedSize() const final { return _cached_size_.Get(); }

+ 35 - 345
src/google/protobuf/api.pb.cc

@@ -215,7 +215,7 @@ Api::Api(const Api& from)
   if (!from._internal_version().empty()) {
     version_.AssignWithDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from.version_);
   }
-  if (from.has_source_context()) {
+  if (from._internal_has_source_context()) {
     source_context_ = new PROTOBUF_NAMESPACE_ID::SourceContext(*from.source_context_);
   } else {
     source_context_ = nullptr;
@@ -272,7 +272,6 @@ void Api::Clear() {
   _internal_metadata_.Clear();
 }
 
-#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 const char* Api::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   while (!ctx->Done(&ptr)) {
@@ -293,7 +292,7 @@ const char* Api::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::intern
           ptr -= 1;
           do {
             ptr += 1;
-            ptr = ctx->ParseMessage(add_methods(), ptr);
+            ptr = ctx->ParseMessage(_internal_add_methods(), ptr);
             CHK_(ptr);
             if (!ctx->DataAvailable(ptr)) break;
           } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<18>(ptr));
@@ -305,7 +304,7 @@ const char* Api::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::intern
           ptr -= 1;
           do {
             ptr += 1;
-            ptr = ctx->ParseMessage(add_options(), ptr);
+            ptr = ctx->ParseMessage(_internal_add_options(), ptr);
             CHK_(ptr);
             if (!ctx->DataAvailable(ptr)) break;
           } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<26>(ptr));
@@ -321,7 +320,7 @@ const char* Api::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::intern
       // .google.protobuf.SourceContext source_context = 5;
       case 5:
         if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 42)) {
-          ptr = ctx->ParseMessage(mutable_source_context(), ptr);
+          ptr = ctx->ParseMessage(_internal_mutable_source_context(), ptr);
           CHK_(ptr);
         } else goto handle_unusual;
         continue;
@@ -331,7 +330,7 @@ const char* Api::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::intern
           ptr -= 1;
           do {
             ptr += 1;
-            ptr = ctx->ParseMessage(add_mixins(), ptr);
+            ptr = ctx->ParseMessage(_internal_add_mixins(), ptr);
             CHK_(ptr);
             if (!ctx->DataAvailable(ptr)) break;
           } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<50>(ptr));
@@ -342,7 +341,7 @@ const char* Api::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::intern
         if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 56)) {
           ::PROTOBUF_NAMESPACE_ID::uint64 val = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint(&ptr);
           CHK_(ptr);
-          set_syntax(static_cast<PROTOBUF_NAMESPACE_ID::Syntax>(val));
+          _internal_set_syntax(static_cast<PROTOBUF_NAMESPACE_ID::Syntax>(val));
         } else goto handle_unusual;
         continue;
       default: {
@@ -364,125 +363,6 @@ failure:
   goto success;
 #undef CHK_
 }
-#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
-bool Api::MergePartialFromCodedStream(
-    ::PROTOBUF_NAMESPACE_ID::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
-  ::PROTOBUF_NAMESPACE_ID::uint32 tag;
-  // @@protoc_insertion_point(parse_start:google.protobuf.Api)
-  for (;;) {
-    ::std::pair<::PROTOBUF_NAMESPACE_ID::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
-    tag = p.first;
-    if (!p.second) goto handle_unusual;
-    switch (::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::GetTagFieldNumber(tag)) {
-      // string name = 1;
-      case 1: {
-        if (static_cast< ::PROTOBUF_NAMESPACE_ID::uint8>(tag) == (10 & 0xFF)) {
-          DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::ReadString(
-                input, this->_internal_mutable_name()));
-          DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String(
-            this->_internal_name().data(), static_cast<int>(this->_internal_name().length()),
-            ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::PARSE,
-            "google.protobuf.Api.name"));
-        } else {
-          goto handle_unusual;
-        }
-        break;
-      }
-
-      // repeated .google.protobuf.Method methods = 2;
-      case 2: {
-        if (static_cast< ::PROTOBUF_NAMESPACE_ID::uint8>(tag) == (18 & 0xFF)) {
-          DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::ReadMessage(
-                input, add_methods()));
-        } else {
-          goto handle_unusual;
-        }
-        break;
-      }
-
-      // repeated .google.protobuf.Option options = 3;
-      case 3: {
-        if (static_cast< ::PROTOBUF_NAMESPACE_ID::uint8>(tag) == (26 & 0xFF)) {
-          DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::ReadMessage(
-                input, add_options()));
-        } else {
-          goto handle_unusual;
-        }
-        break;
-      }
-
-      // string version = 4;
-      case 4: {
-        if (static_cast< ::PROTOBUF_NAMESPACE_ID::uint8>(tag) == (34 & 0xFF)) {
-          DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::ReadString(
-                input, this->_internal_mutable_version()));
-          DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String(
-            this->_internal_version().data(), static_cast<int>(this->_internal_version().length()),
-            ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::PARSE,
-            "google.protobuf.Api.version"));
-        } else {
-          goto handle_unusual;
-        }
-        break;
-      }
-
-      // .google.protobuf.SourceContext source_context = 5;
-      case 5: {
-        if (static_cast< ::PROTOBUF_NAMESPACE_ID::uint8>(tag) == (42 & 0xFF)) {
-          DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::ReadMessage(
-               input, mutable_source_context()));
-        } else {
-          goto handle_unusual;
-        }
-        break;
-      }
-
-      // repeated .google.protobuf.Mixin mixins = 6;
-      case 6: {
-        if (static_cast< ::PROTOBUF_NAMESPACE_ID::uint8>(tag) == (50 & 0xFF)) {
-          DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::ReadMessage(
-                input, add_mixins()));
-        } else {
-          goto handle_unusual;
-        }
-        break;
-      }
-
-      // .google.protobuf.Syntax syntax = 7;
-      case 7: {
-        if (static_cast< ::PROTOBUF_NAMESPACE_ID::uint8>(tag) == (56 & 0xFF)) {
-          int value = 0;
-          DO_((::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::ReadPrimitive<
-                   int, ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::TYPE_ENUM>(
-                 input, &value)));
-          set_syntax(static_cast< PROTOBUF_NAMESPACE_ID::Syntax >(value));
-        } else {
-          goto handle_unusual;
-        }
-        break;
-      }
-
-      default: {
-      handle_unusual:
-        if (tag == 0) {
-          goto success;
-        }
-        DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SkipField(
-              input, tag, _internal_metadata_.mutable_unknown_fields()));
-        break;
-      }
-    }
-  }
-success:
-  // @@protoc_insertion_point(parse_success:google.protobuf.Api)
-  return true;
-failure:
-  // @@protoc_insertion_point(parse_failure:google.protobuf.Api)
-  return false;
-#undef DO_
-}
-#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 
 ::PROTOBUF_NAMESPACE_ID::uint8* Api::InternalSerializeWithCachedSizesToArray(
     ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
@@ -501,19 +381,19 @@ failure:
   }
 
   // repeated .google.protobuf.Method methods = 2;
-  for (auto it = this->methods_.pointer_begin(),
-            end = this->methods_.pointer_end(); it < end; ++it) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->_internal_methods_size()); i < n; i++) {
     stream->EnsureSpace(&target);
     target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::
-      InternalWriteMessageToArray(2, **it, target, stream);
+      InternalWriteMessageToArray(2, this->_internal_methods(i), target, stream);
   }
 
   // repeated .google.protobuf.Option options = 3;
-  for (auto it = this->options_.pointer_begin(),
-            end = this->options_.pointer_end(); it < end; ++it) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->_internal_options_size()); i < n; i++) {
     stream->EnsureSpace(&target);
     target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::
-      InternalWriteMessageToArray(3, **it, target, stream);
+      InternalWriteMessageToArray(3, this->_internal_options(i), target, stream);
   }
 
   // string version = 4;
@@ -535,18 +415,18 @@ failure:
   }
 
   // repeated .google.protobuf.Mixin mixins = 6;
-  for (auto it = this->mixins_.pointer_begin(),
-            end = this->mixins_.pointer_end(); it < end; ++it) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->_internal_mixins_size()); i < n; i++) {
     stream->EnsureSpace(&target);
     target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::
-      InternalWriteMessageToArray(6, **it, target, stream);
+      InternalWriteMessageToArray(6, this->_internal_mixins(i), target, stream);
   }
 
   // .google.protobuf.Syntax syntax = 7;
   if (this->syntax() != 0) {
     stream->EnsureSpace(&target);
     target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteEnumToArray(
-      7, this->syntax(), target);
+      7, this->_internal_syntax(), target);
   }
 
   if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) {
@@ -566,21 +446,21 @@ size_t Api::ByteSizeLong() const {
   (void) cached_has_bits;
 
   // repeated .google.protobuf.Method methods = 2;
-  total_size += 1UL * this->methods_size();
+  total_size += 1UL * this->_internal_methods_size();
   for (const auto& msg : this->methods_) {
     total_size +=
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg);
   }
 
   // repeated .google.protobuf.Option options = 3;
-  total_size += 1UL * this->options_size();
+  total_size += 1UL * this->_internal_options_size();
   for (const auto& msg : this->options_) {
     total_size +=
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg);
   }
 
   // repeated .google.protobuf.Mixin mixins = 6;
-  total_size += 1UL * this->mixins_size();
+  total_size += 1UL * this->_internal_mixins_size();
   for (const auto& msg : this->mixins_) {
     total_size +=
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg);
@@ -610,7 +490,7 @@ size_t Api::ByteSizeLong() const {
   // .google.protobuf.Syntax syntax = 7;
   if (this->syntax() != 0) {
     total_size += 1 +
-      ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::EnumSize(this->syntax());
+      ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::EnumSize(this->_internal_syntax());
   }
 
   if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) {
@@ -656,10 +536,10 @@ void Api::MergeFrom(const Api& from) {
     version_.AssignWithDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from.version_);
   }
   if (from.has_source_context()) {
-    mutable_source_context()->PROTOBUF_NAMESPACE_ID::SourceContext::MergeFrom(from.source_context());
+    _internal_mutable_source_context()->PROTOBUF_NAMESPACE_ID::SourceContext::MergeFrom(from._internal_source_context());
   }
   if (from.syntax() != 0) {
-    set_syntax(from.syntax());
+    _internal_set_syntax(from._internal_syntax());
   }
 }
 
@@ -785,7 +665,6 @@ void Method::Clear() {
   _internal_metadata_.Clear();
 }
 
-#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 const char* Method::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   while (!ctx->Done(&ptr)) {
@@ -834,7 +713,7 @@ const char* Method::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::int
           ptr -= 1;
           do {
             ptr += 1;
-            ptr = ctx->ParseMessage(add_options(), ptr);
+            ptr = ctx->ParseMessage(_internal_add_options(), ptr);
             CHK_(ptr);
             if (!ctx->DataAvailable(ptr)) break;
           } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<50>(ptr));
@@ -845,7 +724,7 @@ const char* Method::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::int
         if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 56)) {
           ::PROTOBUF_NAMESPACE_ID::uint64 val = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint(&ptr);
           CHK_(ptr);
-          set_syntax(static_cast<PROTOBUF_NAMESPACE_ID::Syntax>(val));
+          _internal_set_syntax(static_cast<PROTOBUF_NAMESPACE_ID::Syntax>(val));
         } else goto handle_unusual;
         continue;
       default: {
@@ -867,133 +746,6 @@ failure:
   goto success;
 #undef CHK_
 }
-#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
-bool Method::MergePartialFromCodedStream(
-    ::PROTOBUF_NAMESPACE_ID::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
-  ::PROTOBUF_NAMESPACE_ID::uint32 tag;
-  // @@protoc_insertion_point(parse_start:google.protobuf.Method)
-  for (;;) {
-    ::std::pair<::PROTOBUF_NAMESPACE_ID::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
-    tag = p.first;
-    if (!p.second) goto handle_unusual;
-    switch (::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::GetTagFieldNumber(tag)) {
-      // string name = 1;
-      case 1: {
-        if (static_cast< ::PROTOBUF_NAMESPACE_ID::uint8>(tag) == (10 & 0xFF)) {
-          DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::ReadString(
-                input, this->_internal_mutable_name()));
-          DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String(
-            this->_internal_name().data(), static_cast<int>(this->_internal_name().length()),
-            ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::PARSE,
-            "google.protobuf.Method.name"));
-        } else {
-          goto handle_unusual;
-        }
-        break;
-      }
-
-      // string request_type_url = 2;
-      case 2: {
-        if (static_cast< ::PROTOBUF_NAMESPACE_ID::uint8>(tag) == (18 & 0xFF)) {
-          DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::ReadString(
-                input, this->_internal_mutable_request_type_url()));
-          DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String(
-            this->_internal_request_type_url().data(), static_cast<int>(this->_internal_request_type_url().length()),
-            ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::PARSE,
-            "google.protobuf.Method.request_type_url"));
-        } else {
-          goto handle_unusual;
-        }
-        break;
-      }
-
-      // bool request_streaming = 3;
-      case 3: {
-        if (static_cast< ::PROTOBUF_NAMESPACE_ID::uint8>(tag) == (24 & 0xFF)) {
-
-          DO_((::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::ReadPrimitive<
-                   bool, ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::TYPE_BOOL>(
-                 input, &request_streaming_)));
-        } else {
-          goto handle_unusual;
-        }
-        break;
-      }
-
-      // string response_type_url = 4;
-      case 4: {
-        if (static_cast< ::PROTOBUF_NAMESPACE_ID::uint8>(tag) == (34 & 0xFF)) {
-          DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::ReadString(
-                input, this->_internal_mutable_response_type_url()));
-          DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String(
-            this->_internal_response_type_url().data(), static_cast<int>(this->_internal_response_type_url().length()),
-            ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::PARSE,
-            "google.protobuf.Method.response_type_url"));
-        } else {
-          goto handle_unusual;
-        }
-        break;
-      }
-
-      // bool response_streaming = 5;
-      case 5: {
-        if (static_cast< ::PROTOBUF_NAMESPACE_ID::uint8>(tag) == (40 & 0xFF)) {
-
-          DO_((::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::ReadPrimitive<
-                   bool, ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::TYPE_BOOL>(
-                 input, &response_streaming_)));
-        } else {
-          goto handle_unusual;
-        }
-        break;
-      }
-
-      // repeated .google.protobuf.Option options = 6;
-      case 6: {
-        if (static_cast< ::PROTOBUF_NAMESPACE_ID::uint8>(tag) == (50 & 0xFF)) {
-          DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::ReadMessage(
-                input, add_options()));
-        } else {
-          goto handle_unusual;
-        }
-        break;
-      }
-
-      // .google.protobuf.Syntax syntax = 7;
-      case 7: {
-        if (static_cast< ::PROTOBUF_NAMESPACE_ID::uint8>(tag) == (56 & 0xFF)) {
-          int value = 0;
-          DO_((::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::ReadPrimitive<
-                   int, ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::TYPE_ENUM>(
-                 input, &value)));
-          set_syntax(static_cast< PROTOBUF_NAMESPACE_ID::Syntax >(value));
-        } else {
-          goto handle_unusual;
-        }
-        break;
-      }
-
-      default: {
-      handle_unusual:
-        if (tag == 0) {
-          goto success;
-        }
-        DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SkipField(
-              input, tag, _internal_metadata_.mutable_unknown_fields()));
-        break;
-      }
-    }
-  }
-success:
-  // @@protoc_insertion_point(parse_success:google.protobuf.Method)
-  return true;
-failure:
-  // @@protoc_insertion_point(parse_failure:google.protobuf.Method)
-  return false;
-#undef DO_
-}
-#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 
 ::PROTOBUF_NAMESPACE_ID::uint8* Method::InternalSerializeWithCachedSizesToArray(
     ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
@@ -1024,7 +776,7 @@ failure:
   // bool request_streaming = 3;
   if (this->request_streaming() != 0) {
     stream->EnsureSpace(&target);
-    target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteBoolToArray(3, this->request_streaming(), target);
+    target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteBoolToArray(3, this->_internal_request_streaming(), target);
   }
 
   // string response_type_url = 4;
@@ -1040,22 +792,22 @@ failure:
   // bool response_streaming = 5;
   if (this->response_streaming() != 0) {
     stream->EnsureSpace(&target);
-    target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteBoolToArray(5, this->response_streaming(), target);
+    target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteBoolToArray(5, this->_internal_response_streaming(), target);
   }
 
   // repeated .google.protobuf.Option options = 6;
-  for (auto it = this->options_.pointer_begin(),
-            end = this->options_.pointer_end(); it < end; ++it) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->_internal_options_size()); i < n; i++) {
     stream->EnsureSpace(&target);
     target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::
-      InternalWriteMessageToArray(6, **it, target, stream);
+      InternalWriteMessageToArray(6, this->_internal_options(i), target, stream);
   }
 
   // .google.protobuf.Syntax syntax = 7;
   if (this->syntax() != 0) {
     stream->EnsureSpace(&target);
     target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteEnumToArray(
-      7, this->syntax(), target);
+      7, this->_internal_syntax(), target);
   }
 
   if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) {
@@ -1075,7 +827,7 @@ size_t Method::ByteSizeLong() const {
   (void) cached_has_bits;
 
   // repeated .google.protobuf.Option options = 6;
-  total_size += 1UL * this->options_size();
+  total_size += 1UL * this->_internal_options_size();
   for (const auto& msg : this->options_) {
     total_size +=
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg);
@@ -1115,7 +867,7 @@ size_t Method::ByteSizeLong() const {
   // .google.protobuf.Syntax syntax = 7;
   if (this->syntax() != 0) {
     total_size += 1 +
-      ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::EnumSize(this->syntax());
+      ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::EnumSize(this->_internal_syntax());
   }
 
   if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) {
@@ -1163,13 +915,13 @@ void Method::MergeFrom(const Method& from) {
     response_type_url_.AssignWithDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from.response_type_url_);
   }
   if (from.request_streaming() != 0) {
-    set_request_streaming(from.request_streaming());
+    _internal_set_request_streaming(from._internal_request_streaming());
   }
   if (from.response_streaming() != 0) {
-    set_response_streaming(from.response_streaming());
+    _internal_set_response_streaming(from._internal_response_streaming());
   }
   if (from.syntax() != 0) {
-    set_syntax(from.syntax());
+    _internal_set_syntax(from._internal_syntax());
   }
 }
 
@@ -1275,7 +1027,6 @@ void Mixin::Clear() {
   _internal_metadata_.Clear();
 }
 
-#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 const char* Mixin::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   while (!ctx->Done(&ptr)) {
@@ -1316,67 +1067,6 @@ failure:
   goto success;
 #undef CHK_
 }
-#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
-bool Mixin::MergePartialFromCodedStream(
-    ::PROTOBUF_NAMESPACE_ID::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
-  ::PROTOBUF_NAMESPACE_ID::uint32 tag;
-  // @@protoc_insertion_point(parse_start:google.protobuf.Mixin)
-  for (;;) {
-    ::std::pair<::PROTOBUF_NAMESPACE_ID::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
-    tag = p.first;
-    if (!p.second) goto handle_unusual;
-    switch (::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::GetTagFieldNumber(tag)) {
-      // string name = 1;
-      case 1: {
-        if (static_cast< ::PROTOBUF_NAMESPACE_ID::uint8>(tag) == (10 & 0xFF)) {
-          DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::ReadString(
-                input, this->_internal_mutable_name()));
-          DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String(
-            this->_internal_name().data(), static_cast<int>(this->_internal_name().length()),
-            ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::PARSE,
-            "google.protobuf.Mixin.name"));
-        } else {
-          goto handle_unusual;
-        }
-        break;
-      }
-
-      // string root = 2;
-      case 2: {
-        if (static_cast< ::PROTOBUF_NAMESPACE_ID::uint8>(tag) == (18 & 0xFF)) {
-          DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::ReadString(
-                input, this->_internal_mutable_root()));
-          DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String(
-            this->_internal_root().data(), static_cast<int>(this->_internal_root().length()),
-            ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::PARSE,
-            "google.protobuf.Mixin.root"));
-        } else {
-          goto handle_unusual;
-        }
-        break;
-      }
-
-      default: {
-      handle_unusual:
-        if (tag == 0) {
-          goto success;
-        }
-        DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SkipField(
-              input, tag, _internal_metadata_.mutable_unknown_fields()));
-        break;
-      }
-    }
-  }
-success:
-  // @@protoc_insertion_point(parse_success:google.protobuf.Mixin)
-  return true;
-failure:
-  // @@protoc_insertion_point(parse_failure:google.protobuf.Mixin)
-  return false;
-#undef DO_
-}
-#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 
 ::PROTOBUF_NAMESPACE_ID::uint8* Mixin::InternalSerializeWithCachedSizesToArray(
     ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {

+ 142 - 40
src/google/protobuf/api.pb.h

@@ -145,12 +145,7 @@ class PROTOBUF_EXPORT Api :
   bool IsInitialized() const final;
 
   size_t ByteSizeLong() const final;
-  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
   const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
-  #else
-  bool MergePartialFromCodedStream(
-      ::PROTOBUF_NAMESPACE_ID::io::CodedInputStream* input) final;
-  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
   ::PROTOBUF_NAMESPACE_ID::uint8* InternalSerializeWithCachedSizesToArray(
       ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
   int GetCachedSize() const final { return _cached_size_.Get(); }
@@ -197,10 +192,17 @@ class PROTOBUF_EXPORT Api :
   };
   // repeated .google.protobuf.Method methods = 2;
   int methods_size() const;
+  private:
+  int _internal_methods_size() const;
+  public:
   void clear_methods();
   PROTOBUF_NAMESPACE_ID::Method* mutable_methods(int index);
   ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::Method >*
       mutable_methods();
+  private:
+  const PROTOBUF_NAMESPACE_ID::Method& _internal_methods(int index) const;
+  PROTOBUF_NAMESPACE_ID::Method* _internal_add_methods();
+  public:
   const PROTOBUF_NAMESPACE_ID::Method& methods(int index) const;
   PROTOBUF_NAMESPACE_ID::Method* add_methods();
   const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::Method >&
@@ -208,10 +210,17 @@ class PROTOBUF_EXPORT Api :
 
   // repeated .google.protobuf.Option options = 3;
   int options_size() const;
+  private:
+  int _internal_options_size() const;
+  public:
   void clear_options();
   PROTOBUF_NAMESPACE_ID::Option* mutable_options(int index);
   ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::Option >*
       mutable_options();
+  private:
+  const PROTOBUF_NAMESPACE_ID::Option& _internal_options(int index) const;
+  PROTOBUF_NAMESPACE_ID::Option* _internal_add_options();
+  public:
   const PROTOBUF_NAMESPACE_ID::Option& options(int index) const;
   PROTOBUF_NAMESPACE_ID::Option* add_options();
   const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::Option >&
@@ -219,10 +228,17 @@ class PROTOBUF_EXPORT Api :
 
   // repeated .google.protobuf.Mixin mixins = 6;
   int mixins_size() const;
+  private:
+  int _internal_mixins_size() const;
+  public:
   void clear_mixins();
   PROTOBUF_NAMESPACE_ID::Mixin* mutable_mixins(int index);
   ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::Mixin >*
       mutable_mixins();
+  private:
+  const PROTOBUF_NAMESPACE_ID::Mixin& _internal_mixins(int index) const;
+  PROTOBUF_NAMESPACE_ID::Mixin* _internal_add_mixins();
+  public:
   const PROTOBUF_NAMESPACE_ID::Mixin& mixins(int index) const;
   PROTOBUF_NAMESPACE_ID::Mixin* add_mixins();
   const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::Mixin >&
@@ -270,11 +286,19 @@ class PROTOBUF_EXPORT Api :
   PROTOBUF_NAMESPACE_ID::SourceContext* release_source_context();
   PROTOBUF_NAMESPACE_ID::SourceContext* mutable_source_context();
   void set_allocated_source_context(PROTOBUF_NAMESPACE_ID::SourceContext* source_context);
+  private:
+  const PROTOBUF_NAMESPACE_ID::SourceContext& _internal_source_context() const;
+  PROTOBUF_NAMESPACE_ID::SourceContext* _internal_mutable_source_context();
+  public:
 
   // .google.protobuf.Syntax syntax = 7;
   void clear_syntax();
   PROTOBUF_NAMESPACE_ID::Syntax syntax() const;
   void set_syntax(PROTOBUF_NAMESPACE_ID::Syntax value);
+  private:
+  PROTOBUF_NAMESPACE_ID::Syntax _internal_syntax() const;
+  void _internal_set_syntax(PROTOBUF_NAMESPACE_ID::Syntax value);
+  public:
 
   // @@protoc_insertion_point(class_scope:google.protobuf.Api)
  private:
@@ -362,12 +386,7 @@ class PROTOBUF_EXPORT Method :
   bool IsInitialized() const final;
 
   size_t ByteSizeLong() const final;
-  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
   const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
-  #else
-  bool MergePartialFromCodedStream(
-      ::PROTOBUF_NAMESPACE_ID::io::CodedInputStream* input) final;
-  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
   ::PROTOBUF_NAMESPACE_ID::uint8* InternalSerializeWithCachedSizesToArray(
       ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
   int GetCachedSize() const final { return _cached_size_.Get(); }
@@ -414,10 +433,17 @@ class PROTOBUF_EXPORT Method :
   };
   // repeated .google.protobuf.Option options = 6;
   int options_size() const;
+  private:
+  int _internal_options_size() const;
+  public:
   void clear_options();
   PROTOBUF_NAMESPACE_ID::Option* mutable_options(int index);
   ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::Option >*
       mutable_options();
+  private:
+  const PROTOBUF_NAMESPACE_ID::Option& _internal_options(int index) const;
+  PROTOBUF_NAMESPACE_ID::Option* _internal_add_options();
+  public:
   const PROTOBUF_NAMESPACE_ID::Option& options(int index) const;
   PROTOBUF_NAMESPACE_ID::Option* add_options();
   const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::Option >&
@@ -475,16 +501,28 @@ class PROTOBUF_EXPORT Method :
   void clear_request_streaming();
   bool request_streaming() const;
   void set_request_streaming(bool value);
+  private:
+  bool _internal_request_streaming() const;
+  void _internal_set_request_streaming(bool value);
+  public:
 
   // bool response_streaming = 5;
   void clear_response_streaming();
   bool response_streaming() const;
   void set_response_streaming(bool value);
+  private:
+  bool _internal_response_streaming() const;
+  void _internal_set_response_streaming(bool value);
+  public:
 
   // .google.protobuf.Syntax syntax = 7;
   void clear_syntax();
   PROTOBUF_NAMESPACE_ID::Syntax syntax() const;
   void set_syntax(PROTOBUF_NAMESPACE_ID::Syntax value);
+  private:
+  PROTOBUF_NAMESPACE_ID::Syntax _internal_syntax() const;
+  void _internal_set_syntax(PROTOBUF_NAMESPACE_ID::Syntax value);
+  public:
 
   // @@protoc_insertion_point(class_scope:google.protobuf.Method)
  private:
@@ -572,12 +610,7 @@ class PROTOBUF_EXPORT Mixin :
   bool IsInitialized() const final;
 
   size_t ByteSizeLong() const final;
-  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
   const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
-  #else
-  bool MergePartialFromCodedStream(
-      ::PROTOBUF_NAMESPACE_ID::io::CodedInputStream* input) final;
-  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
   ::PROTOBUF_NAMESPACE_ID::uint8* InternalSerializeWithCachedSizesToArray(
       ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
   int GetCachedSize() const final { return _cached_size_.Get(); }
@@ -731,9 +764,12 @@ inline void Api::set_allocated_name(std::string* name) {
 }
 
 // repeated .google.protobuf.Method methods = 2;
-inline int Api::methods_size() const {
+inline int Api::_internal_methods_size() const {
   return methods_.size();
 }
+inline int Api::methods_size() const {
+  return _internal_methods_size();
+}
 inline void Api::clear_methods() {
   methods_.Clear();
 }
@@ -746,13 +782,19 @@ Api::mutable_methods() {
   // @@protoc_insertion_point(field_mutable_list:google.protobuf.Api.methods)
   return &methods_;
 }
+inline const PROTOBUF_NAMESPACE_ID::Method& Api::_internal_methods(int index) const {
+  return methods_.Get(index);
+}
 inline const PROTOBUF_NAMESPACE_ID::Method& Api::methods(int index) const {
   // @@protoc_insertion_point(field_get:google.protobuf.Api.methods)
-  return methods_.Get(index);
+  return _internal_methods(index);
+}
+inline PROTOBUF_NAMESPACE_ID::Method* Api::_internal_add_methods() {
+  return methods_.Add();
 }
 inline PROTOBUF_NAMESPACE_ID::Method* Api::add_methods() {
   // @@protoc_insertion_point(field_add:google.protobuf.Api.methods)
-  return methods_.Add();
+  return _internal_add_methods();
 }
 inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::Method >&
 Api::methods() const {
@@ -761,9 +803,12 @@ Api::methods() const {
 }
 
 // repeated .google.protobuf.Option options = 3;
-inline int Api::options_size() const {
+inline int Api::_internal_options_size() const {
   return options_.size();
 }
+inline int Api::options_size() const {
+  return _internal_options_size();
+}
 inline PROTOBUF_NAMESPACE_ID::Option* Api::mutable_options(int index) {
   // @@protoc_insertion_point(field_mutable:google.protobuf.Api.options)
   return options_.Mutable(index);
@@ -773,13 +818,19 @@ Api::mutable_options() {
   // @@protoc_insertion_point(field_mutable_list:google.protobuf.Api.options)
   return &options_;
 }
+inline const PROTOBUF_NAMESPACE_ID::Option& Api::_internal_options(int index) const {
+  return options_.Get(index);
+}
 inline const PROTOBUF_NAMESPACE_ID::Option& Api::options(int index) const {
   // @@protoc_insertion_point(field_get:google.protobuf.Api.options)
-  return options_.Get(index);
+  return _internal_options(index);
+}
+inline PROTOBUF_NAMESPACE_ID::Option* Api::_internal_add_options() {
+  return options_.Add();
 }
 inline PROTOBUF_NAMESPACE_ID::Option* Api::add_options() {
   // @@protoc_insertion_point(field_add:google.protobuf.Api.options)
-  return options_.Add();
+  return _internal_add_options();
 }
 inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::Option >&
 Api::options() const {
@@ -848,15 +899,21 @@ inline void Api::set_allocated_version(std::string* version) {
 }
 
 // .google.protobuf.SourceContext source_context = 5;
-inline bool Api::has_source_context() const {
+inline bool Api::_internal_has_source_context() const {
   return this != internal_default_instance() && source_context_ != nullptr;
 }
-inline const PROTOBUF_NAMESPACE_ID::SourceContext& Api::source_context() const {
+inline bool Api::has_source_context() const {
+  return _internal_has_source_context();
+}
+inline const PROTOBUF_NAMESPACE_ID::SourceContext& Api::_internal_source_context() const {
   const PROTOBUF_NAMESPACE_ID::SourceContext* p = source_context_;
-  // @@protoc_insertion_point(field_get:google.protobuf.Api.source_context)
   return p != nullptr ? *p : *reinterpret_cast<const PROTOBUF_NAMESPACE_ID::SourceContext*>(
       &PROTOBUF_NAMESPACE_ID::_SourceContext_default_instance_);
 }
+inline const PROTOBUF_NAMESPACE_ID::SourceContext& Api::source_context() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Api.source_context)
+  return _internal_source_context();
+}
 inline PROTOBUF_NAMESPACE_ID::SourceContext* Api::release_source_context() {
   // @@protoc_insertion_point(field_release:google.protobuf.Api.source_context)
   
@@ -864,15 +921,18 @@ inline PROTOBUF_NAMESPACE_ID::SourceContext* Api::release_source_context() {
   source_context_ = nullptr;
   return temp;
 }
-inline PROTOBUF_NAMESPACE_ID::SourceContext* Api::mutable_source_context() {
+inline PROTOBUF_NAMESPACE_ID::SourceContext* Api::_internal_mutable_source_context() {
   
   if (source_context_ == nullptr) {
     auto* p = CreateMaybeMessage<PROTOBUF_NAMESPACE_ID::SourceContext>(GetArenaNoVirtual());
     source_context_ = p;
   }
-  // @@protoc_insertion_point(field_mutable:google.protobuf.Api.source_context)
   return source_context_;
 }
+inline PROTOBUF_NAMESPACE_ID::SourceContext* Api::mutable_source_context() {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.Api.source_context)
+  return _internal_mutable_source_context();
+}
 inline void Api::set_allocated_source_context(PROTOBUF_NAMESPACE_ID::SourceContext* source_context) {
   ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArenaNoVirtual();
   if (message_arena == nullptr) {
@@ -893,9 +953,12 @@ inline void Api::set_allocated_source_context(PROTOBUF_NAMESPACE_ID::SourceConte
 }
 
 // repeated .google.protobuf.Mixin mixins = 6;
-inline int Api::mixins_size() const {
+inline int Api::_internal_mixins_size() const {
   return mixins_.size();
 }
+inline int Api::mixins_size() const {
+  return _internal_mixins_size();
+}
 inline void Api::clear_mixins() {
   mixins_.Clear();
 }
@@ -908,13 +971,19 @@ Api::mutable_mixins() {
   // @@protoc_insertion_point(field_mutable_list:google.protobuf.Api.mixins)
   return &mixins_;
 }
+inline const PROTOBUF_NAMESPACE_ID::Mixin& Api::_internal_mixins(int index) const {
+  return mixins_.Get(index);
+}
 inline const PROTOBUF_NAMESPACE_ID::Mixin& Api::mixins(int index) const {
   // @@protoc_insertion_point(field_get:google.protobuf.Api.mixins)
-  return mixins_.Get(index);
+  return _internal_mixins(index);
+}
+inline PROTOBUF_NAMESPACE_ID::Mixin* Api::_internal_add_mixins() {
+  return mixins_.Add();
 }
 inline PROTOBUF_NAMESPACE_ID::Mixin* Api::add_mixins() {
   // @@protoc_insertion_point(field_add:google.protobuf.Api.mixins)
-  return mixins_.Add();
+  return _internal_add_mixins();
 }
 inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::Mixin >&
 Api::mixins() const {
@@ -926,13 +995,19 @@ Api::mixins() const {
 inline void Api::clear_syntax() {
   syntax_ = 0;
 }
+inline PROTOBUF_NAMESPACE_ID::Syntax Api::_internal_syntax() const {
+  return static_cast< PROTOBUF_NAMESPACE_ID::Syntax >(syntax_);
+}
 inline PROTOBUF_NAMESPACE_ID::Syntax Api::syntax() const {
   // @@protoc_insertion_point(field_get:google.protobuf.Api.syntax)
-  return static_cast< PROTOBUF_NAMESPACE_ID::Syntax >(syntax_);
+  return _internal_syntax();
 }
-inline void Api::set_syntax(PROTOBUF_NAMESPACE_ID::Syntax value) {
+inline void Api::_internal_set_syntax(PROTOBUF_NAMESPACE_ID::Syntax value) {
   
   syntax_ = value;
+}
+inline void Api::set_syntax(PROTOBUF_NAMESPACE_ID::Syntax value) {
+  _internal_set_syntax(value);
   // @@protoc_insertion_point(field_set:google.protobuf.Api.syntax)
 }
 
@@ -1064,13 +1139,19 @@ inline void Method::set_allocated_request_type_url(std::string* request_type_url
 inline void Method::clear_request_streaming() {
   request_streaming_ = false;
 }
+inline bool Method::_internal_request_streaming() const {
+  return request_streaming_;
+}
 inline bool Method::request_streaming() const {
   // @@protoc_insertion_point(field_get:google.protobuf.Method.request_streaming)
-  return request_streaming_;
+  return _internal_request_streaming();
 }
-inline void Method::set_request_streaming(bool value) {
+inline void Method::_internal_set_request_streaming(bool value) {
   
   request_streaming_ = value;
+}
+inline void Method::set_request_streaming(bool value) {
+  _internal_set_request_streaming(value);
   // @@protoc_insertion_point(field_set:google.protobuf.Method.request_streaming)
 }
 
@@ -1138,20 +1219,29 @@ inline void Method::set_allocated_response_type_url(std::string* response_type_u
 inline void Method::clear_response_streaming() {
   response_streaming_ = false;
 }
+inline bool Method::_internal_response_streaming() const {
+  return response_streaming_;
+}
 inline bool Method::response_streaming() const {
   // @@protoc_insertion_point(field_get:google.protobuf.Method.response_streaming)
-  return response_streaming_;
+  return _internal_response_streaming();
 }
-inline void Method::set_response_streaming(bool value) {
+inline void Method::_internal_set_response_streaming(bool value) {
   
   response_streaming_ = value;
+}
+inline void Method::set_response_streaming(bool value) {
+  _internal_set_response_streaming(value);
   // @@protoc_insertion_point(field_set:google.protobuf.Method.response_streaming)
 }
 
 // repeated .google.protobuf.Option options = 6;
-inline int Method::options_size() const {
+inline int Method::_internal_options_size() const {
   return options_.size();
 }
+inline int Method::options_size() const {
+  return _internal_options_size();
+}
 inline PROTOBUF_NAMESPACE_ID::Option* Method::mutable_options(int index) {
   // @@protoc_insertion_point(field_mutable:google.protobuf.Method.options)
   return options_.Mutable(index);
@@ -1161,13 +1251,19 @@ Method::mutable_options() {
   // @@protoc_insertion_point(field_mutable_list:google.protobuf.Method.options)
   return &options_;
 }
+inline const PROTOBUF_NAMESPACE_ID::Option& Method::_internal_options(int index) const {
+  return options_.Get(index);
+}
 inline const PROTOBUF_NAMESPACE_ID::Option& Method::options(int index) const {
   // @@protoc_insertion_point(field_get:google.protobuf.Method.options)
-  return options_.Get(index);
+  return _internal_options(index);
+}
+inline PROTOBUF_NAMESPACE_ID::Option* Method::_internal_add_options() {
+  return options_.Add();
 }
 inline PROTOBUF_NAMESPACE_ID::Option* Method::add_options() {
   // @@protoc_insertion_point(field_add:google.protobuf.Method.options)
-  return options_.Add();
+  return _internal_add_options();
 }
 inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::Option >&
 Method::options() const {
@@ -1179,13 +1275,19 @@ Method::options() const {
 inline void Method::clear_syntax() {
   syntax_ = 0;
 }
+inline PROTOBUF_NAMESPACE_ID::Syntax Method::_internal_syntax() const {
+  return static_cast< PROTOBUF_NAMESPACE_ID::Syntax >(syntax_);
+}
 inline PROTOBUF_NAMESPACE_ID::Syntax Method::syntax() const {
   // @@protoc_insertion_point(field_get:google.protobuf.Method.syntax)
-  return static_cast< PROTOBUF_NAMESPACE_ID::Syntax >(syntax_);
+  return _internal_syntax();
 }
-inline void Method::set_syntax(PROTOBUF_NAMESPACE_ID::Syntax value) {
+inline void Method::_internal_set_syntax(PROTOBUF_NAMESPACE_ID::Syntax value) {
   
   syntax_ = value;
+}
+inline void Method::set_syntax(PROTOBUF_NAMESPACE_ID::Syntax value) {
+  _internal_set_syntax(value);
   // @@protoc_insertion_point(field_set:google.protobuf.Method.syntax)
 }
 

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

@@ -690,7 +690,7 @@ class PROTOBUF_EXPORT alignas(8) Arena final {
                                         !has_get_arena<T>::value,
                                     int>::type = 0>
   PROTOBUF_ALWAYS_INLINE static Arena* GetArenaInternal(const T* value) {
-    (void) value;
+    (void)value;
     return nullptr;
   }
 

+ 21 - 13
src/google/protobuf/compiler/command_line_interface.cc

@@ -413,7 +413,9 @@ class CommandLineInterface::MemoryOutputStream
   // implements ZeroCopyOutputStream ---------------------------------
   virtual bool Next(void** data, int* size) { return inner_->Next(data, size); }
   virtual void BackUp(int count) { inner_->BackUp(count); }
-  virtual int64 ByteCount() const { return inner_->ByteCount(); }
+  virtual int64 ByteCount() const {
+    return inner_->ByteCount();
+  }
 
  private:
   // Checks to see if "filename_.meta" exists in directory_; if so, fixes the
@@ -1062,15 +1064,19 @@ bool CommandLineInterface::ParseInputFiles(
     DescriptorPool* descriptor_pool,
     std::vector<const FileDescriptor*>* parsed_files) {
 
+  // Track unused imports in all source files
+  for (const auto& input_file : input_files_) {
+    descriptor_pool->AddUnusedImportTrackFile(input_file);
+  }
+  bool result = true;
   // Parse each file.
   for (const auto& input_file : input_files_) {
     // Import the file.
-    descriptor_pool->AddUnusedImportTrackFile(input_file);
     const FileDescriptor* parsed_file =
         descriptor_pool->FindFileByName(input_file);
-    descriptor_pool->ClearUnusedImportTrackFiles();
     if (parsed_file == NULL) {
-      return false;
+      result = false;
+      break;
     }
     parsed_files->push_back(parsed_file);
 
@@ -1080,7 +1086,8 @@ bool CommandLineInterface::ParseInputFiles(
                 << ": This file contains services, but "
                    "--disallow_services was used."
                 << std::endl;
-      return false;
+      result = false;
+      break;
     }
 
     // Enforce --direct_dependencies
@@ -1098,11 +1105,13 @@ bool CommandLineInterface::ParseInputFiles(
         }
       }
       if (indirect_imports) {
-        return false;
+        result = false;
+        break;
       }
     }
   }
-  return true;
+  descriptor_pool->ClearUnusedImportTrackFiles();
+  return result;
 }
 
 void CommandLineInterface::Clear() {
@@ -1431,13 +1440,12 @@ CommandLineInterface::InterpretArgument(const std::string& name,
     // On Windows, the shell (typically cmd.exe) does not expand wildcards in
     // file names (e.g. foo\*.proto), so we do it ourselves.
     switch (google::protobuf::io::win32::ExpandWildcards(
-          value,
-          [this](const string& path) {
-            this->input_files_.push_back(path);
-          })) {
+        value,
+        [this](const string& path) { this->input_files_.push_back(path); })) {
       case google::protobuf::io::win32::ExpandWildcardsResult::kSuccess:
         break;
-      case google::protobuf::io::win32::ExpandWildcardsResult::kErrorNoMatchingFile:
+      case google::protobuf::io::win32::ExpandWildcardsResult::
+          kErrorNoMatchingFile:
         // Path does not exist, is not a file, or it's longer than MAX_PATH and
         // long path handling is disabled.
         std::cerr << "Invalid file name pattern or missing input file \""
@@ -1448,7 +1456,7 @@ CommandLineInterface::InterpretArgument(const std::string& name,
                   << "\" to or from Windows style" << std::endl;
         return PARSE_ARGUMENT_FAIL;
     }
-#else  // not _WIN32
+#else   // not _WIN32
     // On other platforms than Windows (e.g. Linux, Mac OS) the shell (typically
     // Bash) expands wildcards.
     input_files_.push_back(value);

+ 74 - 1
src/google/protobuf/compiler/command_line_interface_unittest.cc

@@ -56,9 +56,9 @@
 #include <google/protobuf/io/zero_copy_stream.h>
 #include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/descriptor.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/io/io_win32.h>
 
 #include <google/protobuf/stubs/strutil.h>
@@ -142,6 +142,10 @@ class CommandLineInterfaceTest : public testing::Test {
   // substring.
   void ExpectErrorSubstring(const std::string& expected_substring);
 
+  // Checks that Run() returned zero and the stderr contains the given
+  // substring.
+  void ExpectWarningSubstring(const std::string& expected_substring);
+
   // Checks that the captured stdout is the same as the expected_text.
   void ExpectCapturedStdout(const std::string& expected_text);
 
@@ -406,6 +410,12 @@ void CommandLineInterfaceTest::ExpectErrorSubstring(
   EXPECT_PRED_FORMAT2(testing::IsSubstring, expected_substring, error_text_);
 }
 
+void CommandLineInterfaceTest::ExpectWarningSubstring(
+    const std::string& expected_substring) {
+  EXPECT_EQ(0, return_code_);
+  EXPECT_PRED_FORMAT2(testing::IsSubstring, expected_substring, error_text_);
+}
+
 #if defined(_WIN32) && !defined(__CYGWIN__)
 bool CommandLineInterfaceTest::HasAlternateErrorSubstring(
     const std::string& expected_substring) {
@@ -835,6 +845,69 @@ TEST_F(CommandLineInterfaceTest,
   ExpectErrorSubstring("bar.proto: \"Baz\" is not defined.");
 }
 
+TEST_F(CommandLineInterfaceTest,
+       OnlyReportsUnusedImportsForFilesBeingGenerated) {
+  CreateTempFile("unused.proto",
+                 "syntax = \"proto2\";\n"
+                 "message Unused {}\n");
+  CreateTempFile("bar.proto",
+                 "syntax = \"proto2\";\n"
+                 "import \"unused.proto\";\n"
+                 "message Bar {}\n");
+  CreateTempFile("foo.proto",
+                 "syntax = \"proto2\";\n"
+                 "import \"bar.proto\";\n"
+                 "message Foo {\n"
+                 "  optional Bar bar = 1;\n"
+                 "}\n");
+
+  Run("protocol_compiler --test_out=$tmpdir "
+      "--proto_path=$tmpdir foo.proto");
+  ExpectNoErrors();
+}
+
+TEST_F(CommandLineInterfaceTest, ReportsTransitiveMisingImports_LeafFirst) {
+  CreateTempFile("unused.proto",
+                 "syntax = \"proto2\";\n"
+                 "message Unused {}\n");
+  CreateTempFile("bar.proto",
+                 "syntax = \"proto2\";\n"
+                 "import \"unused.proto\";\n"
+                 "message Bar {}\n");
+  CreateTempFile("foo.proto",
+                 "syntax = \"proto2\";\n"
+                 "import \"bar.proto\";\n"
+                 "message Foo {\n"
+                 "  optional Bar bar = 1;\n"
+                 "}\n");
+
+  Run("protocol_compiler --test_out=$tmpdir "
+      "--proto_path=$tmpdir bar.proto foo.proto");
+  ExpectWarningSubstring(
+      "bar.proto:2:1: warning: Import unused.proto but not used.");
+}
+
+TEST_F(CommandLineInterfaceTest, ReportsTransitiveMisingImports_LeafLast) {
+  CreateTempFile("unused.proto",
+                 "syntax = \"proto2\";\n"
+                 "message Unused {}\n");
+  CreateTempFile("bar.proto",
+                 "syntax = \"proto2\";\n"
+                 "import \"unused.proto\";\n"
+                 "message Bar {}\n");
+  CreateTempFile("foo.proto",
+                 "syntax = \"proto2\";\n"
+                 "import \"bar.proto\";\n"
+                 "message Foo {\n"
+                 "  optional Bar bar = 1;\n"
+                 "}\n");
+
+  Run("protocol_compiler --test_out=$tmpdir "
+      "--proto_path=$tmpdir foo.proto bar.proto");
+  ExpectWarningSubstring(
+      "bar.proto:2:1: warning: Import unused.proto but not used.");
+}
+
 TEST_F(CommandLineInterfaceTest, CreateDirectory) {
   // Test that when we output to a sub-directory, it is created.
 

+ 10 - 11
src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc

@@ -44,6 +44,8 @@
 
 #include <map>
 
+#include <google/protobuf/testing/file.h>
+#include <google/protobuf/testing/file.h>
 #include <google/protobuf/compiler/cpp/cpp_helpers.h>
 #include <google/protobuf/compiler/cpp/cpp_generator.h>
 #include <google/protobuf/compiler/importer.h>
@@ -51,15 +53,12 @@
 #include <google/protobuf/io/zero_copy_stream_impl.h>
 #include <google/protobuf/descriptor.h>
 #include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
 #include <google/protobuf/stubs/substitute.h>
 #include <google/protobuf/stubs/map_util.h>
 #include <google/protobuf/stubs/stl_util.h>
 
-#include <google/protobuf/testing/file.h>
-#include <google/protobuf/testing/file.h>
-#include <google/protobuf/testing/googletest.h>
-#include <gtest/gtest.h>
-
 namespace google {
 namespace protobuf {
 namespace compiler {
@@ -178,16 +177,16 @@ TEST(BootstrapTest, GeneratedFilesMatch) {
   }
 }
 
-//test Generate in cpp_generator.cc
-TEST(BootstrapTest, OptionNotExist)
-{
+// test Generate in cpp_generator.cc
+TEST(BootstrapTest, OptionNotExist) {
   cpp::CppGenerator generator;
   DescriptorPool pool;
-  GeneratorContext *generator_context = nullptr;
+  GeneratorContext* generator_context = nullptr;
   std::string parameter = "aaa";
   string error;
-  ASSERT_FALSE(generator.Generate(pool.FindFileByName("google/protobuf/descriptor.proto"),
-                                  parameter, generator_context, &error));
+  ASSERT_FALSE(generator.Generate(
+      pool.FindFileByName("google/protobuf/descriptor.proto"), parameter,
+      generator_context, &error));
   EXPECT_EQ(error, "Unknown generator option: " + parameter);
 }
 

+ 61 - 57
src/google/protobuf/compiler/cpp/cpp_enum_field.cc

@@ -77,7 +77,11 @@ void EnumFieldGenerator::GenerateAccessorDeclarations(
   Formatter format(printer, variables_);
   format(
       "$deprecated_attr$$type$ ${1$$name$$}$() const;\n"
-      "$deprecated_attr$void ${1$set_$name$$}$($type$ value);\n",
+      "$deprecated_attr$void ${1$set_$name$$}$($type$ value);\n"
+      "private:\n"
+      "$type$ ${1$_internal_$name$$}$() const;\n"
+      "void ${1$_internal_set_$name$$}$($type$ value);\n"
+      "public:\n",
       descriptor_);
 }
 
@@ -85,19 +89,25 @@ void EnumFieldGenerator::GenerateInlineAccessorDefinitions(
     io::Printer* printer) const {
   Formatter format(printer, variables_);
   format(
+      "inline $type$ $classname$::_internal_$name$() const {\n"
+      "  return static_cast< $type$ >($name$_);\n"
+      "}\n"
       "inline $type$ $classname$::$name$() const {\n"
       "$annotate_accessor$"
       "  // @@protoc_insertion_point(field_get:$full_name$)\n"
-      "  return static_cast< $type$ >($name$_);\n"
+      "  return _internal_$name$();\n"
       "}\n"
-      "inline void $classname$::set_$name$($type$ value) {\n"
-      "$annotate_accessor$");
+      "inline void $classname$::_internal_set_$name$($type$ value) {\n");
   if (!HasPreservingUnknownEnumSemantics(descriptor_)) {
     format("  assert($type$_IsValid(value));\n");
   }
   format(
       "  $set_hasbit$\n"
       "  $name$_ = value;\n"
+      "}\n"
+      "inline void $classname$::set_$name$($type$ value) {\n"
+      "$annotate_accessor$"
+      "  _internal_set_$name$(value);\n"
       "  // @@protoc_insertion_point(field_set:$full_name$)\n"
       "}\n");
 }
@@ -109,7 +119,7 @@ void EnumFieldGenerator::GenerateClearingCode(io::Printer* printer) const {
 
 void EnumFieldGenerator::GenerateMergingCode(io::Printer* printer) const {
   Formatter format(printer, variables_);
-  format("set_$name$(from.$name$());\n");
+  format("_internal_set_$name$(from._internal_$name$());\n");
 }
 
 void EnumFieldGenerator::GenerateSwappingCode(io::Printer* printer) const {
@@ -128,51 +138,22 @@ void EnumFieldGenerator::GenerateCopyConstructorCode(
   format("$name$_ = from.$name$_;\n");
 }
 
-void EnumFieldGenerator::GenerateMergeFromCodedStream(
-    io::Printer* printer) const {
-  Formatter format(printer, variables_);
-  format(
-      "int value = 0;\n"
-      "DO_((::$proto_ns$::internal::WireFormatLite::ReadPrimitive<\n"
-      "         int, ::$proto_ns$::internal::WireFormatLite::TYPE_ENUM>(\n"
-      "       input, &value)));\n");
-  if (HasPreservingUnknownEnumSemantics(descriptor_)) {
-    format("set_$name$(static_cast< $type$ >(value));\n");
-  } else {
-    format(
-        "if ($type$_IsValid(value)) {\n"
-        "  set_$name$(static_cast< $type$ >(value));\n");
-    if (UseUnknownFieldSet(descriptor_->file(), options_)) {
-      format(
-          "} else {\n"
-          "  mutable_unknown_fields()->AddVarint(\n"
-          "      $number$, static_cast<$uint64$>(value));\n");
-    } else {
-      format(
-          "} else {\n"
-          "  unknown_fields_stream.WriteVarint32($1$u);\n"
-          "  unknown_fields_stream.WriteVarint32(\n"
-          "      static_cast<$uint32$>(value));\n",
-          internal::WireFormat::MakeTag(descriptor_));
-    }
-    format("}\n");
-  }
-}
-
 void EnumFieldGenerator::GenerateSerializeWithCachedSizesToArray(
     io::Printer* printer) const {
   Formatter format(printer, variables_);
   format(
       "stream->EnsureSpace(&target);\n"
       "target = ::$proto_ns$::internal::WireFormatLite::WriteEnumToArray(\n"
-      "  $number$, this->$name$(), target);\n");
+      "  $number$, this->_internal_$name$(), target);\n");
 }
 
 void EnumFieldGenerator::GenerateByteSize(io::Printer* printer) const {
   Formatter format(printer, variables_);
   format(
       "total_size += $tag_size$ +\n"
-      "  ::$proto_ns$::internal::WireFormatLite::EnumSize(this->$name$());\n");
+      "  "
+      "::$proto_ns$::internal::WireFormatLite::EnumSize(this->_internal_$name$("
+      "));\n");
 }
 
 // ===================================================================
@@ -189,26 +170,32 @@ void EnumOneofFieldGenerator::GenerateInlineAccessorDefinitions(
     io::Printer* printer) const {
   Formatter format(printer, variables_);
   format(
-      "inline $type$ $classname$::$name$() const {\n"
-      "$annotate_accessor$"
-      "  // @@protoc_insertion_point(field_get:$full_name$)\n"
-      "  if (has_$name$()) {\n"
+      "inline $type$ $classname$::_internal_$name$() const {\n"
+      "  if (_internal_has_$name$()) {\n"
       "    return static_cast< $type$ >($field_member$);\n"
       "  }\n"
       "  return static_cast< $type$ >($default$);\n"
       "}\n"
-      "inline void $classname$::set_$name$($type$ value) {\n"
-      "$annotate_accessor$");
+      "inline $type$ $classname$::$name$() const {\n"
+      "$annotate_accessor$"
+      "  // @@protoc_insertion_point(field_get:$full_name$)\n"
+      "  return _internal_$name$();\n"
+      "}\n"
+      "inline void $classname$::_internal_set_$name$($type$ value) {\n");
   if (!HasPreservingUnknownEnumSemantics(descriptor_)) {
     format("  assert($type$_IsValid(value));\n");
   }
   format(
-      "  if (!has_$name$()) {\n"
+      "  if (!_internal_has_$name$()) {\n"
       "    clear_$oneof_name$();\n"
       "    set_has_$name$();\n"
       "  }\n"
       "  $field_member$ = value;\n"
+      "}\n"
+      "inline void $classname$::set_$name$($type$ value) {\n"
+      "$annotate_accessor$"
       "  // @@protoc_insertion_point(field_set:$full_name$)\n"
+      "  _internal_set_$name$(value);\n"
       "}\n");
 }
 
@@ -251,6 +238,12 @@ void RepeatedEnumFieldGenerator::GenerateAccessorDeclarations(
     io::Printer* printer) const {
   Formatter format(printer, variables_);
   format(
+      "private:\n"
+      "$type$ ${1$_internal_$name$$}$(int index) const;\n"
+      "void ${1$_internal_add_$name$$}$($type$ value);\n"
+      "::$proto_ns$::RepeatedField<int>* "
+      "${1$_internal_mutable_$name$$}$();\n"
+      "public:\n"
       "$deprecated_attr$$type$ ${1$$name$$}$(int index) const;\n"
       "$deprecated_attr$void ${1$set_$name$$}$(int index, $type$ value);\n"
       "$deprecated_attr$void ${1$add_$name$$}$($type$ value);\n"
@@ -265,10 +258,13 @@ void RepeatedEnumFieldGenerator::GenerateInlineAccessorDefinitions(
     io::Printer* printer) const {
   Formatter format(printer, variables_);
   format(
+      "inline $type$ $classname$::_internal_$name$(int index) const {\n"
+      "  return static_cast< $type$ >($name$_.Get(index));\n"
+      "}\n"
       "inline $type$ $classname$::$name$(int index) const {\n"
       "$annotate_accessor$"
       "  // @@protoc_insertion_point(field_get:$full_name$)\n"
-      "  return static_cast< $type$ >($name$_.Get(index));\n"
+      "  return _internal_$name$(index);\n"
       "}\n"
       "inline void $classname$::set_$name$(int index, $type$ value) {\n"
       "$annotate_accessor$");
@@ -279,14 +275,17 @@ void RepeatedEnumFieldGenerator::GenerateInlineAccessorDefinitions(
       "  $name$_.Set(index, value);\n"
       "  // @@protoc_insertion_point(field_set:$full_name$)\n"
       "}\n"
-      "inline void $classname$::add_$name$($type$ value) {\n"
-      "$annotate_accessor$");
+      "inline void $classname$::_internal_add_$name$($type$ value) {\n");
   if (!HasPreservingUnknownEnumSemantics(descriptor_)) {
     format("  assert($type$_IsValid(value));\n");
   }
   format(
       "  $name$_.Add(value);\n"
+      "}\n"
+      "inline void $classname$::add_$name$($type$ value) {\n"
+      "$annotate_accessor$"
       "  // @@protoc_insertion_point(field_add:$full_name$)\n"
+      "  _internal_add_$name$(value);\n"
       "}\n"
       "inline const ::$proto_ns$::RepeatedField<int>&\n"
       "$classname$::$name$() const {\n"
@@ -295,10 +294,14 @@ void RepeatedEnumFieldGenerator::GenerateInlineAccessorDefinitions(
       "  return $name$_;\n"
       "}\n"
       "inline ::$proto_ns$::RepeatedField<int>*\n"
+      "$classname$::_internal_mutable_$name$() {\n"
+      "  return &$name$_;\n"
+      "}\n"
+      "inline ::$proto_ns$::RepeatedField<int>*\n"
       "$classname$::mutable_$name$() {\n"
       "$annotate_accessor$"
       "  // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
-      "  return &$name$_;\n"
+      "  return _internal_mutable_$name$();\n"
       "}\n");
 }
 
@@ -369,7 +372,7 @@ void RepeatedEnumFieldGenerator::GenerateMergeFromCodedStreamWithPacking(
           "       $number$,\n"
           "       nullptr,\n"
           "       nullptr,\n"
-          "       this->mutable_$name$())));\n");
+          "       this->_internal_mutable_$name$())));\n");
     } else if (UseUnknownFieldSet(descriptor_->file(), options_)) {
       format(
           "DO_((::$proto_ns$::internal::WireFormat::"
@@ -378,7 +381,7 @@ void RepeatedEnumFieldGenerator::GenerateMergeFromCodedStreamWithPacking(
           "       $number$,\n"
           "       $type$_IsValid,\n"
           "       mutable_unknown_fields(),\n"
-          "       this->mutable_$name$())));\n");
+          "       this->_internal_mutable_$name$())));\n");
     } else {
       format(
           "DO_((::$proto_ns$::internal::"
@@ -387,7 +390,7 @@ void RepeatedEnumFieldGenerator::GenerateMergeFromCodedStreamWithPacking(
           "       $number$,\n"
           "       $type$_IsValid,\n"
           "       &unknown_fields_stream,\n"
-          "       this->mutable_$name$())));\n");
+          "       this->_internal_mutable_$name$())));\n");
     }
   } else {
     format(
@@ -405,7 +408,7 @@ void RepeatedEnumFieldGenerator::GenerateMergeFromCodedStreamWithPacking(
     } else {
       format(
           "  if ($type$_IsValid(value)) {\n"
-          "    add_$name$(static_cast< $type$ >(value));\n"
+          "    _internal_add_$name$(static_cast< $type$ >(value));\n"
           "  } else {\n");
       if (UseUnknownFieldSet(descriptor_->file(), options_)) {
         format(
@@ -441,10 +444,10 @@ void RepeatedEnumFieldGenerator::GenerateSerializeWithCachedSizesToArray(
         "}\n");
   } else {
     format(
-        "for (const auto& x : this->$name$()) {\n"
+        "for (int i = 0, n = this->_internal_$name$_size(); i < n; i++) {\n"
         "  stream->EnsureSpace(&target);\n"
         "  target = ::$proto_ns$::internal::WireFormatLite::WriteEnumToArray(\n"
-        "      $number$, x, target);\n"
+        "      $number$, this->_internal_$name$(i), target);\n"
         "}\n");
   }
 }
@@ -454,12 +457,13 @@ void RepeatedEnumFieldGenerator::GenerateByteSize(io::Printer* printer) const {
   format(
       "{\n"
       "  size_t data_size = 0;\n"
-      "  unsigned int count = static_cast<unsigned int>(this->$name$_size());");
+      "  unsigned int count = static_cast<unsigned "
+      "int>(this->_internal_$name$_size());");
   format.Indent();
   format(
       "for (unsigned int i = 0; i < count; i++) {\n"
       "  data_size += ::$proto_ns$::internal::WireFormatLite::EnumSize(\n"
-      "    this->$name$(static_cast<int>(i)));\n"
+      "    this->_internal_$name$(static_cast<int>(i)));\n"
       "}\n");
 
   if (descriptor_->is_packed()) {

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

@@ -58,7 +58,6 @@ class EnumFieldGenerator : public FieldGenerator {
   void GenerateSwappingCode(io::Printer* printer) const;
   void GenerateConstructorCode(io::Printer* printer) const;
   void GenerateCopyConstructorCode(io::Printer* printer) const;
-  void GenerateMergeFromCodedStream(io::Printer* printer) const;
   void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
   void GenerateByteSize(io::Printer* printer) const;
 

+ 0 - 11
src/google/protobuf/compiler/cpp/cpp_field.cc

@@ -113,17 +113,6 @@ void SetCommonOneofFieldVariables(
 
 FieldGenerator::~FieldGenerator() {}
 
-void FieldGenerator::GenerateMergeFromCodedStreamWithPacking(
-    io::Printer* printer) const {
-  // Reaching here indicates a bug. Cases are:
-  //   - This FieldGenerator should support packing, but this method should be
-  //     overridden.
-  //   - This FieldGenerator doesn't support packing, and this method should
-  //     never have been called.
-  GOOGLE_LOG(FATAL) << "GenerateMergeFromCodedStreamWithPacking() "
-             << "called on field generator that does not support packing.";
-}
-
 FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor,
                                      const Options& options,
                                      MessageSCCAnalyzer* scc_analyzer)

+ 0 - 13
src/google/protobuf/compiler/cpp/cpp_field.h

@@ -168,19 +168,6 @@ class FieldGenerator {
   virtual void GenerateDefaultInstanceAllocator(
       io::Printer* /*printer*/) const {}
 
-  // Generate lines to decode this field, which will be placed inside the
-  // message's MergeFromCodedStream() method.
-  virtual void GenerateMergeFromCodedStream(io::Printer* printer) const = 0;
-
-  // Returns true if this field's "MergeFromCodedStream" code needs the arena
-  // to be defined as a variable.
-  virtual bool MergeFromCodedStreamNeedsArena() const { return false; }
-
-  // Generate lines to decode this field from a packed value, which will be
-  // placed inside the message's MergeFromCodedStream() method.
-  virtual void GenerateMergeFromCodedStreamWithPacking(
-      io::Printer* printer) const;
-
   // Generate lines to serialize this field directly to the array "target",
   // which are placed within the message's SerializeWithCachedSizesToArray()
   // method. This must also advance "target" past the written bytes.

+ 1 - 12
src/google/protobuf/compiler/cpp/cpp_file.cc

@@ -414,7 +414,7 @@ void FileGenerator::GenerateSourceIncludes(io::Printer* printer) {
   if (IsProto2MessageSetFile(file_, options_)) {
     format(
         // Implementation of proto1 MessageSet API methods.
-        "#include \"net/proto2/bridge/internal/message_set_util.h\"\n");
+        "#include \"net/proto2/internal/message_set_util.h\"\n");
   }
 
   if (options_.proto_h) {
@@ -591,10 +591,6 @@ void FileGenerator::GenerateSourceForMessage(int idx, io::Printer* printer) {
 
     // Define default instances
     GenerateSourceDefaultInstance(idx, printer);
-    if (options_.lite_implicit_weak_fields) {
-      format("void $1$_ReferenceStrong() {}\n",
-             message_generators_[idx]->classname_);
-    }
 
     // Generate classes.
     format("\n");
@@ -665,10 +661,6 @@ void FileGenerator::GenerateSource(io::Printer* printer) {
     // Define default instances
     for (int i = 0; i < message_generators_.size(); i++) {
       GenerateSourceDefaultInstance(i, printer);
-      if (options_.lite_implicit_weak_fields) {
-        format("void $1$_ReferenceStrong() {}\n",
-               message_generators_[i]->classname_);
-      }
     }
   }
 
@@ -1159,9 +1151,6 @@ class FileGenerator::ForwardDeclarations {
           "$dllexport_decl $extern $3$ $4$;\n",
           class_desc, classname, DefaultInstanceType(class_desc, options),
           DefaultInstanceName(class_desc, options));
-      if (options.lite_implicit_weak_fields) {
-        format("void $1$_ReferenceStrong();\n", classname);
-      }
     }
   }
 

+ 14 - 16
src/google/protobuf/compiler/cpp/cpp_helpers.cc

@@ -202,7 +202,7 @@ void SetIntVar(const Options& options, const std::string& type,
 }
 
 bool HasInternalAccessors(const FieldOptions::CType ctype) {
-  return ctype == FieldOptions::STRING;
+  return ctype == FieldOptions::STRING || ctype == FieldOptions::CORD;
 }
 
 }  // namespace
@@ -399,11 +399,6 @@ std::string FileDllExport(const FileDescriptor* file, const Options& options) {
   return UniqueName("PROTOBUF_INTERNAL_EXPORT", file, options);
 }
 
-std::string ReferenceFunctionName(const Descriptor* descriptor,
-                                  const Options& options) {
-  return QualifiedClassName(descriptor, options) + "_ReferenceStrong";
-}
-
 std::string SuperClassName(const Descriptor* descriptor,
                            const Options& options) {
   return "::" + ProtobufNamespace(options) +
@@ -1505,9 +1500,11 @@ class ParseLoopGenerator {
             StrCat(", ", QualifiedClassName(field->enum_type(), options_),
                          "_IsValid, &_internal_metadata_, ", field->number());
       }
-      format_("ptr = $pi_ns$::Packed$1$Parser(mutable_$2$(), ptr, ctx$3$);\n",
-              DeclaredTypeMethodName(field->type()), FieldName(field),
-              enum_validator);
+      format_(
+          "ptr = $pi_ns$::Packed$1$Parser(_internal_mutable_$2$(), ptr, "
+          "ctx$3$);\n",
+          DeclaredTypeMethodName(field->type()), FieldName(field),
+          enum_validator);
     } else {
       auto field_type = field->type();
       switch (field_type) {
@@ -1537,8 +1534,8 @@ class ParseLoopGenerator {
           } else if (IsLazy(field, options_)) {
             if (field->containing_oneof() != nullptr) {
               format_(
-                  "if (!has_$1$()) {\n"
-                  "  clear_$1$();\n"
+                  "if (!_internal_has_$1$()) {\n"
+                  "  clear_$2$();\n"
                   "  $2$_.$1$_ = ::$proto_ns$::Arena::CreateMessage<\n"
                   "      $pi_ns$::LazyField>("
                   "GetArenaNoVirtual());\n"
@@ -1575,7 +1572,7 @@ class ParseLoopGenerator {
                 " _$classname$_default_instance_.$2$_), ptr);\n",
                 field->number(), FieldName(field));
           } else {
-            format_("ptr = ctx->ParseMessage($1$_$2$(), ptr);\n",
+            format_("ptr = ctx->ParseMessage(_internal_$1$_$2$(), ptr);\n",
                     field->is_repeated() ? "add" : "mutable", FieldName(field));
           }
           break;
@@ -1619,7 +1616,8 @@ class ParseLoopGenerator {
                     QualifiedClassName(field->enum_type(), options_));
             format_.Indent();
           }
-          format_("$1$_$2$(static_cast<$3$>(val));\n", prefix, FieldName(field),
+          format_("_internal_$1$_$2$(static_cast<$3$>(val));\n", prefix,
+                  FieldName(field),
                   QualifiedClassName(field->enum_type(), options_));
           if (!HasPreservingUnknownEnumSemantics(field)) {
             format_.Outdent();
@@ -1639,7 +1637,7 @@ class ParseLoopGenerator {
           if (field->is_repeated() || field->containing_oneof()) {
             string prefix = field->is_repeated() ? "add" : "set";
             format_(
-                "$1$_$2$($pi_ns$::ReadVarint$3$(&ptr));\n"
+                "_internal_$1$_$2$($pi_ns$::ReadVarint$3$(&ptr));\n"
                 "CHK_(ptr);\n",
                 prefix, FieldName(field), zigzag);
           } else {
@@ -1661,7 +1659,7 @@ class ParseLoopGenerator {
         if (field->is_repeated() || field->containing_oneof()) {
           string prefix = field->is_repeated() ? "add" : "set";
           format_(
-              "$1$_$2$($pi_ns$::UnalignedLoad<$3$>(ptr));\n"
+              "_internal_$1$_$2$($pi_ns$::UnalignedLoad<$3$>(ptr));\n"
               "ptr += sizeof($3$);\n",
               prefix, FieldName(field), type);
         } else {
@@ -1682,7 +1680,7 @@ class ParseLoopGenerator {
       }
       case WireFormatLite::WIRETYPE_START_GROUP: {
         format_(
-            "ptr = ctx->ParseGroup($1$_$2$(), ptr, $3$);\n"
+            "ptr = ctx->ParseGroup(_internal_$1$_$2$(), ptr, $3$);\n"
             "CHK_(ptr);\n",
             field->is_repeated() ? "add" : "mutable", FieldName(field), tag);
         break;

+ 1 - 6
src/google/protobuf/compiler/cpp/cpp_helpers.h

@@ -49,6 +49,7 @@
 #include <google/protobuf/port.h>
 #include <google/protobuf/stubs/strutil.h>
 
+// Must be included last.
 #include <google/protobuf/port_def.inc>
 
 namespace google {
@@ -153,12 +154,6 @@ std::string DescriptorTableName(const FileDescriptor* file,
 // dllexport needed for the target file, if any.
 std::string FileDllExport(const FileDescriptor* file, const Options& options);
 
-// Returns the name of a no-op function that we can call to introduce a linker
-// dependency on the given message type. This is used to implement implicit weak
-// fields.
-std::string ReferenceFunctionName(const Descriptor* descriptor,
-                                  const Options& options);
-
 // Name of the base class: google::protobuf::Message or google::protobuf::MessageLite.
 std::string SuperClassName(const Descriptor* descriptor,
                            const Options& options);

+ 27 - 81
src/google/protobuf/compiler/cpp/cpp_map_field.cc

@@ -112,6 +112,12 @@ void MapFieldGenerator::GenerateAccessorDeclarations(
     io::Printer* printer) const {
   Formatter format(printer, variables_);
   format(
+      "private:\n"
+      "const ::$proto_ns$::Map< $key_cpp$, $val_cpp$ >&\n"
+      "    ${1$_internal_$name$$}$() const;\n"
+      "::$proto_ns$::Map< $key_cpp$, $val_cpp$ >*\n"
+      "    ${1$_internal_mutable_$name$$}$();\n"
+      "public:\n"
       "$deprecated_attr$const ::$proto_ns$::Map< $key_cpp$, $val_cpp$ >&\n"
       "    ${1$$name$$}$() const;\n"
       "$deprecated_attr$::$proto_ns$::Map< $key_cpp$, $val_cpp$ >*\n"
@@ -123,17 +129,25 @@ void MapFieldGenerator::GenerateInlineAccessorDefinitions(
     io::Printer* printer) const {
   Formatter format(printer, variables_);
   format(
+      "inline const ::$proto_ns$::Map< $key_cpp$, $val_cpp$ >&\n"
+      "$classname$::_internal_$name$() const {\n"
+      "  return $name$_.GetMap();\n"
+      "}\n"
       "inline const ::$proto_ns$::Map< $key_cpp$, $val_cpp$ >&\n"
       "$classname$::$name$() const {\n"
       "$annotate_accessor$"
       "  // @@protoc_insertion_point(field_map:$full_name$)\n"
-      "  return $name$_.GetMap();\n"
+      "  return _internal_$name$();\n"
+      "}\n"
+      "inline ::$proto_ns$::Map< $key_cpp$, $val_cpp$ >*\n"
+      "$classname$::_internal_mutable_$name$() {\n"
+      "  return $name$_.MutableMap();\n"
       "}\n"
       "inline ::$proto_ns$::Map< $key_cpp$, $val_cpp$ >*\n"
       "$classname$::mutable_$name$() {\n"
       "$annotate_accessor$"
       "  // @@protoc_insertion_point(field_mutable_map:$full_name$)\n"
-      "  return $name$_.MutableMap();\n"
+      "  return _internal_mutable_$name$();\n"
       "}\n");
 }
 
@@ -158,75 +172,6 @@ void MapFieldGenerator::GenerateCopyConstructorCode(
   GenerateMergingCode(printer);
 }
 
-void MapFieldGenerator::GenerateMergeFromCodedStream(
-    io::Printer* printer) const {
-  Formatter format(printer, variables_);
-  const FieldDescriptor* key_field =
-      descriptor_->message_type()->FindFieldByName("key");
-  const FieldDescriptor* value_field =
-      descriptor_->message_type()->FindFieldByName("value");
-  std::string key;
-  std::string value;
-  format(
-      "$map_classname$::Parser< ::$proto_ns$::internal::MapField$lite$<\n"
-      "    $map_classname$,\n"
-      "    $key_cpp$, $val_cpp$,\n"
-      "    ::$proto_ns$::internal::WireFormatLite::$key_wire_type$,\n"
-      "    ::$proto_ns$::internal::WireFormatLite::$val_wire_type$,\n"
-      "    $default_enum_value$ >,\n"
-      "  ::$proto_ns$::Map< $key_cpp$, $val_cpp$ > >"
-      " parser(&$name$_);\n");
-  if (IsProto3Field(descriptor_) ||
-      value_field->type() != FieldDescriptor::TYPE_ENUM) {
-    format(
-        "DO_(::$proto_ns$::internal::WireFormatLite::ReadMessageNoVirtual(\n"
-        "    input, &parser));\n");
-    key = "parser.key()";
-    value = "parser.value()";
-  } else {
-    key = "entry->key()";
-    value = "entry->value()";
-    format("auto entry = parser.NewEntry();\n");
-    format(
-        "std::string data;\n"
-        "DO_(::$proto_ns$::internal::WireFormatLite::ReadString(input, "
-        "&data));\n"
-        "DO_(entry->ParseFromString(data));\n"
-        "if ($val_cpp$_IsValid(*entry->mutable_value())) {\n"
-        "  (*mutable_$name$())[entry->key()] =\n"
-        "      static_cast< $val_cpp$ >(*entry->mutable_value());\n"
-        "} else {\n");
-    if (HasDescriptorMethods(descriptor_->file(), options_)) {
-      format(
-          "  mutable_unknown_fields()"
-          "->AddLengthDelimited($number$, data);\n");
-    } else {
-      format(
-          "  unknown_fields_stream.WriteVarint32($tag$u);\n"
-          "  unknown_fields_stream.WriteVarint32(\n"
-          "      static_cast< ::google::protobuf::uint32>(data.size()));\n"
-          "  unknown_fields_stream.WriteString(data);\n");
-    }
-    format("}\n");
-  }
-
-  if (key_field->type() == FieldDescriptor::TYPE_STRING) {
-    GenerateUtf8CheckCodeForString(
-        key_field, options_, true,
-        StrCat(key, ".data(), static_cast<int>(", key, ".length()),\n")
-            .data(),
-        format);
-  }
-  if (value_field->type() == FieldDescriptor::TYPE_STRING) {
-    GenerateUtf8CheckCodeForString(
-        value_field, options_, true,
-        StrCat(value, ".data(), static_cast<int>(", value,
-                     ".length()),\n")
-            .data(),
-        format);
-  }
-}
-
 static void GenerateSerializationLoop(const Formatter& format, bool string_key,
                                       bool string_value,
                                       bool is_deterministic) {
@@ -238,8 +183,8 @@ static void GenerateSerializationLoop(const Formatter& format, bool string_key,
   } else {
     format(
         "for (::$proto_ns$::Map< $key_cpp$, $val_cpp$ >::const_iterator\n"
-        "    it = this->$name$().begin();\n"
-        "    it != this->$name$().end(); ++it) {\n");
+        "    it = this->_internal_$name$().begin();\n"
+        "    it != this->_internal_$name$().end(); ++it) {\n");
     ptr = "it";
   }
   format.Indent();
@@ -262,7 +207,7 @@ static void GenerateSerializationLoop(const Formatter& format, bool string_key,
 void MapFieldGenerator::GenerateSerializeWithCachedSizesToArray(
     io::Printer* printer) const {
   Formatter format(printer, variables_);
-  format("if (!this->$name$().empty()) {\n");
+  format("if (!this->_internal_$name$().empty()) {\n");
   format.Indent();
   const FieldDescriptor* key_field =
       descriptor_->message_type()->FindFieldByName("key");
@@ -313,15 +258,15 @@ void MapFieldGenerator::GenerateSerializeWithCachedSizesToArray(
   format(
       "\n"
       "if (stream->IsSerializationDeterministic() &&\n"
-      "    this->$name$().size() > 1) {\n"
+      "    this->_internal_$name$().size() > 1) {\n"
       "  ::std::unique_ptr<SortItem[]> items(\n"
-      "      new SortItem[this->$name$().size()]);\n"
+      "      new SortItem[this->_internal_$name$().size()]);\n"
       "  typedef ::$proto_ns$::Map< $key_cpp$, $val_cpp$ >::size_type "
       "size_type;\n"
       "  size_type n = 0;\n"
       "  for (::$proto_ns$::Map< $key_cpp$, $val_cpp$ >::const_iterator\n"
-      "      it = this->$name$().begin();\n"
-      "      it != this->$name$().end(); ++it, ++n) {\n"
+      "      it = this->_internal_$name$().begin();\n"
+      "      it != this->_internal_$name$().end(); ++it, ++n) {\n"
       "    items[static_cast<ptrdiff_t>(n)] = SortItem(&*it);\n"
       "  }\n"
       "  ::std::sort(&items[0], &items[static_cast<ptrdiff_t>(n)], Less());\n");
@@ -341,10 +286,11 @@ void MapFieldGenerator::GenerateByteSize(io::Printer* printer) const {
   Formatter format(printer, variables_);
   format(
       "total_size += $tag_size$ *\n"
-      "    ::$proto_ns$::internal::FromIntSize(this->$name$_size());\n"
+      "    "
+      "::$proto_ns$::internal::FromIntSize(this->_internal_$name$_size());\n"
       "for (::$proto_ns$::Map< $key_cpp$, $val_cpp$ >::const_iterator\n"
-      "    it = this->$name$().begin();\n"
-      "    it != this->$name$().end(); ++it) {\n"
+      "    it = this->_internal_$name$().begin();\n"
+      "    it != this->_internal_$name$().end(); ++it) {\n"
       "  total_size += $map_classname$::Funcs::ByteSizeLong(it->first, "
       "it->second);\n"
       "}\n");

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

@@ -55,7 +55,6 @@ class MapFieldGenerator : public FieldGenerator {
   void GenerateSwappingCode(io::Printer* printer) const;
   void GenerateConstructorCode(io::Printer* printer) const {}
   void GenerateCopyConstructorCode(io::Printer* printer) const;
-  void GenerateMergeFromCodedStream(io::Printer* printer) const;
   void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
   void GenerateByteSize(io::Printer* printer) const;
 

+ 43 - 331
src/google/protobuf/compiler/cpp/cpp_message.cc

@@ -185,7 +185,7 @@ bool EmitFieldNonDefaultCondition(io::Printer* printer,
     format.Indent();
     return true;
   } else if (field->containing_oneof()) {
-    format("if (has_$name$()) {\n");
+    format("if (_internal_has_$name$()) {\n");
     format.Indent();
     return true;
   }
@@ -734,7 +734,12 @@ void MessageGenerator::GenerateFieldAccessorDeclarations(io::Printer* printer) {
     format.AddMap(vars);
 
     if (field->is_repeated()) {
-      format("$deprecated_attr$int ${1$$name$_size$}$() const;\n", field);
+      format(
+          "$deprecated_attr$int ${1$$name$_size$}$() const;\n"
+          "private:\n"
+          "int ${1$_internal_$name$_size$}$() const;\n"
+          "public:\n",
+          field);
     } else if (HasHasMethod(field)) {
       format(
           "$deprecated_attr$bool ${1$has_$name$$}$() const;\n"
@@ -745,7 +750,7 @@ void MessageGenerator::GenerateFieldAccessorDeclarations(io::Printer* printer) {
     } else if (HasPrivateHasMethod(field)) {
       format(
           "private:\n"
-          "bool ${1$has_$name$$}$() const;\n"
+          "bool ${1$_internal_has_$name$$}$() const;\n"
           "public:\n",
           field);
     }
@@ -804,7 +809,19 @@ void MessageGenerator::GenerateSingularFieldHasBits(
                strings::Hex(1u << (has_bit_index % 32), strings::ZERO_PAD_8));
     format(
         "inline bool $classname$::_internal_has_$name$() const {\n"
-        "  return (_has_bits_[$has_array_index$] & 0x$has_mask$u) != 0;\n"
+        "  bool value = "
+        "(_has_bits_[$has_array_index$] & 0x$has_mask$u) != 0;\n");
+
+    if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
+        !IsLazy(field, options_)) {
+      // We maintain the invariant that for a submessage x, has_x() returning
+      // true implies that x_ is not null. By giving this information to the
+      // compiler, we allow it to eliminate unnecessary null checks later on.
+      format("  PROTOBUF_ASSUME(!value || $name$_ != nullptr);\n");
+    }
+
+    format(
+        "  return value;\n"
         "}\n"
         "inline bool $classname$::has_$name$() const {\n"
         "$annotate_accessor$"
@@ -815,18 +832,21 @@ void MessageGenerator::GenerateSingularFieldHasBits(
     if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
       if (IsLazy(field, options_)) {
         format(
-            "inline bool $classname$::has_$name$() const {\n"
-            "$annotate_accessor$"
+            "inline bool $classname$::_internal_has_$name$() const {\n"
             "  return !$name$_.IsCleared();\n"
             "}\n");
       } else {
         format(
-            "inline bool $classname$::has_$name$() const {\n"
-            "$annotate_accessor$"
+            "inline bool $classname$::_internal_has_$name$() const {\n"
             "  return this != internal_default_instance() "
             "&& $name$_ != nullptr;\n"
             "}\n");
       }
+      format(
+          "inline bool $classname$::has_$name$() const {\n"
+          "$annotate_accessor$"
+          "  return _internal_has_$name$();\n"
+          "}\n");
     }
   }
 }
@@ -858,12 +878,7 @@ void MessageGenerator::GenerateOneofMemberHasBits(const FieldDescriptor* field,
   //
   // If has_$name$() is private, there is no need to add an internal accessor.
   // Only annotate public accessors.
-  if (HasPrivateHasMethod(field)) {
-    format(
-        "inline bool $classname$::has_$name$() const {\n"
-        "  return $oneof_name$_case() == k$field_name$;\n"
-        "}\n");
-  } else {
+  if (HasHasMethod(field)) {
     format(
         "inline bool $classname$::_internal_has_$name$() const {\n"
         "  return $oneof_name$_case() == k$field_name$;\n"
@@ -872,6 +887,11 @@ void MessageGenerator::GenerateOneofMemberHasBits(const FieldDescriptor* field,
         "$annotate_accessor$"
         "  return _internal_has_$name$();\n"
         "}\n");
+  } else if (HasPrivateHasMethod(field)) {
+    format(
+        "inline bool $classname$::_internal_has_$name$() const {\n"
+        "  return $oneof_name$_case() == k$field_name$;\n"
+        "}\n");
   }
   // set_has_$name$() for oneof fields is always private; hence should not be
   // annotated.
@@ -896,7 +916,7 @@ void MessageGenerator::GenerateFieldClear(const FieldDescriptor* field,
   if (field->containing_oneof()) {
     // Clear this field only if it is the active field in this oneof,
     // otherwise ignore
-    format("if (has_$name$()) {\n");
+    format("if (_internal_has_$name$()) {\n");
     format.Indent();
     field_generators_.get(field).GenerateClearingCode(format.printer());
     format("clear_has_$oneof_name$();\n");
@@ -937,9 +957,12 @@ void MessageGenerator::GenerateFieldAccessorDefinitions(io::Printer* printer) {
     // Generate has_$name$() or $name$_size().
     if (field->is_repeated()) {
       format(
+          "inline int $classname$::_internal_$name$_size() const {\n"
+          "  return $name$_$1$.size();\n"
+          "}\n"
           "inline int $classname$::$name$_size() const {\n"
           "$annotate_accessor$"
-          "  return $name$_$1$.size();\n"
+          "  return _internal_$name$_size();\n"
           "}\n",
           IsImplicitWeakField(field, options_, scc_analyzer_) &&
                   field->message_type()
@@ -1313,13 +1336,8 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) {
         "bool IsInitialized() const$ is_initialized_final$;\n"
         "\n"
         "size_t ByteSizeLong() const final;\n"
-        "#if $GOOGLE_PROTOBUF$_ENABLE_EXPERIMENTAL_PARSER\n"
         "const char* _InternalParse(const char* ptr, "
         "::$proto_ns$::internal::ParseContext* ctx) final;\n"
-        "#else\n"
-        "bool MergePartialFromCodedStream(\n"
-        "    ::$proto_ns$::io::CodedInputStream* input) final;\n"
-        "#endif  // $GOOGLE_PROTOBUF$_ENABLE_EXPERIMENTAL_PARSER\n"
         "$uint8$* InternalSerializeWithCachedSizesToArray(\n"
         "    $uint8$* target, ::$proto_ns$::io::EpsCopyOutputStream* stream) "
         "const final;\n");
@@ -3226,7 +3244,7 @@ void MessageGenerator::GenerateMergeFrom(io::Printer* printer) {
 
           format("if (cached_has_bits & 0x$1$u) {\n", mask);
         } else {
-          format("if (from.has_$1$()) {\n", FieldName(field));
+          format("if (from._internal_has_$1$()) {\n", FieldName(field));
         }
         format.Indent();
 
@@ -3384,322 +3402,15 @@ void MessageGenerator::GenerateMergeFromCodedStream(io::Printer* printer) {
   if (descriptor_->options().message_set_wire_format()) {
     // Special-case MessageSet.
     format(
-        "#if $GOOGLE_PROTOBUF$_ENABLE_EXPERIMENTAL_PARSER\n"
         "const char* $classname$::_InternalParse(const char* ptr,\n"
         "                  ::$proto_ns$::internal::ParseContext* ctx) {\n"
         "  return _extensions_.ParseMessageSet(ptr, \n"
         "      internal_default_instance(), &_internal_metadata_, ctx);\n"
-        "}\n"
-        "#else\n"
-        "bool $classname$::MergePartialFromCodedStream(\n"
-        "    ::$proto_ns$::io::CodedInputStream* input) {\n"
-        "  return _extensions_.ParseMessageSet(input,\n"
-        "      internal_default_instance(), $mutable_unknown_fields$);\n"
-        "}\n"
-        "#endif  // $GOOGLE_PROTOBUF$_ENABLE_EXPERIMENTAL_PARSER\n");
+        "}\n");
     return;
   }
-  format("#if $GOOGLE_PROTOBUF$_ENABLE_EXPERIMENTAL_PARSER\n");
   GenerateParserLoop(descriptor_, max_has_bit_index_, options_, scc_analyzer_,
                      printer);
-  format("#else  // $GOOGLE_PROTOBUF$_ENABLE_EXPERIMENTAL_PARSER\n");
-  std::vector<const FieldDescriptor*> ordered_fields =
-      SortFieldsByNumber(descriptor_);
-
-  format(
-      "bool $classname$::MergePartialFromCodedStream(\n"
-      "    ::$proto_ns$::io::CodedInputStream* input) {\n");
-
-  if (table_driven_) {
-    format.Indent();
-
-    const std::string lite =
-        UseUnknownFieldSet(descriptor_->file(), options_) ? "" : "Lite";
-
-    format(
-        "return ::$proto_ns$::internal::MergePartialFromCodedStream$1$(\n"
-        "    this, ::$tablename$::schema[\n"
-        "      $classname$::kIndexInFileMessages], input);\n",
-        lite);
-
-    format.Outdent();
-
-    format("}\n");
-    format("#endif  // $GOOGLE_PROTOBUF$_ENABLE_EXPERIMENTAL_PARSER\n");
-    return;
-  }
-
-  if (SupportsArenas(descriptor_)) {
-    for (auto field : ordered_fields) {
-      const FieldGenerator& field_generator = field_generators_.get(field);
-      if (field_generator.MergeFromCodedStreamNeedsArena()) {
-        format("  ::$proto_ns$::Arena* arena = GetArenaNoVirtual();\n");
-        break;
-      }
-    }
-  }
-
-  format(
-      "#define DO_(EXPRESSION) if "
-      "(!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure\n"
-      "  $uint32$ tag;\n");
-
-  if (!UseUnknownFieldSet(descriptor_->file(), options_)) {
-    format(
-        "  ::$proto_ns$::internal::LiteUnknownFieldSetter "
-        "unknown_fields_setter(\n"
-        "      &_internal_metadata_);\n"
-        "  ::$proto_ns$::io::StringOutputStream unknown_fields_output(\n"
-        "      unknown_fields_setter.buffer());\n"
-        "  ::$proto_ns$::io::CodedOutputStream unknown_fields_stream(\n"
-        "      &unknown_fields_output, false);\n");
-  }
-
-  format("  // @@protoc_insertion_point(parse_start:$full_name$)\n");
-
-  format.Indent();
-  format("for (;;) {\n");
-  format.Indent();
-
-  // To calculate the maximum tag to expect, we look at the highest-numbered
-  // field. We need to be prepared to handle more than one wire type if that
-  // field is a packable repeated field, so to simplify things we assume the
-  // highest possible wire type of 5.
-  uint32 maxtag =
-      ordered_fields.empty() ? 0 : ordered_fields.back()->number() * 8 + 5;
-  const int kCutoff0 = 127;               // fits in 1-byte varint
-  const int kCutoff1 = (127 << 7) + 127;  // fits in 2-byte varint
-
-  // We need to capture the last tag when parsing if this is a Group type, as
-  // our caller will verify (via CodedInputStream::LastTagWas) that the correct
-  // closing tag was received.
-  bool capture_last_tag = false;
-  const Descriptor* parent = descriptor_->containing_type();
-  if (parent) {
-    for (auto field : FieldRange(parent)) {
-      if (field->type() == FieldDescriptor::TYPE_GROUP &&
-          field->message_type() == descriptor_) {
-        capture_last_tag = true;
-        break;
-      }
-    }
-
-    for (int i = 0; i < parent->extension_count(); i++) {
-      const FieldDescriptor* field = parent->extension(i);
-      if (field->type() == FieldDescriptor::TYPE_GROUP &&
-          field->message_type() == descriptor_) {
-        capture_last_tag = true;
-        break;
-      }
-    }
-  }
-
-  for (int i = 0; i < descriptor_->file()->extension_count(); i++) {
-    const FieldDescriptor* field = descriptor_->file()->extension(i);
-    if (field->type() == FieldDescriptor::TYPE_GROUP &&
-        field->message_type() == descriptor_) {
-      capture_last_tag = true;
-      break;
-    }
-  }
-
-  format(
-      "::std::pair<$uint32$, bool> p = "
-      "input->ReadTagWithCutoffNoLastTag($1$u);\n"
-      "tag = p.first;\n"
-      "if (!p.second) goto handle_unusual;\n",
-      maxtag <= kCutoff0 ? kCutoff0 : (maxtag <= kCutoff1 ? kCutoff1 : maxtag));
-
-  if (descriptor_->field_count() > 0) {
-    // We don't even want to print the switch() if we have no fields because
-    // MSVC dislikes switch() statements that contain only a default value.
-
-    // Note:  If we just switched on the tag rather than the field number, we
-    // could avoid the need for the if() to check the wire type at the beginning
-    // of each case.  However, this is actually a bit slower in practice as it
-    // creates a jump table that is 8x larger and sparser, and meanwhile the
-    // if()s are highly predictable.
-    //
-    // Historically, we inserted checks to peek at the next tag on the wire and
-    // jump directly to the next case statement.  While this avoids the jump
-    // table that the switch uses, it greatly increases code size (20-60%) and
-    // inserts branches that may fail (especially for real world protos that
-    // interleave--in field number order--hot and cold fields).  Loadtests
-    // confirmed that removing this optimization is performance neutral.
-    if (num_weak_fields_ > 0) {
-      format("uint32 weak_offset;\n");
-    }
-    format(
-        "switch (::$proto_ns$::internal::WireFormatLite::"
-        "GetTagFieldNumber(tag)) {\n");
-
-    format.Indent();
-
-    for (auto field : ordered_fields) {
-      PrintFieldComment(format, field);
-      if (IsWeak(field, options_)) {
-        format(
-            "case $1$:\n"
-            "  weak_offset = offsetof($classname$DefaultTypeInternal, $2$_);\n"
-            "  goto handle_weak_field_map;\n",
-            field->number(), FieldName(field));
-        continue;
-      }
-
-      format("case $1$: {\n", field->number());
-      format.Indent();
-      const FieldGenerator& field_generator = field_generators_.get(field);
-
-      // Emit code to parse the common, expected case.
-      // MSVC is warning about truncating constant in the static_cast so
-      // we truncate the tag explicitly.
-      format("if (static_cast< $uint8$>(tag) == ($1$ & 0xFF)) {\n",
-             WireFormat::MakeTag(field));
-
-      format.Indent();
-      if (field->is_packed()) {
-        field_generator.GenerateMergeFromCodedStreamWithPacking(printer);
-      } else {
-        field_generator.GenerateMergeFromCodedStream(printer);
-      }
-      format.Outdent();
-
-      // Emit code to parse unexpectedly packed or unpacked values.
-      if (field->is_packed()) {
-        internal::WireFormatLite::WireType wiretype =
-            WireFormat::WireTypeForFieldType(field->type());
-        const uint32 tag =
-            internal::WireFormatLite::MakeTag(field->number(), wiretype);
-        format("} else if (static_cast< $uint8$>(tag) == ($1$ & 0xFF)) {\n",
-               tag);
-
-        format.Indent();
-        field_generator.GenerateMergeFromCodedStream(printer);
-        format.Outdent();
-      } else if (field->is_packable() && !field->is_packed()) {
-        internal::WireFormatLite::WireType wiretype =
-            internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED;
-        const uint32 tag =
-            internal::WireFormatLite::MakeTag(field->number(), wiretype);
-        format("} else if (static_cast< $uint8$>(tag) == ($1$ & 0xFF)) {\n",
-               tag);
-        format.Indent();
-        field_generator.GenerateMergeFromCodedStreamWithPacking(printer);
-        format.Outdent();
-      }
-
-      format(
-          "} else {\n"
-          "  goto handle_unusual;\n"
-          "}\n");
-
-      format("break;\n");
-
-      format.Outdent();
-      format("}\n\n");
-    }
-    if (num_weak_fields_ > 0) {
-      format("handle_weak_field_map: {\n");
-      format.Indent();
-
-      format(
-          "if ((tag & 0x7) != 2) goto handle_unusual;\n"
-          "DO_(_weak_field_map_.ReadMessage(input, tag >> 3,\n"
-          "    &_$classname$_default_instance_, weak_offset));\n");
-      format("break;\n");
-      format.Outdent();
-      format("}\n\n");
-    }
-    format("default: {\n");
-    format.Indent();
-  }
-
-  format.Outdent();
-  format("handle_unusual:\n");
-  format.Indent();
-  // If tag is 0 or an end-group tag then this must be the end of the message.
-  if (capture_last_tag) {
-    format(
-        "if (tag == 0 ||\n"
-        "    ::$proto_ns$::internal::WireFormatLite::GetTagWireType(tag) ==\n"
-        "    ::$proto_ns$::internal::WireFormatLite::WIRETYPE_END_GROUP) {\n"
-        "  input->SetLastTag(tag);\n"
-        "  goto success;\n"
-        "}\n");
-  } else {
-    format(
-        "if (tag == 0) {\n"
-        "  goto success;\n"
-        "}\n");
-  }
-
-  // Handle extension ranges.
-  if (descriptor_->extension_range_count() > 0) {
-    format("if (");
-    for (int i = 0; i < descriptor_->extension_range_count(); i++) {
-      const Descriptor::ExtensionRange* range = descriptor_->extension_range(i);
-      if (i > 0) format(" ||\n    ");
-
-      uint32 start_tag = WireFormatLite::MakeTag(
-          range->start, static_cast<WireFormatLite::WireType>(0));
-      uint32 end_tag = WireFormatLite::MakeTag(
-          range->end, static_cast<WireFormatLite::WireType>(0));
-
-      if (range->end > FieldDescriptor::kMaxNumber) {
-        format("($1$u <= tag)", start_tag);
-      } else {
-        format("($1$u <= tag && tag < $2$u)", start_tag, end_tag);
-      }
-    }
-    format(") {\n");
-    if (UseUnknownFieldSet(descriptor_->file(), options_)) {
-      format(
-          "  DO_(_extensions_.ParseField(tag, input,\n"
-          "      internal_default_instance(),\n"
-          "      $mutable_unknown_fields$));\n");
-    } else {
-      format(
-          "  DO_(_extensions_.ParseField(tag, input,\n"
-          "      internal_default_instance(),\n"
-          "      &unknown_fields_stream));\n");
-    }
-    format(
-        "  continue;\n"
-        "}\n");
-  }
-
-  // We really don't recognize this tag.  Skip it.
-  if (UseUnknownFieldSet(descriptor_->file(), options_)) {
-    format(
-        "DO_(::$proto_ns$::internal::WireFormat::SkipField(\n"
-        "      input, tag, $mutable_unknown_fields$));\n");
-  } else {
-    format(
-        "DO_(::$proto_ns$::internal::WireFormatLite::SkipField(\n"
-        "    input, tag, &unknown_fields_stream));\n");
-  }
-
-  if (descriptor_->field_count() > 0) {
-    format("break;\n");
-    format.Outdent();
-    format("}\n");  // default:
-    format.Outdent();
-    format("}\n");  // switch
-  }
-
-  format.Outdent();
-  format.Outdent();
-  format(
-      "  }\n"  // for (;;)
-      "success:\n"
-      "  // @@protoc_insertion_point(parse_success:$full_name$)\n"
-      "  return true;\n"
-      "failure:\n"
-      "  // @@protoc_insertion_point(parse_failure:$full_name$)\n"
-      "  return false;\n"
-      "#undef DO_\n"
-      "}\n");
-  format("#endif  // $GOOGLE_PROTOBUF$_ENABLE_EXPERIMENTAL_PARSER\n");
 }
 
 void MessageGenerator::GenerateSerializeOneofFields(
@@ -3715,12 +3426,13 @@ void MessageGenerator::GenerateSerializeOneofFields(
   format("switch ($1$_case()) {\n", oneof->name());
   format.Indent();
   for (auto field : fields) {
-    format("case k$1$:\n", UnderscoresToCamelCase(field->name(), true));
+    format("case k$1$: {\n", UnderscoresToCamelCase(field->name(), true));
     format.Indent();
     field_generators_.get(field).GenerateSerializeWithCachedSizesToArray(
         printer);
     format("break;\n");
     format.Outdent();
+    format("}\n");
   }
   format.Outdent();
   // Doing nothing is an option.

+ 74 - 73
src/google/protobuf/compiler/cpp/cpp_message_field.cc

@@ -66,8 +66,8 @@ void SetMessageVariables(const FieldDescriptor* descriptor,
       QualifiedDefaultInstancePtr(descriptor->message_type(), options);
   (*variables)["type_reference_function"] =
       implicit_weak
-          ? ("  " + ReferenceFunctionName(descriptor->message_type(), options) +
-             "();\n")
+          ? ("  " + (*variables)["proto_ns"] + "::internal::StrongReference(" +
+             (*variables)["type_default_instance"] + ");\n")
           : "";
   // NOTE: Escaped here to unblock proto1->proto2 migration.
   // TODO(liujisi): Extend this to apply for other conflicting methods.
@@ -108,7 +108,11 @@ void MessageFieldGenerator::GenerateAccessorDeclarations(
       "$deprecated_attr$$type$* ${1$$release_name$$}$();\n"
       "$deprecated_attr$$type$* ${1$mutable_$name$$}$();\n"
       "$deprecated_attr$void ${1$set_allocated_$name$$}$"
-      "($type$* $name$);\n",
+      "($type$* $name$);\n"
+      "private:\n"
+      "const $type$& ${1$_internal_$name$$}$() const;\n"
+      "$type$* ${1$_internal_mutable_$name$$}$();\n"
+      "public:\n",
       descriptor_);
   if (SupportsArenas(descriptor_)) {
     format(
@@ -149,13 +153,16 @@ void MessageFieldGenerator::GenerateInlineAccessorDefinitions(
     io::Printer* printer) const {
   Formatter format(printer, variables_);
   format(
-      "inline const $type$& $classname$::$name$() const {\n"
-      "$annotate_accessor$"
+      "inline const $type$& $classname$::_internal_$name$() const {\n"
       "$type_reference_function$"
       "  const $type$* p = $casted_member$;\n"
-      "  // @@protoc_insertion_point(field_get:$full_name$)\n"
       "  return p != nullptr ? *p : *reinterpret_cast<const $type$*>(\n"
       "      &$type_default_instance$);\n"
+      "}\n"
+      "inline const $type$& $classname$::$name$() const {\n"
+      "$annotate_accessor$"
+      "  // @@protoc_insertion_point(field_get:$full_name$)\n"
+      "  return _internal_$name$();\n"
       "}\n");
 
   if (SupportsArenas(descriptor_)) {
@@ -182,8 +189,7 @@ void MessageFieldGenerator::GenerateInlineAccessorDefinitions(
       "}\n");
 
   format(
-      "inline $type$* $classname$::mutable_$name$() {\n"
-      "$annotate_accessor$"
+      "inline $type$* $classname$::_internal_mutable_$name$() {\n"
       "$type_reference_function$"
       "  $set_hasbit$\n"
       "  if ($name$_ == nullptr) {\n"
@@ -195,8 +201,12 @@ void MessageFieldGenerator::GenerateInlineAccessorDefinitions(
   }
   format(
       "  }\n"
-      "  // @@protoc_insertion_point(field_mutable:$full_name$)\n"
       "  return $casted_member$;\n"
+      "}\n"
+      "inline $type$* $classname$::mutable_$name$() {\n"
+      "$annotate_accessor$"
+      "  // @@protoc_insertion_point(field_mutable:$full_name$)\n"
+      "  return _internal_mutable_$name$();\n"
       "}\n");
 
   // We handle the most common case inline, and delegate less common cases to
@@ -381,7 +391,9 @@ void MessageFieldGenerator::GenerateMergingCode(io::Printer* printer) const {
         "_Internal::mutable_$name$(this)->CheckTypeAndMergeFrom(\n"
         "    _Internal::$name$(&from));\n");
   } else {
-    format("mutable_$name$()->$type$::MergeFrom(from.$name$());\n");
+    format(
+        "_internal_mutable_$name$()->$type$::MergeFrom(from._internal_$name$())"
+        ";\n");
   }
 }
 
@@ -413,31 +425,13 @@ void MessageFieldGenerator::GenerateCopyConstructorCode(
     io::Printer* printer) const {
   Formatter format(printer, variables_);
   format(
-      "if (from.has_$name$()) {\n"
+      "if (from._internal_has_$name$()) {\n"
       "  $name$_ = new $type$(*from.$name$_);\n"
       "} else {\n"
       "  $name$_ = nullptr;\n"
       "}\n");
 }
 
-void MessageFieldGenerator::GenerateMergeFromCodedStream(
-    io::Printer* printer) const {
-  Formatter format(printer, variables_);
-  if (implicit_weak_field_) {
-    format(
-        "DO_(::$proto_ns$::internal::WireFormatLite::ReadMessage(\n"
-        "     input, _Internal::mutable_$name$(this)));\n");
-  } else if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE) {
-    format(
-        "DO_(::$proto_ns$::internal::WireFormatLite::ReadMessage(\n"
-        "     input, mutable_$name$()));\n");
-  } else {
-    format(
-        "DO_(::$proto_ns$::internal::WireFormatLite::ReadGroup(\n"
-        "      $number$, input, mutable_$name$()));\n");
-  }
-}
-
 void MessageFieldGenerator::GenerateSerializeWithCachedSizesToArray(
     io::Printer* printer) const {
   Formatter format(printer, variables_);
@@ -528,12 +522,15 @@ void MessageOneofFieldGenerator::GenerateInlineAccessorDefinitions(
       "}\n");
 
   format(
+      "inline const $type$& $classname$::_internal_$name$() const {\n"
+      "  return _internal_has_$name$()\n"
+      "      ? *$field_member$\n"
+      "      : *reinterpret_cast< $type$*>(&$type_default_instance$);\n"
+      "}\n"
       "inline const $type$& $classname$::$name$() const {\n"
       "$annotate_accessor$"
       "  // @@protoc_insertion_point(field_get:$full_name$)\n"
-      "  return has_$name$()\n"
-      "      ? *$field_member$\n"
-      "      : *reinterpret_cast< $type$*>(&$type_default_instance$);\n"
+      "  return _internal_$name$();\n"
       "}\n");
 
   if (SupportsArenas(descriptor_)) {
@@ -568,16 +565,19 @@ void MessageOneofFieldGenerator::GenerateInlineAccessorDefinitions(
   }
 
   format(
-      "inline $type$* $classname$::mutable_$name$() {\n"
-      "$annotate_accessor$"
-      "  if (!has_$name$()) {\n"
+      "inline $type$* $classname$::_internal_mutable_$name$() {\n"
+      "  if (!_internal_has_$name$()) {\n"
       "    clear_$oneof_name$();\n"
       "    set_has_$name$();\n"
       "    $field_member$ = CreateMaybeMessage< $type$ >(\n"
       "        GetArenaNoVirtual());\n"
       "  }\n"
-      "  // @@protoc_insertion_point(field_mutable:$full_name$)\n"
       "  return $field_member$;\n"
+      "}\n"
+      "inline $type$* $classname$::mutable_$name$() {\n"
+      "$annotate_accessor$"
+      "  // @@protoc_insertion_point(field_mutable:$full_name$)\n"
+      "  return _internal_mutable_$name$();\n"
       "}\n");
 }
 
@@ -646,6 +646,10 @@ void RepeatedMessageFieldGenerator::GenerateAccessorDeclarations(
       "$deprecated_attr$$type$* ${1$mutable_$name$$}$(int index);\n"
       "$deprecated_attr$::$proto_ns$::RepeatedPtrField< $type$ >*\n"
       "    ${1$mutable_$name$$}$();\n"
+      "private:\n"
+      "const $type$& ${1$_internal_$name$$}$(int index) const;\n"
+      "$type$* ${1$_internal_add_$name$$}$();\n"
+      "public:\n"
       "$deprecated_attr$const $type$& ${1$$name$$}$(int index) const;\n"
       "$deprecated_attr$$type$* ${1$add_$name$$}$();\n"
       "$deprecated_attr$const ::$proto_ns$::RepeatedPtrField< $type$ >&\n"
@@ -676,27 +680,33 @@ void RepeatedMessageFieldGenerator::GenerateInlineAccessorDefinitions(
 
   if (options_.safe_boundary_check) {
     format(
-        "inline const $type$& $classname$::$name$(int index) const {\n"
-        "$annotate_accessor$"
-        "  // @@protoc_insertion_point(field_get:$full_name$)\n"
+        "inline const $type$& $classname$::_internal_$name$(int index) const "
+        "{\n"
         "  return $name$_$weak$.InternalCheckedGet(index,\n"
         "      *reinterpret_cast<const $type$*>(&$type_default_instance$));\n"
         "}\n");
   } else {
     format(
-        "inline const $type$& $classname$::$name$(int index) const {\n"
-        "$annotate_accessor$"
-        "  // @@protoc_insertion_point(field_get:$full_name$)\n"
+        "inline const $type$& $classname$::_internal_$name$(int index) const "
+        "{\n"
         "$type_reference_function$"
         "  return $name$_$weak$.Get(index);\n"
         "}\n");
   }
 
   format(
+      "inline const $type$& $classname$::$name$(int index) const {\n"
+      "$annotate_accessor$"
+      "  // @@protoc_insertion_point(field_get:$full_name$)\n"
+      "  return _internal_$name$(index);\n"
+      "}\n"
+      "inline $type$* $classname$::_internal_add_$name$() {\n"
+      "  return $name$_$weak$.Add();\n"
+      "}\n"
       "inline $type$* $classname$::add_$name$() {\n"
       "$annotate_accessor$"
       "  // @@protoc_insertion_point(field_add:$full_name$)\n"
-      "  return $name$_$weak$.Add();\n"
+      "  return _internal_add_$name$();\n"
       "}\n");
 
   format(
@@ -732,47 +742,38 @@ void RepeatedMessageFieldGenerator::GenerateConstructorCode(
   // Not needed for repeated fields.
 }
 
-void RepeatedMessageFieldGenerator::GenerateMergeFromCodedStream(
+void RepeatedMessageFieldGenerator::GenerateSerializeWithCachedSizesToArray(
     io::Printer* printer) const {
   Formatter format(printer, variables_);
-  if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE) {
-    if (implicit_weak_field_) {
-      format(
-          "DO_(::$proto_ns$::internal::WireFormatLite::"
-          "ReadMessage(input, $name$_.AddWeak(\n"
-          "    reinterpret_cast<const ::$proto_ns$::MessageLite*>(\n"
-          "        $type_default_instance_ptr$))));\n");
-    } else {
-      format(
-          "DO_(::$proto_ns$::internal::WireFormatLite::"
-          "ReadMessage(\n"
-          "      input, add_$name$()));\n");
-    }
+  if (implicit_weak_field_) {
+    format(
+        "for (auto it = this->$name$_.pointer_begin(),\n"
+        "          end = this->$name$_.pointer_end(); it < end; ++it) {\n"
+        "  stream->EnsureSpace(&target);\n"
+        "  target = ::$proto_ns$::internal::WireFormatLite::\n"
+        "    InternalWrite$declared_type$ToArray($number$, **it, target, "
+        "stream);\n"
+        "}\n");
   } else {
     format(
-        "DO_(::$proto_ns$::internal::WireFormatLite::"
-        "ReadGroup($number$, input, add_$name$()));\n");
+        "for (unsigned int i = 0,\n"
+        "    n = static_cast<unsigned int>(this->_internal_$name$_size()); i < "
+        "n; i++) "
+        "{\n"
+        "  stream->EnsureSpace(&target);\n"
+        "  target = ::$proto_ns$::internal::WireFormatLite::\n"
+        "    InternalWrite$declared_type$ToArray($number$, "
+        "this->_internal_$name$(i), target, "
+        "stream);\n"
+        "}\n");
   }
 }
 
-void RepeatedMessageFieldGenerator::GenerateSerializeWithCachedSizesToArray(
-    io::Printer* printer) const {
-  Formatter format(printer, variables_);
-  format(
-      "for (auto it = this->$name$_.pointer_begin(),\n"
-      "          end = this->$name$_.pointer_end(); it < end; ++it) {\n"
-      "  stream->EnsureSpace(&target);\n"
-      "  target = ::$proto_ns$::internal::WireFormatLite::\n"
-      "    InternalWrite$declared_type$ToArray($number$, **it, target, "
-      "stream);\n"
-      "}\n");
-}
-
 void RepeatedMessageFieldGenerator::GenerateByteSize(
     io::Printer* printer) const {
   Formatter format(printer, variables_);
   format(
-      "total_size += $tag_size$UL * this->$name$_size();\n"
+      "total_size += $tag_size$UL * this->_internal_$name$_size();\n"
       "for (const auto& msg : this->$name$_) {\n"
       "  total_size +=\n"
       "    ::$proto_ns$::internal::WireFormatLite::$declared_type$Size(msg);\n"

+ 0 - 2
src/google/protobuf/compiler/cpp/cpp_message_field.h

@@ -66,7 +66,6 @@ class MessageFieldGenerator : public FieldGenerator {
   void GenerateDestructorCode(io::Printer* printer) const;
   void GenerateConstructorCode(io::Printer* printer) const;
   void GenerateCopyConstructorCode(io::Printer* printer) const;
-  void GenerateMergeFromCodedStream(io::Printer* printer) const;
   void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
   void GenerateByteSize(io::Printer* printer) const;
 
@@ -116,7 +115,6 @@ class RepeatedMessageFieldGenerator : public FieldGenerator {
   void GenerateSwappingCode(io::Printer* printer) const;
   void GenerateConstructorCode(io::Printer* printer) const;
   void GenerateCopyConstructorCode(io::Printer* printer) const {}
-  void GenerateMergeFromCodedStream(io::Printer* printer) const;
   void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
   void GenerateByteSize(io::Printer* printer) const;
 

+ 66 - 68
src/google/protobuf/compiler/cpp/cpp_primitive_field.cc

@@ -136,7 +136,11 @@ void PrimitiveFieldGenerator::GenerateAccessorDeclarations(
   Formatter format(printer, variables_);
   format(
       "$deprecated_attr$$type$ ${1$$name$$}$() const;\n"
-      "$deprecated_attr$void ${1$set_$name$$}$($type$ value);\n",
+      "$deprecated_attr$void ${1$set_$name$$}$($type$ value);\n"
+      "private:\n"
+      "$type$ ${1$_internal_$name$$}$() const;\n"
+      "void ${1$_internal_set_$name$$}$($type$ value);\n"
+      "public:\n",
       descriptor_);
 }
 
@@ -144,15 +148,21 @@ void PrimitiveFieldGenerator::GenerateInlineAccessorDefinitions(
     io::Printer* printer) const {
   Formatter format(printer, variables_);
   format(
+      "inline $type$ $classname$::_internal_$name$() const {\n"
+      "  return $name$_;\n"
+      "}\n"
       "inline $type$ $classname$::$name$() const {\n"
       "$annotate_accessor$"
       "  // @@protoc_insertion_point(field_get:$full_name$)\n"
-      "  return $name$_;\n"
+      "  return _internal_$name$();\n"
       "}\n"
-      "inline void $classname$::set_$name$($type$ value) {\n"
-      "$annotate_accessor$"
+      "inline void $classname$::_internal_set_$name$($type$ value) {\n"
       "  $set_hasbit$\n"
       "  $name$_ = value;\n"
+      "}\n"
+      "inline void $classname$::set_$name$($type$ value) {\n"
+      "$annotate_accessor$"
+      "  _internal_set_$name$(value);\n"
       "  // @@protoc_insertion_point(field_set:$full_name$)\n"
       "}\n");
 }
@@ -164,7 +174,7 @@ void PrimitiveFieldGenerator::GenerateClearingCode(io::Printer* printer) const {
 
 void PrimitiveFieldGenerator::GenerateMergingCode(io::Printer* printer) const {
   Formatter format(printer, variables_);
-  format("set_$name$(from.$name$());\n");
+  format("_internal_set_$name$(from._internal_$name$());\n");
 }
 
 void PrimitiveFieldGenerator::GenerateSwappingCode(io::Printer* printer) const {
@@ -184,17 +194,6 @@ void PrimitiveFieldGenerator::GenerateCopyConstructorCode(
   format("$name$_ = from.$name$_;\n");
 }
 
-void PrimitiveFieldGenerator::GenerateMergeFromCodedStream(
-    io::Printer* printer) const {
-  Formatter format(printer, variables_);
-  format(
-      "$set_hasbit_io$\n"
-      "DO_((::$proto_ns$::internal::WireFormatLite::ReadPrimitive<\n"
-      "         $type$, "
-      "::$proto_ns$::internal::WireFormatLite::$wire_format_field_type$>(\n"
-      "       input, &$name$_)));\n");
-}
-
 void PrimitiveFieldGenerator::GenerateSerializeWithCachedSizesToArray(
     io::Printer* printer) const {
   Formatter format(printer, variables_);
@@ -202,7 +201,7 @@ void PrimitiveFieldGenerator::GenerateSerializeWithCachedSizesToArray(
       "stream->EnsureSpace(&target);\n"
       "target = "
       "::$proto_ns$::internal::WireFormatLite::Write$declared_type$ToArray("
-      "$number$, this->$name$(), target);\n");
+      "$number$, this->_internal_$name$(), target);\n");
 }
 
 void PrimitiveFieldGenerator::GenerateByteSize(io::Printer* printer) const {
@@ -212,7 +211,7 @@ void PrimitiveFieldGenerator::GenerateByteSize(io::Printer* printer) const {
     format(
         "total_size += $tag_size$ +\n"
         "  ::$proto_ns$::internal::WireFormatLite::$declared_type$Size(\n"
-        "    this->$name$());\n");
+        "    this->_internal_$name$());\n");
   } else {
     format("total_size += $tag_size$ + $fixed_size$;\n");
   }
@@ -232,21 +231,27 @@ void PrimitiveOneofFieldGenerator::GenerateInlineAccessorDefinitions(
     io::Printer* printer) const {
   Formatter format(printer, variables_);
   format(
-      "inline $type$ $classname$::$name$() const {\n"
-      "$annotate_accessor$"
-      "  // @@protoc_insertion_point(field_get:$full_name$)\n"
-      "  if (has_$name$()) {\n"
+      "inline $type$ $classname$::_internal_$name$() const {\n"
+      "  if (_internal_has_$name$()) {\n"
       "    return $field_member$;\n"
       "  }\n"
       "  return $default$;\n"
       "}\n"
-      "inline void $classname$::set_$name$($type$ value) {\n"
-      "$annotate_accessor$"
-      "  if (!has_$name$()) {\n"
+      "inline void $classname$::_internal_set_$name$($type$ value) {\n"
+      "  if (!_internal_has_$name$()) {\n"
       "    clear_$oneof_name$();\n"
       "    set_has_$name$();\n"
       "  }\n"
       "  $field_member$ = value;\n"
+      "}\n"
+      "inline $type$ $classname$::$name$() const {\n"
+      "$annotate_accessor$"
+      "  // @@protoc_insertion_point(field_get:$full_name$)\n"
+      "  return _internal_$name$();\n"
+      "}\n"
+      "inline void $classname$::set_$name$($type$ value) {\n"
+      "$annotate_accessor$"
+      "  _internal_set_$name$(value);\n"
       "  // @@protoc_insertion_point(field_set:$full_name$)\n"
       "}\n");
 }
@@ -268,18 +273,6 @@ void PrimitiveOneofFieldGenerator::GenerateConstructorCode(
   format("$ns$::_$classname$_default_instance_.$name$_ = $default$;\n");
 }
 
-void PrimitiveOneofFieldGenerator::GenerateMergeFromCodedStream(
-    io::Printer* printer) const {
-  Formatter format(printer, variables_);
-  format(
-      "clear_$oneof_name$();\n"
-      "DO_((::$proto_ns$::internal::WireFormatLite::ReadPrimitive<\n"
-      "         $type$, "
-      "::$proto_ns$::internal::WireFormatLite::$wire_format_field_type$>(\n"
-      "       input, &$field_member$)));\n"
-      "set_has_$name$();\n");
-}
-
 // ===================================================================
 
 RepeatedPrimitiveFieldGenerator::RepeatedPrimitiveFieldGenerator(
@@ -312,6 +305,14 @@ void RepeatedPrimitiveFieldGenerator::GenerateAccessorDeclarations(
     io::Printer* printer) const {
   Formatter format(printer, variables_);
   format(
+      "private:\n"
+      "$type$ ${1$_internal_$name$$}$(int index) const;\n"
+      "const ::$proto_ns$::RepeatedField< $type$ >&\n"
+      "    ${1$_internal_$name$$}$() const;\n"
+      "void ${1$_internal_add_$name$$}$($type$ value);\n"
+      "::$proto_ns$::RepeatedField< $type$ >*\n"
+      "    ${1$_internal_mutable_$name$$}$();\n"
+      "public:\n"
       "$deprecated_attr$$type$ ${1$$name$$}$(int index) const;\n"
       "$deprecated_attr$void ${1$set_$name$$}$(int index, $type$ value);\n"
       "$deprecated_attr$void ${1$add_$name$$}$($type$ value);\n"
@@ -326,32 +327,46 @@ void RepeatedPrimitiveFieldGenerator::GenerateInlineAccessorDefinitions(
     io::Printer* printer) const {
   Formatter format(printer, variables_);
   format(
+      "inline $type$ $classname$::_internal_$name$(int index) const {\n"
+      "  return $name$_.Get(index);\n"
+      "}\n"
       "inline $type$ $classname$::$name$(int index) const {\n"
       "$annotate_accessor$"
       "  // @@protoc_insertion_point(field_get:$full_name$)\n"
-      "  return $name$_.Get(index);\n"
+      "  return _internal_$name$(index);\n"
       "}\n"
       "inline void $classname$::set_$name$(int index, $type$ value) {\n"
       "$annotate_accessor$"
       "  $name$_.Set(index, value);\n"
       "  // @@protoc_insertion_point(field_set:$full_name$)\n"
       "}\n"
+      "inline void $classname$::_internal_add_$name$($type$ value) {\n"
+      "  $name$_.Add(value);\n"
+      "}\n"
       "inline void $classname$::add_$name$($type$ value) {\n"
       "$annotate_accessor$"
-      "  $name$_.Add(value);\n"
+      "  _internal_add_$name$(value);\n"
       "  // @@protoc_insertion_point(field_add:$full_name$)\n"
       "}\n"
       "inline const ::$proto_ns$::RepeatedField< $type$ >&\n"
+      "$classname$::_internal_$name$() const {\n"
+      "  return $name$_;\n"
+      "}\n"
+      "inline const ::$proto_ns$::RepeatedField< $type$ >&\n"
       "$classname$::$name$() const {\n"
       "$annotate_accessor$"
       "  // @@protoc_insertion_point(field_list:$full_name$)\n"
-      "  return $name$_;\n"
+      "  return _internal_$name$();\n"
+      "}\n"
+      "inline ::$proto_ns$::RepeatedField< $type$ >*\n"
+      "$classname$::_internal_mutable_$name$() {\n"
+      "  return &$name$_;\n"
       "}\n"
       "inline ::$proto_ns$::RepeatedField< $type$ >*\n"
       "$classname$::mutable_$name$() {\n"
       "$annotate_accessor$"
       "  // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
-      "  return &$name$_;\n"
+      "  return _internal_mutable_$name$();\n"
       "}\n");
 }
 
@@ -384,34 +399,15 @@ void RepeatedPrimitiveFieldGenerator::GenerateCopyConstructorCode(
   format("$name$_.CopyFrom(from.$name$_);\n");
 }
 
-void RepeatedPrimitiveFieldGenerator::GenerateMergeFromCodedStream(
-    io::Printer* printer) const {
-  Formatter format(printer, variables_);
-  format(
-      "DO_((::$proto_ns$::internal::WireFormatLite::$repeated_reader$<\n"
-      "         $type$, "
-      "::$proto_ns$::internal::WireFormatLite::$wire_format_field_type$>(\n"
-      "       $tag_size$, $tag$u, input, this->mutable_$name$())));\n");
-}
-
-void RepeatedPrimitiveFieldGenerator::GenerateMergeFromCodedStreamWithPacking(
-    io::Printer* printer) const {
-  Formatter format(printer, variables_);
-  format(
-      "DO_((::$proto_ns$::internal::WireFormatLite::$packed_reader$<\n"
-      "         $type$, "
-      "::$proto_ns$::internal::WireFormatLite::$wire_format_field_type$>(\n"
-      "       input, this->mutable_$name$())));\n");
-}
-
 void RepeatedPrimitiveFieldGenerator::GenerateSerializeWithCachedSizesToArray(
     io::Printer* printer) const {
   Formatter format(printer, variables_);
   if (descriptor_->is_packed()) {
     if (FixedSize(descriptor_->type()) > 0) {
       format(
-          "if (this->$name$_size() > 0) {\n"
-          "  target = stream->WriteFixedPacked($number$, $name$_, target);\n"
+          "if (this->_internal_$name$_size() > 0) {\n"
+          "  target = stream->WriteFixedPacked($number$, _internal_$name$(), "
+          "target);\n"
           "}\n");
     } else {
       format(
@@ -420,16 +416,17 @@ void RepeatedPrimitiveFieldGenerator::GenerateSerializeWithCachedSizesToArray(
           "_$name$_cached_byte_size_.load(std::memory_order_relaxed);\n"
           "  if (byte_size > 0) {\n"
           "    target = stream->Write$declared_type$Packed(\n"
-          "        $number$, $name$_, byte_size, target);\n"
+          "        $number$, _internal_$name$(), byte_size, target);\n"
           "  }\n"
           "}\n");
     }
   } else {
     format(
-        "for (const auto& x : this->$name$()) {\n"
+        "for (int i = 0, n = this->_internal_$name$_size(); i < n; i++) {\n"
         "  stream->EnsureSpace(&target);\n"
         "  target = ::$proto_ns$::internal::WireFormatLite::"
-        "Write$declared_type$ToArray($number$, x, target);\n"
+        "Write$declared_type$ToArray($number$, this->_internal_$name$(i), "
+        "target);\n"
         "}\n");
   }
 }
@@ -446,7 +443,8 @@ void RepeatedPrimitiveFieldGenerator::GenerateByteSize(
         "  $declared_type$Size(this->$name$_);\n");
   } else {
     format(
-        "unsigned int count = static_cast<unsigned int>(this->$name$_size());\n"
+        "unsigned int count = static_cast<unsigned "
+        "int>(this->_internal_$name$_size());\n"
         "size_t data_size = $fixed_size$UL * count;\n");
   }
 
@@ -465,7 +463,7 @@ void RepeatedPrimitiveFieldGenerator::GenerateByteSize(
     format(
         "total_size += $tag_size$ *\n"
         "              "
-        "::$proto_ns$::internal::FromIntSize(this->$name$_size());\n"
+        "::$proto_ns$::internal::FromIntSize(this->_internal_$name$_size());\n"
         "total_size += data_size;\n");
   }
   format.Outdent();

+ 0 - 4
src/google/protobuf/compiler/cpp/cpp_primitive_field.h

@@ -59,7 +59,6 @@ class PrimitiveFieldGenerator : public FieldGenerator {
   void GenerateSwappingCode(io::Printer* printer) const;
   void GenerateConstructorCode(io::Printer* printer) const;
   void GenerateCopyConstructorCode(io::Printer* printer) const;
-  void GenerateMergeFromCodedStream(io::Printer* printer) const;
   void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
   void GenerateByteSize(io::Printer* printer) const;
 
@@ -78,7 +77,6 @@ class PrimitiveOneofFieldGenerator : public PrimitiveFieldGenerator {
   void GenerateClearingCode(io::Printer* printer) const;
   void GenerateSwappingCode(io::Printer* printer) const;
   void GenerateConstructorCode(io::Printer* printer) const;
-  void GenerateMergeFromCodedStream(io::Printer* printer) const;
 
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveOneofFieldGenerator);
@@ -99,8 +97,6 @@ class RepeatedPrimitiveFieldGenerator : public FieldGenerator {
   void GenerateSwappingCode(io::Printer* printer) const;
   void GenerateConstructorCode(io::Printer* printer) const;
   void GenerateCopyConstructorCode(io::Printer* printer) const;
-  void GenerateMergeFromCodedStream(io::Printer* printer) const;
-  void GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const;
   void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
   void GenerateByteSize(io::Printer* printer) const;
 

+ 31 - 123
src/google/protobuf/compiler/cpp/cpp_string_field.cc

@@ -602,44 +602,6 @@ void StringFieldGenerator::GenerateDefaultInstanceAllocator(
   }
 }
 
-void StringFieldGenerator::GenerateMergeFromCodedStream(
-    io::Printer* printer) const {
-  Formatter format(printer, variables_);
-  // The google3 version of proto2 has ArenaStrings and parses into them
-  // directly, but for the open-source release, we always parse into std::string
-  // instances. Note that for lite, we do similarly to the open source release
-  // and use std::string, not ArenaString.
-  if (!options_.opensource_runtime && !inlined_ &&
-      SupportsArenas(descriptor_) && !lite_) {
-    // If arena != NULL, the current string is either an ArenaString (no
-    // destructor necessary) or a materialized std::string (and is on the
-    // Arena's destructor list).  No call to ArenaStringPtr::Destroy is needed.
-    format(
-        "if (arena != nullptr) {\n"
-        "  ::$proto_ns$::internal::TaggedPtr<std::string> str =\n"
-        "    ::$proto_ns$::internal::ReadArenaString(input, arena);\n"
-        "  DO_(!str.IsNull());\n"
-        "  $set_hasbit_io$\n"
-        "  $name$_.UnsafeSetTaggedPointer(str);\n"
-        "} else {\n"
-        "  DO_(::$proto_ns$::internal::WireFormatLite::Read$declared_type$(\n"
-        "        input, this->_internal_mutable_$name$()));\n"
-        "}\n");
-  } else {
-    format(
-        "DO_(::$proto_ns$::internal::WireFormatLite::Read$declared_type$(\n"
-        "      input, this->_internal_mutable_$name$()));\n");
-  }
-
-  if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
-    GenerateUtf8CheckCodeForString(
-        descriptor_, options_, true,
-        "this->_internal_$name$().data(), "
-        "static_cast<int>(this->_internal_$name$().length()),\n",
-        format);
-  }
-}
-
 bool StringFieldGenerator::MergeFromCodedStreamNeedsArena() const {
   return !lite_ && !inlined_ && !options_.opensource_runtime;
 }
@@ -682,10 +644,6 @@ StringOneofFieldGenerator::StringOneofFieldGenerator(
   variables_["field_name"] = UnderscoresToCamelCase(descriptor->name(), true);
   variables_["oneof_index"] =
       StrCat(descriptor->containing_oneof()->index());
-  // has_$name$() for oneof fields is private if has_bit is not present. In that
-  // case, use _has_$name$() instead of _internal_has_$name$().
-  variables_["internal"] =
-      HasFieldPresence(descriptor->file()) ? "_internal_" : "";
 }
 
 StringOneofFieldGenerator::~StringOneofFieldGenerator() {}
@@ -712,14 +670,14 @@ void StringOneofFieldGenerator::GenerateInlineAccessorDefinitions(
   if (SupportsArenas(descriptor_)) {
     format(
         "inline const std::string& $classname$::_internal_$name$() const {\n"
-        "  if ($internal$has_$name$()) {\n"
+        "  if (_internal_has_$name$()) {\n"
         "    return $field_member$.Get();\n"
         "  }\n"
         "  return *$default_variable$;\n"
         "}\n"
         "inline void $classname$::_internal_set_$name$(const std::string& "
         "value) {\n"
-        "  if (!$internal$has_$name$()) {\n"
+        "  if (!_internal_has_$name$()) {\n"
         "    clear_$oneof_name$();\n"
         "    set_has_$name$();\n"
         "    $field_member$.UnsafeSetDefault($default_variable$);\n"
@@ -730,7 +688,7 @@ void StringOneofFieldGenerator::GenerateInlineAccessorDefinitions(
         "inline void $classname$::set_$name$(std::string&& value) {\n"
         "$annotate_accessor$"
         "  // @@protoc_insertion_point(field_set:$full_name$)\n"
-        "  if (!has_$name$()) {\n"
+        "  if (!_internal_has_$name$()) {\n"
         "    clear_$oneof_name$();\n"
         "    set_has_$name$();\n"
         "    $field_member$.UnsafeSetDefault($default_variable$);\n"
@@ -742,7 +700,7 @@ void StringOneofFieldGenerator::GenerateInlineAccessorDefinitions(
         "inline void $classname$::set_$name$(const char* value) {\n"
         "$annotate_accessor$"
         "  $null_check$"
-        "  if (!has_$name$()) {\n"
+        "  if (!_internal_has_$name$()) {\n"
         "    clear_$oneof_name$();\n"
         "    set_has_$name$();\n"
         "    $field_member$.UnsafeSetDefault($default_variable$);\n"
@@ -755,7 +713,7 @@ void StringOneofFieldGenerator::GenerateInlineAccessorDefinitions(
       format(
           "inline void $classname$::set_$name$(::StringPiece value) {\n"
           "$annotate_accessor$"
-          "  if (!has_$name$()) {\n"
+          "  if (!_internal_has_$name$()) {\n"
           "    clear_$oneof_name$();\n"
           "    set_has_$name$();\n"
           "    $field_member$.UnsafeSetDefault($default_variable$);\n"
@@ -770,7 +728,7 @@ void StringOneofFieldGenerator::GenerateInlineAccessorDefinitions(
         "void $classname$::set_$name$(const $pointer_type$* value,\n"
         "                             size_t size) {\n"
         "$annotate_accessor$"
-        "  if (!has_$name$()) {\n"
+        "  if (!_internal_has_$name$()) {\n"
         "    clear_$oneof_name$();\n"
         "    set_has_$name$();\n"
         "    $field_member$.UnsafeSetDefault($default_variable$);\n"
@@ -782,7 +740,7 @@ void StringOneofFieldGenerator::GenerateInlineAccessorDefinitions(
         "  // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
         "}\n"
         "inline std::string* $classname$::_internal_mutable_$name$() {\n"
-        "  if (!$internal$has_$name$()) {\n"
+        "  if (!_internal_has_$name$()) {\n"
         "    clear_$oneof_name$();\n"
         "    set_has_$name$();\n"
         "    $field_member$.UnsafeSetDefault($default_variable$);\n"
@@ -793,7 +751,7 @@ void StringOneofFieldGenerator::GenerateInlineAccessorDefinitions(
         "inline std::string* $classname$::$release_name$() {\n"
         "$annotate_accessor$"
         "  // @@protoc_insertion_point(field_release:$full_name$)\n"
-        "  if (has_$name$()) {\n"
+        "  if (_internal_has_$name$()) {\n"
         "    clear_has_$oneof_name$();\n"
         "    return $field_member$.Release($default_variable$,\n"
         "        GetArenaNoVirtual());\n"
@@ -819,7 +777,7 @@ void StringOneofFieldGenerator::GenerateInlineAccessorDefinitions(
           "  // "
           "@@protoc_insertion_point(field_unsafe_arena_release:$full_name$)\n"
           "  $DCHK$(GetArenaNoVirtual() != nullptr);\n"
-          "  if (has_$name$()) {\n"
+          "  if (_internal_has_$name$()) {\n"
           "    clear_has_$oneof_name$();\n"
           "    return $field_member$.UnsafeArenaRelease(\n"
           "        $default_variable$, GetArenaNoVirtual());\n"
@@ -831,7 +789,7 @@ void StringOneofFieldGenerator::GenerateInlineAccessorDefinitions(
           "std::string* $name$) {\n"
           "$annotate_accessor$"
           "  $DCHK$(GetArenaNoVirtual() != nullptr);\n"
-          "  if (!has_$name$()) {\n"
+          "  if (!_internal_has_$name$()) {\n"
           "    $field_member$.UnsafeSetDefault($default_variable$);\n"
           "  }\n"
           "  clear_$oneof_name$();\n"
@@ -848,14 +806,14 @@ void StringOneofFieldGenerator::GenerateInlineAccessorDefinitions(
     // No-arena case.
     format(
         "inline const std::string& $classname$::_internal_$name$() const {\n"
-        "  if ($internal$has_$name$()) {\n"
+        "  if (_internal_has_$name$()) {\n"
         "    return $field_member$.GetNoArena();\n"
         "  }\n"
         "  return *$default_variable$;\n"
         "}\n"
         "inline void $classname$::_internal_set_$name$(const std::string& "
         "value) {\n"
-        "  if (!$internal$has_$name$()) {\n"
+        "  if (!_internal_has_$name$()) {\n"
         "    clear_$oneof_name$();\n"
         "    set_has_$name$();\n"
         "    $field_member$.UnsafeSetDefault($default_variable$);\n"
@@ -865,7 +823,7 @@ void StringOneofFieldGenerator::GenerateInlineAccessorDefinitions(
         "inline void $classname$::set_$name$(std::string&& value) {\n"
         "$annotate_accessor$"
         "  // @@protoc_insertion_point(field_set:$full_name$)\n"
-        "  if (!has_$name$()) {\n"
+        "  if (!_internal_has_$name$()) {\n"
         "    clear_$oneof_name$();\n"
         "    set_has_$name$();\n"
         "    $field_member$.UnsafeSetDefault($default_variable$);\n"
@@ -876,7 +834,7 @@ void StringOneofFieldGenerator::GenerateInlineAccessorDefinitions(
         "inline void $classname$::set_$name$(const char* value) {\n"
         "$annotate_accessor$"
         "  $null_check$"
-        "  if (!has_$name$()) {\n"
+        "  if (!_internal_has_$name$()) {\n"
         "    clear_$oneof_name$();\n"
         "    set_has_$name$();\n"
         "    $field_member$.UnsafeSetDefault($default_variable$);\n"
@@ -889,7 +847,7 @@ void StringOneofFieldGenerator::GenerateInlineAccessorDefinitions(
       format(
           "inline void $classname$::set_$name$(::StringPiece value) {\n"
           "$annotate_accessor$"
-          "  if (!has_$name$()) {\n"
+          "  if (!_internal_has_$name$()) {\n"
           "    clear_$oneof_name$();\n"
           "    set_has_$name$();\n"
           "    $field_member$.UnsafeSetDefault($default_variable$);\n"
@@ -903,7 +861,7 @@ void StringOneofFieldGenerator::GenerateInlineAccessorDefinitions(
         "void $classname$::set_$name$(const $pointer_type$* value, size_t "
         "size) {\n"
         "$annotate_accessor$"
-        "  if (!has_$name$()) {\n"
+        "  if (!_internal_has_$name$()) {\n"
         "    clear_$oneof_name$();\n"
         "    set_has_$name$();\n"
         "    $field_member$.UnsafeSetDefault($default_variable$);\n"
@@ -913,7 +871,7 @@ void StringOneofFieldGenerator::GenerateInlineAccessorDefinitions(
         "  // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
         "}\n"
         "inline std::string* $classname$::_internal_mutable_$name$() {\n"
-        "  if (!$internal$has_$name$()) {\n"
+        "  if (!_internal_has_$name$()) {\n"
         "    clear_$oneof_name$();\n"
         "    set_has_$name$();\n"
         "    $field_member$.UnsafeSetDefault($default_variable$);\n"
@@ -923,7 +881,7 @@ void StringOneofFieldGenerator::GenerateInlineAccessorDefinitions(
         "inline std::string* $classname$::$release_name$() {\n"
         "$annotate_accessor$"
         "  // @@protoc_insertion_point(field_release:$full_name$)\n"
-        "  if (has_$name$()) {\n"
+        "  if (_internal_has_$name$()) {\n"
         "    clear_has_$oneof_name$();\n"
         "    return $field_member$.ReleaseNoArena($default_variable$);\n"
         "  } else {\n"
@@ -978,49 +936,11 @@ void StringOneofFieldGenerator::GenerateDestructorCode(
     io::Printer* printer) const {
   Formatter format(printer, variables_);
   format(
-      "if (has_$name$()) {\n"
+      "if (_internal_has_$name$()) {\n"
       "  $field_member$.DestroyNoArena($default_variable$);\n"
       "}\n");
 }
 
-void StringOneofFieldGenerator::GenerateMergeFromCodedStream(
-    io::Printer* printer) const {
-  Formatter format(printer, variables_);
-  // See above: ArenaString is not included in the open-source release.
-  if (!options_.opensource_runtime && SupportsArenas(descriptor_) && !lite_) {
-    // If has_$name$(), then the current string is either an ArenaString (no
-    // destructor necessary) or a materialized std::string (and is on the
-    // Arena's destructor list).  No call to ArenaStringPtr::Destroy is needed.
-    format(
-        "if (arena != nullptr) {\n"
-        "  clear_$oneof_name$();\n"
-        "  if (!has_$name$()) {\n"
-        "    $field_member$.UnsafeSetDefault($default_variable$);\n"
-        "    set_has_$name$();\n"
-        "  }\n"
-        "  ::$proto_ns$::internal::TaggedPtr<std::string> new_value =\n"
-        "    ::$proto_ns$::internal::ReadArenaString(input, arena);\n"
-        "  DO_(!new_value.IsNull());\n"
-        "  $field_member$.UnsafeSetTaggedPointer(new_value);\n"
-        "} else {\n"
-        "  DO_(::$proto_ns$::internal::WireFormatLite::Read$declared_type$(\n"
-        "        input, this->_internal_mutable_$name$()));\n"
-        "}\n");
-  } else {
-    format(
-        "DO_(::$proto_ns$::internal::WireFormatLite::Read$declared_type$(\n"
-        "      input, this->_internal_mutable_$name$()));\n");
-  }
-
-  if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
-    GenerateUtf8CheckCodeForString(
-        descriptor_, options_, true,
-        "this->_internal_$name$().data(), "
-        "static_cast<int>(this->_internal_$name$().length()),\n",
-        format);
-  }
-}
-
 // ===================================================================
 
 RepeatedStringFieldGenerator::RepeatedStringFieldGenerator(
@@ -1092,6 +1012,7 @@ void RepeatedStringFieldGenerator::GenerateAccessorDeclarations(
       "${1$mutable_$name$$}$()"
       ";\n"
       "private:\n"
+      "const std::string& ${1$_internal_$name$$}$(int index) const;\n"
       "std::string* _internal_add_$name$();\n"
       "public:\n",
       descriptor_);
@@ -1114,21 +1035,24 @@ void RepeatedStringFieldGenerator::GenerateInlineAccessorDefinitions(
       "}\n");
   if (options_.safe_boundary_check) {
     format(
-        "inline const std::string& $classname$::$name$(int index) const {\n"
-        "$annotate_accessor$"
-        "  // @@protoc_insertion_point(field_get:$full_name$)\n"
+        "inline const std::string& $classname$::_internal_$name$(int index) "
+        "const {\n"
         "  return $name$_.InternalCheckedGet(\n"
         "      index, ::$proto_ns$::internal::GetEmptyStringAlreadyInited());\n"
         "}\n");
   } else {
     format(
-        "inline const std::string& $classname$::$name$(int index) const {\n"
-        "$annotate_accessor$"
-        "  // @@protoc_insertion_point(field_get:$full_name$)\n"
+        "inline const std::string& $classname$::_internal_$name$(int index) "
+        "const {\n"
         "  return $name$_.Get(index);\n"
         "}\n");
   }
   format(
+      "inline const std::string& $classname$::$name$(int index) const {\n"
+      "$annotate_accessor$"
+      "  // @@protoc_insertion_point(field_get:$full_name$)\n"
+      "  return _internal_$name$(index);\n"
+      "}\n"
       "inline std::string* $classname$::mutable_$name$(int index) {\n"
       "$annotate_accessor$"
       "  // @@protoc_insertion_point(field_mutable:$full_name$)\n"
@@ -1247,28 +1171,12 @@ void RepeatedStringFieldGenerator::GenerateCopyConstructorCode(
   format("$name$_.CopyFrom(from.$name$_);");
 }
 
-void RepeatedStringFieldGenerator::GenerateMergeFromCodedStream(
-    io::Printer* printer) const {
-  Formatter format(printer, variables_);
-  format(
-      "DO_(::$proto_ns$::internal::WireFormatLite::Read$declared_type$(\n"
-      "      input, this->_internal_add_$name$()));\n");
-  if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
-    GenerateUtf8CheckCodeForString(
-        descriptor_, options_, true,
-        "$name$_.Get($name$_.size() - 1).data(),\n"
-        "static_cast<int>($name$_.Get($name$_.size() - 1).length()),\n",
-        format);
-  }
-}
-
 void RepeatedStringFieldGenerator::GenerateSerializeWithCachedSizesToArray(
     io::Printer* printer) const {
   Formatter format(printer, variables_);
   format(
-      "for (auto it = $field_member$.pointer_begin(),\n"
-      "          end = $field_member$.pointer_end(); it < end; ++it) {\n"
-      "  const auto& s = **it;\n");
+      "for (int i = 0, n = this->_internal_$name$_size(); i < n; i++) {\n"
+      "  const auto& s = this->_internal_$name$(i);\n");
   // format("for (const std::string& s : this->$name$()) {\n");
   format.Indent();
   if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {

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

@@ -65,7 +65,6 @@ class StringFieldGenerator : public FieldGenerator {
   void GenerateDestructorCode(io::Printer* printer) const;
   bool GenerateArenaDestructorCode(io::Printer* printer) const;
   void GenerateDefaultInstanceAllocator(io::Printer* printer) const;
-  void GenerateMergeFromCodedStream(io::Printer* printer) const;
   void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
   void GenerateByteSize(io::Printer* printer) const;
   uint32 CalculateFieldTag() const;
@@ -97,7 +96,6 @@ class StringOneofFieldGenerator : public StringFieldGenerator {
   void GenerateSwappingCode(io::Printer* printer) const;
   void GenerateConstructorCode(io::Printer* printer) const;
   void GenerateDestructorCode(io::Printer* printer) const;
-  void GenerateMergeFromCodedStream(io::Printer* printer) const;
 
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringOneofFieldGenerator);
@@ -118,7 +116,6 @@ class RepeatedStringFieldGenerator : public FieldGenerator {
   void GenerateSwappingCode(io::Printer* printer) const;
   void GenerateConstructorCode(io::Printer* printer) const;
   void GenerateCopyConstructorCode(io::Printer* printer) const;
-  void GenerateMergeFromCodedStream(io::Printer* printer) const;
   void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
   void GenerateByteSize(io::Printer* printer) const;
 

+ 2 - 1
src/google/protobuf/compiler/cpp/cpp_unittest.inc

@@ -72,12 +72,13 @@
 #include <google/protobuf/stubs/callback.h>
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/substitute.h>
 #include <google/protobuf/testing/googletest.h>
 #include <gtest/gtest.h>
 #include <google/protobuf/stubs/casts.h>
+#include <google/protobuf/stubs/substitute.h>
 #include <google/protobuf/stubs/stl_util.h>
 
+// Must be included last.
 #include <google/protobuf/port_def.inc>
 
 namespace google {

+ 1 - 1
src/google/protobuf/compiler/importer_unittest.cc

@@ -44,9 +44,9 @@
 #include <google/protobuf/testing/file.h>
 #include <google/protobuf/io/zero_copy_stream_impl.h>
 #include <google/protobuf/descriptor.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/stubs/map_util.h>
 #include <google/protobuf/stubs/strutil.h>
 

+ 2 - 1
src/google/protobuf/compiler/java/java_file.cc

@@ -237,7 +237,8 @@ bool FileGenerator::Validate(std::string* error) {
   }
 
   // Print a warning if optimize_for = LITE_RUNTIME is used.
-  if (file_->options().optimize_for() == FileOptions::LITE_RUNTIME) {
+  if (file_->options().optimize_for() == FileOptions::LITE_RUNTIME &&
+      !options_.enforce_lite) {
     GOOGLE_LOG(WARNING)
         << "The optimize_for = LITE_RUNTIME option is no longer supported by "
         << "protobuf Java code generator and is ignored--protoc will always "

+ 2 - 1
src/google/protobuf/compiler/java/java_helpers.cc

@@ -32,13 +32,14 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
+#include <google/protobuf/compiler/java/java_helpers.h>
+
 #include <algorithm>
 #include <limits>
 #include <unordered_set>
 #include <vector>
 
 #include <google/protobuf/stubs/stringprintf.h>
-#include <google/protobuf/compiler/java/java_helpers.h>
 #include <google/protobuf/compiler/java/java_name_resolver.h>
 #include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/wire_format.h>

+ 1 - 1
src/google/protobuf/compiler/java/java_helpers.h

@@ -369,7 +369,7 @@ inline bool SupportUnknownEnumValue(const FileDescriptor* descriptor) {
   return descriptor->syntax() == FileDescriptor::SYNTAX_PROTO3;
 }
 
-// Check whether a mesasge has repeated fields.
+// Check whether a message has repeated fields.
 bool HasRepeatedFields(const Descriptor* descriptor);
 
 inline bool IsMapEntry(const Descriptor* descriptor) {

+ 7 - 3
src/google/protobuf/compiler/java/java_message.cc

@@ -415,9 +415,13 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) {
                    "private int $oneof_name$Case_ = 0;\n"
                    "private java.lang.Object $oneof_name$_;\n");
     // OneofCase enum
-    printer->Print(vars,
-                   "public enum $oneof_capitalized_name$Case\n"
-                   "    implements com.google.protobuf.Internal.EnumLite {\n");
+    printer->Print(
+        vars,
+        "public enum $oneof_capitalized_name$Case\n"
+        // TODO(dweis): Remove EnumLite when we want to break compatibility with
+        // 3.x users
+        "    implements com.google.protobuf.Internal.EnumLite,\n"
+        "        com.google.protobuf.AbstractMessage.InternalOneOfEnum {\n");
     printer->Indent();
     for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
       const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);

+ 3 - 4
src/google/protobuf/compiler/java/java_message_lite.cc

@@ -235,9 +235,7 @@ void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) {
                    "private int $oneof_name$Case_ = 0;\n"
                    "private java.lang.Object $oneof_name$_;\n");
     // OneofCase enum
-    printer->Print(vars,
-                   "public enum $oneof_capitalized_name$Case\n"
-                   "    implements com.google.protobuf.Internal.EnumLite {\n");
+    printer->Print(vars, "public enum $oneof_capitalized_name$Case {\n");
     printer->Indent();
     for (int j = 0; j < oneof->field_count(); j++) {
       const FieldDescriptor* field = oneof->field(j);
@@ -275,7 +273,8 @@ void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) {
         "    default: return null;\n"
         "  }\n"
         "}\n"
-        "@java.lang.Override\n"
+        // TODO(b/135620659): Rename this to "getFieldNumber" or something to
+        // disambiguate it from actual proto enums.
         "public int getNumber() {\n"
         "  return this.value;\n"
         "}\n",

+ 2 - 1
src/google/protobuf/compiler/java/java_string_field.cc

@@ -838,7 +838,8 @@ void RepeatedImmutableStringFieldGenerator::GenerateBuilderMembers(
                  "  return $name$_.get(index);\n"
                  "}\n");
   printer->Annotate("{", "}", descriptor_);
-  WriteFieldStringBytesAccessorDocComment(printer, descriptor_, LIST_ADDER);
+  WriteFieldStringBytesAccessorDocComment(printer, descriptor_,
+                                          LIST_INDEXED_GETTER);
   printer->Print(variables_,
                  "$deprecation$public com.google.protobuf.ByteString\n"
                  "    ${$get$capitalized_name$Bytes$}$(int index) {\n"

+ 7 - 0
src/google/protobuf/compiler/js/js_generator.cc

@@ -3142,6 +3142,13 @@ void Generator::GenerateClassDeserializeBinaryField(
       printer->Print(", null");
     }
     printer->Print(", $defaultKey$", "defaultKey", JSFieldDefault(key_field));
+    if (value_field->type() == FieldDescriptor::TYPE_MESSAGE) {
+      printer->Print(", new $messageType$()", "messageType",
+                     GetMessagePath(options, value_field->message_type()));
+    } else {
+      printer->Print(", $defaultValue$", "defaultValue",
+                     JSFieldDefault(value_field));
+    }
     printer->Print(");\n");
     printer->Print("         });\n");
   } else {

+ 3 - 2
src/google/protobuf/compiler/mock_code_generator.cc

@@ -33,11 +33,12 @@
 #include <google/protobuf/compiler/mock_code_generator.h>
 
 #include <stdlib.h>
+
 #include <iostream>
 #include <memory>
 #include <vector>
-#include <google/protobuf/stubs/strutil.h>
 
+#include <google/protobuf/stubs/strutil.h>
 
 #include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/stubs/common.h>
@@ -50,8 +51,8 @@
 #include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/descriptor.h>
 #include <google/protobuf/text_format.h>
-#include <google/protobuf/stubs/substitute.h>
 #include <gtest/gtest.h>
+#include <google/protobuf/stubs/substitute.h>
 
 #ifdef major
 #undef major

+ 2 - 1
src/google/protobuf/compiler/parser.cc

@@ -2206,7 +2206,8 @@ bool Parser::ParseMethodOptions(const LocationRecorder& parent_location,
 bool Parser::ParseLabel(FieldDescriptorProto::Label* label,
                         const LocationRecorder& field_location,
                         const FileDescriptorProto* containing_file) {
-  if (!LookingAt("optional") && !LookingAt("repeated") && !LookingAt("required")) {
+  if (!LookingAt("optional") && !LookingAt("repeated") &&
+      !LookingAt("required")) {
     return false;
   }
   LocationRecorder location(field_location,

+ 4 - 5
src/google/protobuf/compiler/parser_unittest.cc

@@ -32,13 +32,13 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
+#include <google/protobuf/compiler/parser.h>
+
 #include <algorithm>
 #include <map>
 #include <memory>
 #include <vector>
 
-#include <google/protobuf/compiler/parser.h>
-
 #include <google/protobuf/test_util2.h>
 #include <google/protobuf/unittest.pb.h>
 #include <google/protobuf/unittest_custom_options.pb.h>
@@ -47,11 +47,10 @@
 #include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/text_format.h>
 #include <google/protobuf/wire_format.h>
-#include <google/protobuf/stubs/substitute.h>
-#include <google/protobuf/stubs/map_util.h>
-
 #include <google/protobuf/testing/googletest.h>
 #include <gtest/gtest.h>
+#include <google/protobuf/stubs/substitute.h>
+#include <google/protobuf/stubs/map_util.h>
 
 namespace google {
 namespace protobuf {

+ 22 - 329
src/google/protobuf/compiler/plugin.pb.cc

@@ -289,7 +289,6 @@ void Version::Clear() {
   _internal_metadata_.Clear();
 }
 
-#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 const char* Version::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   _Internal::HasBits has_bits{};
@@ -349,91 +348,6 @@ failure:
   goto success;
 #undef CHK_
 }
-#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
-bool Version::MergePartialFromCodedStream(
-    ::PROTOBUF_NAMESPACE_ID::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
-  ::PROTOBUF_NAMESPACE_ID::uint32 tag;
-  // @@protoc_insertion_point(parse_start:google.protobuf.compiler.Version)
-  for (;;) {
-    ::std::pair<::PROTOBUF_NAMESPACE_ID::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
-    tag = p.first;
-    if (!p.second) goto handle_unusual;
-    switch (::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::GetTagFieldNumber(tag)) {
-      // optional int32 major = 1;
-      case 1: {
-        if (static_cast< ::PROTOBUF_NAMESPACE_ID::uint8>(tag) == (8 & 0xFF)) {
-          _Internal::set_has_major(&_has_bits_);
-          DO_((::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::ReadPrimitive<
-                   ::PROTOBUF_NAMESPACE_ID::int32, ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::TYPE_INT32>(
-                 input, &major_)));
-        } else {
-          goto handle_unusual;
-        }
-        break;
-      }
-
-      // optional int32 minor = 2;
-      case 2: {
-        if (static_cast< ::PROTOBUF_NAMESPACE_ID::uint8>(tag) == (16 & 0xFF)) {
-          _Internal::set_has_minor(&_has_bits_);
-          DO_((::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::ReadPrimitive<
-                   ::PROTOBUF_NAMESPACE_ID::int32, ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::TYPE_INT32>(
-                 input, &minor_)));
-        } else {
-          goto handle_unusual;
-        }
-        break;
-      }
-
-      // optional int32 patch = 3;
-      case 3: {
-        if (static_cast< ::PROTOBUF_NAMESPACE_ID::uint8>(tag) == (24 & 0xFF)) {
-          _Internal::set_has_patch(&_has_bits_);
-          DO_((::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::ReadPrimitive<
-                   ::PROTOBUF_NAMESPACE_ID::int32, ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::TYPE_INT32>(
-                 input, &patch_)));
-        } else {
-          goto handle_unusual;
-        }
-        break;
-      }
-
-      // optional string suffix = 4;
-      case 4: {
-        if (static_cast< ::PROTOBUF_NAMESPACE_ID::uint8>(tag) == (34 & 0xFF)) {
-          DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::ReadString(
-                input, this->_internal_mutable_suffix()));
-          ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField(
-            this->_internal_suffix().data(), static_cast<int>(this->_internal_suffix().length()),
-            ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::PARSE,
-            "google.protobuf.compiler.Version.suffix");
-        } else {
-          goto handle_unusual;
-        }
-        break;
-      }
-
-      default: {
-      handle_unusual:
-        if (tag == 0) {
-          goto success;
-        }
-        DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SkipField(
-              input, tag, _internal_metadata_.mutable_unknown_fields()));
-        break;
-      }
-    }
-  }
-success:
-  // @@protoc_insertion_point(parse_success:google.protobuf.compiler.Version)
-  return true;
-failure:
-  // @@protoc_insertion_point(parse_failure:google.protobuf.compiler.Version)
-  return false;
-#undef DO_
-}
-#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 
 ::PROTOBUF_NAMESPACE_ID::uint8* Version::InternalSerializeWithCachedSizesToArray(
     ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
@@ -445,19 +359,19 @@ failure:
   // optional int32 major = 1;
   if (cached_has_bits & 0x00000002u) {
     stream->EnsureSpace(&target);
-    target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(1, this->major(), target);
+    target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(1, this->_internal_major(), target);
   }
 
   // optional int32 minor = 2;
   if (cached_has_bits & 0x00000004u) {
     stream->EnsureSpace(&target);
-    target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(2, this->minor(), target);
+    target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(2, this->_internal_minor(), target);
   }
 
   // optional int32 patch = 3;
   if (cached_has_bits & 0x00000008u) {
     stream->EnsureSpace(&target);
-    target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(3, this->patch(), target);
+    target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(3, this->_internal_patch(), target);
   }
 
   // optional string suffix = 4;
@@ -499,21 +413,21 @@ size_t Version::ByteSizeLong() const {
     if (cached_has_bits & 0x00000002u) {
       total_size += 1 +
         ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size(
-          this->major());
+          this->_internal_major());
     }
 
     // optional int32 minor = 2;
     if (cached_has_bits & 0x00000004u) {
       total_size += 1 +
         ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size(
-          this->minor());
+          this->_internal_minor());
     }
 
     // optional int32 patch = 3;
     if (cached_has_bits & 0x00000008u) {
       total_size += 1 +
         ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size(
-          this->patch());
+          this->_internal_patch());
     }
 
   }
@@ -642,7 +556,7 @@ CodeGeneratorRequest::CodeGeneratorRequest(const CodeGeneratorRequest& from)
   if (from._internal_has_parameter()) {
     parameter_.AssignWithDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from.parameter_);
   }
-  if (from.has_compiler_version()) {
+  if (from._internal_has_compiler_version()) {
     compiler_version_ = new PROTOBUF_NAMESPACE_ID::compiler::Version(*from.compiler_version_);
   } else {
     compiler_version_ = nullptr;
@@ -697,7 +611,6 @@ void CodeGeneratorRequest::Clear() {
   _internal_metadata_.Clear();
 }
 
-#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 const char* CodeGeneratorRequest::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   _Internal::HasBits has_bits{};
@@ -728,7 +641,7 @@ const char* CodeGeneratorRequest::_InternalParse(const char* ptr, ::PROTOBUF_NAM
       // optional .google.protobuf.compiler.Version compiler_version = 3;
       case 3:
         if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 26)) {
-          ptr = ctx->ParseMessage(mutable_compiler_version(), ptr);
+          ptr = ctx->ParseMessage(_internal_mutable_compiler_version(), ptr);
           CHK_(ptr);
         } else goto handle_unusual;
         continue;
@@ -738,7 +651,7 @@ const char* CodeGeneratorRequest::_InternalParse(const char* ptr, ::PROTOBUF_NAM
           ptr -= 1;
           do {
             ptr += 1;
-            ptr = ctx->ParseMessage(add_proto_file(), ptr);
+            ptr = ctx->ParseMessage(_internal_add_proto_file(), ptr);
             CHK_(ptr);
             if (!ctx->DataAvailable(ptr)) break;
           } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<122>(ptr));
@@ -764,90 +677,6 @@ failure:
   goto success;
 #undef CHK_
 }
-#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
-bool CodeGeneratorRequest::MergePartialFromCodedStream(
-    ::PROTOBUF_NAMESPACE_ID::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
-  ::PROTOBUF_NAMESPACE_ID::uint32 tag;
-  // @@protoc_insertion_point(parse_start:google.protobuf.compiler.CodeGeneratorRequest)
-  for (;;) {
-    ::std::pair<::PROTOBUF_NAMESPACE_ID::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
-    tag = p.first;
-    if (!p.second) goto handle_unusual;
-    switch (::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::GetTagFieldNumber(tag)) {
-      // repeated string file_to_generate = 1;
-      case 1: {
-        if (static_cast< ::PROTOBUF_NAMESPACE_ID::uint8>(tag) == (10 & 0xFF)) {
-          DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::ReadString(
-                input, this->_internal_add_file_to_generate()));
-          ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField(
-            file_to_generate_.Get(file_to_generate_.size() - 1).data(),
-            static_cast<int>(file_to_generate_.Get(file_to_generate_.size() - 1).length()),
-            ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::PARSE,
-            "google.protobuf.compiler.CodeGeneratorRequest.file_to_generate");
-        } else {
-          goto handle_unusual;
-        }
-        break;
-      }
-
-      // optional string parameter = 2;
-      case 2: {
-        if (static_cast< ::PROTOBUF_NAMESPACE_ID::uint8>(tag) == (18 & 0xFF)) {
-          DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::ReadString(
-                input, this->_internal_mutable_parameter()));
-          ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField(
-            this->_internal_parameter().data(), static_cast<int>(this->_internal_parameter().length()),
-            ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::PARSE,
-            "google.protobuf.compiler.CodeGeneratorRequest.parameter");
-        } else {
-          goto handle_unusual;
-        }
-        break;
-      }
-
-      // optional .google.protobuf.compiler.Version compiler_version = 3;
-      case 3: {
-        if (static_cast< ::PROTOBUF_NAMESPACE_ID::uint8>(tag) == (26 & 0xFF)) {
-          DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::ReadMessage(
-               input, mutable_compiler_version()));
-        } else {
-          goto handle_unusual;
-        }
-        break;
-      }
-
-      // repeated .google.protobuf.FileDescriptorProto proto_file = 15;
-      case 15: {
-        if (static_cast< ::PROTOBUF_NAMESPACE_ID::uint8>(tag) == (122 & 0xFF)) {
-          DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::ReadMessage(
-                input, add_proto_file()));
-        } else {
-          goto handle_unusual;
-        }
-        break;
-      }
-
-      default: {
-      handle_unusual:
-        if (tag == 0) {
-          goto success;
-        }
-        DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SkipField(
-              input, tag, _internal_metadata_.mutable_unknown_fields()));
-        break;
-      }
-    }
-  }
-success:
-  // @@protoc_insertion_point(parse_success:google.protobuf.compiler.CodeGeneratorRequest)
-  return true;
-failure:
-  // @@protoc_insertion_point(parse_failure:google.protobuf.compiler.CodeGeneratorRequest)
-  return false;
-#undef DO_
-}
-#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 
 ::PROTOBUF_NAMESPACE_ID::uint8* CodeGeneratorRequest::InternalSerializeWithCachedSizesToArray(
     ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
@@ -856,9 +685,8 @@ failure:
   (void) cached_has_bits;
 
   // repeated string file_to_generate = 1;
-  for (auto it = file_to_generate_.pointer_begin(),
-            end = file_to_generate_.pointer_end(); it < end; ++it) {
-    const auto& s = **it;
+  for (int i = 0, n = this->_internal_file_to_generate_size(); i < n; i++) {
+    const auto& s = this->_internal_file_to_generate(i);
     ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField(
       s.data(), static_cast<int>(s.length()),
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE,
@@ -886,11 +714,11 @@ failure:
   }
 
   // repeated .google.protobuf.FileDescriptorProto proto_file = 15;
-  for (auto it = this->proto_file_.pointer_begin(),
-            end = this->proto_file_.pointer_end(); it < end; ++it) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->_internal_proto_file_size()); i < n; i++) {
     stream->EnsureSpace(&target);
     target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::
-      InternalWriteMessageToArray(15, **it, target, stream);
+      InternalWriteMessageToArray(15, this->_internal_proto_file(i), target, stream);
   }
 
   if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) {
@@ -918,7 +746,7 @@ size_t CodeGeneratorRequest::ByteSizeLong() const {
   }
 
   // repeated .google.protobuf.FileDescriptorProto proto_file = 15;
-  total_size += 1UL * this->proto_file_size();
+  total_size += 1UL * this->_internal_proto_file_size();
   for (const auto& msg : this->proto_file_) {
     total_size +=
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg);
@@ -981,7 +809,7 @@ void CodeGeneratorRequest::MergeFrom(const CodeGeneratorRequest& from) {
       parameter_.AssignWithDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from.parameter_);
     }
     if (cached_has_bits & 0x00000002u) {
-      mutable_compiler_version()->PROTOBUF_NAMESPACE_ID::compiler::Version::MergeFrom(from.compiler_version());
+      _internal_mutable_compiler_version()->PROTOBUF_NAMESPACE_ID::compiler::Version::MergeFrom(from._internal_compiler_version());
     }
   }
 }
@@ -1113,7 +941,6 @@ void CodeGeneratorResponse_File::Clear() {
   _internal_metadata_.Clear();
 }
 
-#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 const char* CodeGeneratorResponse_File::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   _Internal::HasBits has_bits{};
@@ -1163,82 +990,6 @@ failure:
   goto success;
 #undef CHK_
 }
-#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
-bool CodeGeneratorResponse_File::MergePartialFromCodedStream(
-    ::PROTOBUF_NAMESPACE_ID::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
-  ::PROTOBUF_NAMESPACE_ID::uint32 tag;
-  // @@protoc_insertion_point(parse_start:google.protobuf.compiler.CodeGeneratorResponse.File)
-  for (;;) {
-    ::std::pair<::PROTOBUF_NAMESPACE_ID::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
-    tag = p.first;
-    if (!p.second) goto handle_unusual;
-    switch (::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::GetTagFieldNumber(tag)) {
-      // optional string name = 1;
-      case 1: {
-        if (static_cast< ::PROTOBUF_NAMESPACE_ID::uint8>(tag) == (10 & 0xFF)) {
-          DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::ReadString(
-                input, this->_internal_mutable_name()));
-          ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField(
-            this->_internal_name().data(), static_cast<int>(this->_internal_name().length()),
-            ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::PARSE,
-            "google.protobuf.compiler.CodeGeneratorResponse.File.name");
-        } else {
-          goto handle_unusual;
-        }
-        break;
-      }
-
-      // optional string insertion_point = 2;
-      case 2: {
-        if (static_cast< ::PROTOBUF_NAMESPACE_ID::uint8>(tag) == (18 & 0xFF)) {
-          DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::ReadString(
-                input, this->_internal_mutable_insertion_point()));
-          ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField(
-            this->_internal_insertion_point().data(), static_cast<int>(this->_internal_insertion_point().length()),
-            ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::PARSE,
-            "google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point");
-        } else {
-          goto handle_unusual;
-        }
-        break;
-      }
-
-      // optional string content = 15;
-      case 15: {
-        if (static_cast< ::PROTOBUF_NAMESPACE_ID::uint8>(tag) == (122 & 0xFF)) {
-          DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::ReadString(
-                input, this->_internal_mutable_content()));
-          ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField(
-            this->_internal_content().data(), static_cast<int>(this->_internal_content().length()),
-            ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::PARSE,
-            "google.protobuf.compiler.CodeGeneratorResponse.File.content");
-        } else {
-          goto handle_unusual;
-        }
-        break;
-      }
-
-      default: {
-      handle_unusual:
-        if (tag == 0) {
-          goto success;
-        }
-        DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SkipField(
-              input, tag, _internal_metadata_.mutable_unknown_fields()));
-        break;
-      }
-    }
-  }
-success:
-  // @@protoc_insertion_point(parse_success:google.protobuf.compiler.CodeGeneratorResponse.File)
-  return true;
-failure:
-  // @@protoc_insertion_point(parse_failure:google.protobuf.compiler.CodeGeneratorResponse.File)
-  return false;
-#undef DO_
-}
-#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 
 ::PROTOBUF_NAMESPACE_ID::uint8* CodeGeneratorResponse_File::InternalSerializeWithCachedSizesToArray(
     ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
@@ -1468,7 +1219,6 @@ void CodeGeneratorResponse::Clear() {
   _internal_metadata_.Clear();
 }
 
-#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 const char* CodeGeneratorResponse::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   _Internal::HasBits has_bits{};
@@ -1490,7 +1240,7 @@ const char* CodeGeneratorResponse::_InternalParse(const char* ptr, ::PROTOBUF_NA
           ptr -= 1;
           do {
             ptr += 1;
-            ptr = ctx->ParseMessage(add_file(), ptr);
+            ptr = ctx->ParseMessage(_internal_add_file(), ptr);
             CHK_(ptr);
             if (!ctx->DataAvailable(ptr)) break;
           } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<122>(ptr));
@@ -1516,63 +1266,6 @@ failure:
   goto success;
 #undef CHK_
 }
-#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
-bool CodeGeneratorResponse::MergePartialFromCodedStream(
-    ::PROTOBUF_NAMESPACE_ID::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
-  ::PROTOBUF_NAMESPACE_ID::uint32 tag;
-  // @@protoc_insertion_point(parse_start:google.protobuf.compiler.CodeGeneratorResponse)
-  for (;;) {
-    ::std::pair<::PROTOBUF_NAMESPACE_ID::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
-    tag = p.first;
-    if (!p.second) goto handle_unusual;
-    switch (::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::GetTagFieldNumber(tag)) {
-      // optional string error = 1;
-      case 1: {
-        if (static_cast< ::PROTOBUF_NAMESPACE_ID::uint8>(tag) == (10 & 0xFF)) {
-          DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::ReadString(
-                input, this->_internal_mutable_error()));
-          ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField(
-            this->_internal_error().data(), static_cast<int>(this->_internal_error().length()),
-            ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::PARSE,
-            "google.protobuf.compiler.CodeGeneratorResponse.error");
-        } else {
-          goto handle_unusual;
-        }
-        break;
-      }
-
-      // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
-      case 15: {
-        if (static_cast< ::PROTOBUF_NAMESPACE_ID::uint8>(tag) == (122 & 0xFF)) {
-          DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::ReadMessage(
-                input, add_file()));
-        } else {
-          goto handle_unusual;
-        }
-        break;
-      }
-
-      default: {
-      handle_unusual:
-        if (tag == 0) {
-          goto success;
-        }
-        DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SkipField(
-              input, tag, _internal_metadata_.mutable_unknown_fields()));
-        break;
-      }
-    }
-  }
-success:
-  // @@protoc_insertion_point(parse_success:google.protobuf.compiler.CodeGeneratorResponse)
-  return true;
-failure:
-  // @@protoc_insertion_point(parse_failure:google.protobuf.compiler.CodeGeneratorResponse)
-  return false;
-#undef DO_
-}
-#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 
 ::PROTOBUF_NAMESPACE_ID::uint8* CodeGeneratorResponse::InternalSerializeWithCachedSizesToArray(
     ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
@@ -1592,11 +1285,11 @@ failure:
   }
 
   // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
-  for (auto it = this->file_.pointer_begin(),
-            end = this->file_.pointer_end(); it < end; ++it) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->_internal_file_size()); i < n; i++) {
     stream->EnsureSpace(&target);
     target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::
-      InternalWriteMessageToArray(15, **it, target, stream);
+      InternalWriteMessageToArray(15, this->_internal_file(i), target, stream);
   }
 
   if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) {
@@ -1616,7 +1309,7 @@ size_t CodeGeneratorResponse::ByteSizeLong() const {
   (void) cached_has_bits;
 
   // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
-  total_size += 1UL * this->file_size();
+  total_size += 1UL * this->_internal_file_size();
   for (const auto& msg : this->file_) {
     total_size +=
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg);
@@ -1662,7 +1355,7 @@ void CodeGeneratorResponse::MergeFrom(const CodeGeneratorResponse& from) {
   (void) cached_has_bits;
 
   file_.MergeFrom(from.file_);
-  if (from.has_error()) {
+  if (from._internal_has_error()) {
     _has_bits_[0] |= 0x00000001u;
     error_.AssignWithDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from.error_);
   }

+ 121 - 48
src/google/protobuf/compiler/plugin.pb.h

@@ -164,12 +164,7 @@ class PROTOC_EXPORT Version :
   bool IsInitialized() const final;
 
   size_t ByteSizeLong() const final;
-  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
   const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
-  #else
-  bool MergePartialFromCodedStream(
-      ::PROTOBUF_NAMESPACE_ID::io::CodedInputStream* input) final;
-  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
   ::PROTOBUF_NAMESPACE_ID::uint8* InternalSerializeWithCachedSizesToArray(
       ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
   int GetCachedSize() const final { return _cached_size_.Get(); }
@@ -239,6 +234,10 @@ class PROTOC_EXPORT Version :
   void clear_major();
   ::PROTOBUF_NAMESPACE_ID::int32 major() const;
   void set_major(::PROTOBUF_NAMESPACE_ID::int32 value);
+  private:
+  ::PROTOBUF_NAMESPACE_ID::int32 _internal_major() const;
+  void _internal_set_major(::PROTOBUF_NAMESPACE_ID::int32 value);
+  public:
 
   // optional int32 minor = 2;
   bool has_minor() const;
@@ -248,6 +247,10 @@ class PROTOC_EXPORT Version :
   void clear_minor();
   ::PROTOBUF_NAMESPACE_ID::int32 minor() const;
   void set_minor(::PROTOBUF_NAMESPACE_ID::int32 value);
+  private:
+  ::PROTOBUF_NAMESPACE_ID::int32 _internal_minor() const;
+  void _internal_set_minor(::PROTOBUF_NAMESPACE_ID::int32 value);
+  public:
 
   // optional int32 patch = 3;
   bool has_patch() const;
@@ -257,6 +260,10 @@ class PROTOC_EXPORT Version :
   void clear_patch();
   ::PROTOBUF_NAMESPACE_ID::int32 patch() const;
   void set_patch(::PROTOBUF_NAMESPACE_ID::int32 value);
+  private:
+  ::PROTOBUF_NAMESPACE_ID::int32 _internal_patch() const;
+  void _internal_set_patch(::PROTOBUF_NAMESPACE_ID::int32 value);
+  public:
 
   // @@protoc_insertion_point(class_scope:google.protobuf.compiler.Version)
  private:
@@ -349,12 +356,7 @@ class PROTOC_EXPORT CodeGeneratorRequest :
   bool IsInitialized() const final;
 
   size_t ByteSizeLong() const final;
-  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
   const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
-  #else
-  bool MergePartialFromCodedStream(
-      ::PROTOBUF_NAMESPACE_ID::io::CodedInputStream* input) final;
-  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
   ::PROTOBUF_NAMESPACE_ID::uint8* InternalSerializeWithCachedSizesToArray(
       ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
   int GetCachedSize() const final { return _cached_size_.Get(); }
@@ -398,6 +400,9 @@ class PROTOC_EXPORT CodeGeneratorRequest :
   };
   // repeated string file_to_generate = 1;
   int file_to_generate_size() const;
+  private:
+  int _internal_file_to_generate_size() const;
+  public:
   void clear_file_to_generate();
   const std::string& file_to_generate(int index) const;
   std::string* mutable_file_to_generate(int index);
@@ -413,15 +418,23 @@ class PROTOC_EXPORT CodeGeneratorRequest :
   const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<std::string>& file_to_generate() const;
   ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<std::string>* mutable_file_to_generate();
   private:
+  const std::string& _internal_file_to_generate(int index) const;
   std::string* _internal_add_file_to_generate();
   public:
 
   // repeated .google.protobuf.FileDescriptorProto proto_file = 15;
   int proto_file_size() const;
+  private:
+  int _internal_proto_file_size() const;
+  public:
   void clear_proto_file();
   PROTOBUF_NAMESPACE_ID::FileDescriptorProto* mutable_proto_file(int index);
   ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::FileDescriptorProto >*
       mutable_proto_file();
+  private:
+  const PROTOBUF_NAMESPACE_ID::FileDescriptorProto& _internal_proto_file(int index) const;
+  PROTOBUF_NAMESPACE_ID::FileDescriptorProto* _internal_add_proto_file();
+  public:
   const PROTOBUF_NAMESPACE_ID::FileDescriptorProto& proto_file(int index) const;
   PROTOBUF_NAMESPACE_ID::FileDescriptorProto* add_proto_file();
   const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::FileDescriptorProto >&
@@ -457,6 +470,10 @@ class PROTOC_EXPORT CodeGeneratorRequest :
   PROTOBUF_NAMESPACE_ID::compiler::Version* release_compiler_version();
   PROTOBUF_NAMESPACE_ID::compiler::Version* mutable_compiler_version();
   void set_allocated_compiler_version(PROTOBUF_NAMESPACE_ID::compiler::Version* compiler_version);
+  private:
+  const PROTOBUF_NAMESPACE_ID::compiler::Version& _internal_compiler_version() const;
+  PROTOBUF_NAMESPACE_ID::compiler::Version* _internal_mutable_compiler_version();
+  public:
 
   // @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorRequest)
  private:
@@ -549,12 +566,7 @@ class PROTOC_EXPORT CodeGeneratorResponse_File :
   bool IsInitialized() const final;
 
   size_t ByteSizeLong() const final;
-  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
   const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
-  #else
-  bool MergePartialFromCodedStream(
-      ::PROTOBUF_NAMESPACE_ID::io::CodedInputStream* input) final;
-  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
   ::PROTOBUF_NAMESPACE_ID::uint8* InternalSerializeWithCachedSizesToArray(
       ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
   int GetCachedSize() const final { return _cached_size_.Get(); }
@@ -745,12 +757,7 @@ class PROTOC_EXPORT CodeGeneratorResponse :
   bool IsInitialized() const final;
 
   size_t ByteSizeLong() const final;
-  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
   const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
-  #else
-  bool MergePartialFromCodedStream(
-      ::PROTOBUF_NAMESPACE_ID::io::CodedInputStream* input) final;
-  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
   ::PROTOBUF_NAMESPACE_ID::uint8* InternalSerializeWithCachedSizesToArray(
       ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
   int GetCachedSize() const final { return _cached_size_.Get(); }
@@ -794,10 +801,17 @@ class PROTOC_EXPORT CodeGeneratorResponse :
   };
   // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
   int file_size() const;
+  private:
+  int _internal_file_size() const;
+  public:
   void clear_file();
   PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File* mutable_file(int index);
   ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File >*
       mutable_file();
+  private:
+  const PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File& _internal_file(int index) const;
+  PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File* _internal_add_file();
+  public:
   const PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File& file(int index) const;
   PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File* add_file();
   const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File >&
@@ -847,7 +861,8 @@ class PROTOC_EXPORT CodeGeneratorResponse :
 
 // optional int32 major = 1;
 inline bool Version::_internal_has_major() const {
-  return (_has_bits_[0] & 0x00000002u) != 0;
+  bool value = (_has_bits_[0] & 0x00000002u) != 0;
+  return value;
 }
 inline bool Version::has_major() const {
   return _internal_has_major();
@@ -856,19 +871,26 @@ inline void Version::clear_major() {
   major_ = 0;
   _has_bits_[0] &= ~0x00000002u;
 }
+inline ::PROTOBUF_NAMESPACE_ID::int32 Version::_internal_major() const {
+  return major_;
+}
 inline ::PROTOBUF_NAMESPACE_ID::int32 Version::major() const {
   // @@protoc_insertion_point(field_get:google.protobuf.compiler.Version.major)
-  return major_;
+  return _internal_major();
 }
-inline void Version::set_major(::PROTOBUF_NAMESPACE_ID::int32 value) {
+inline void Version::_internal_set_major(::PROTOBUF_NAMESPACE_ID::int32 value) {
   _has_bits_[0] |= 0x00000002u;
   major_ = value;
+}
+inline void Version::set_major(::PROTOBUF_NAMESPACE_ID::int32 value) {
+  _internal_set_major(value);
   // @@protoc_insertion_point(field_set:google.protobuf.compiler.Version.major)
 }
 
 // optional int32 minor = 2;
 inline bool Version::_internal_has_minor() const {
-  return (_has_bits_[0] & 0x00000004u) != 0;
+  bool value = (_has_bits_[0] & 0x00000004u) != 0;
+  return value;
 }
 inline bool Version::has_minor() const {
   return _internal_has_minor();
@@ -877,19 +899,26 @@ inline void Version::clear_minor() {
   minor_ = 0;
   _has_bits_[0] &= ~0x00000004u;
 }
+inline ::PROTOBUF_NAMESPACE_ID::int32 Version::_internal_minor() const {
+  return minor_;
+}
 inline ::PROTOBUF_NAMESPACE_ID::int32 Version::minor() const {
   // @@protoc_insertion_point(field_get:google.protobuf.compiler.Version.minor)
-  return minor_;
+  return _internal_minor();
 }
-inline void Version::set_minor(::PROTOBUF_NAMESPACE_ID::int32 value) {
+inline void Version::_internal_set_minor(::PROTOBUF_NAMESPACE_ID::int32 value) {
   _has_bits_[0] |= 0x00000004u;
   minor_ = value;
+}
+inline void Version::set_minor(::PROTOBUF_NAMESPACE_ID::int32 value) {
+  _internal_set_minor(value);
   // @@protoc_insertion_point(field_set:google.protobuf.compiler.Version.minor)
 }
 
 // optional int32 patch = 3;
 inline bool Version::_internal_has_patch() const {
-  return (_has_bits_[0] & 0x00000008u) != 0;
+  bool value = (_has_bits_[0] & 0x00000008u) != 0;
+  return value;
 }
 inline bool Version::has_patch() const {
   return _internal_has_patch();
@@ -898,19 +927,26 @@ inline void Version::clear_patch() {
   patch_ = 0;
   _has_bits_[0] &= ~0x00000008u;
 }
+inline ::PROTOBUF_NAMESPACE_ID::int32 Version::_internal_patch() const {
+  return patch_;
+}
 inline ::PROTOBUF_NAMESPACE_ID::int32 Version::patch() const {
   // @@protoc_insertion_point(field_get:google.protobuf.compiler.Version.patch)
-  return patch_;
+  return _internal_patch();
 }
-inline void Version::set_patch(::PROTOBUF_NAMESPACE_ID::int32 value) {
+inline void Version::_internal_set_patch(::PROTOBUF_NAMESPACE_ID::int32 value) {
   _has_bits_[0] |= 0x00000008u;
   patch_ = value;
+}
+inline void Version::set_patch(::PROTOBUF_NAMESPACE_ID::int32 value) {
+  _internal_set_patch(value);
   // @@protoc_insertion_point(field_set:google.protobuf.compiler.Version.patch)
 }
 
 // optional string suffix = 4;
 inline bool Version::_internal_has_suffix() const {
-  return (_has_bits_[0] & 0x00000001u) != 0;
+  bool value = (_has_bits_[0] & 0x00000001u) != 0;
+  return value;
 }
 inline bool Version::has_suffix() const {
   return _internal_has_suffix();
@@ -983,9 +1019,12 @@ inline void Version::set_allocated_suffix(std::string* suffix) {
 // CodeGeneratorRequest
 
 // repeated string file_to_generate = 1;
-inline int CodeGeneratorRequest::file_to_generate_size() const {
+inline int CodeGeneratorRequest::_internal_file_to_generate_size() const {
   return file_to_generate_.size();
 }
+inline int CodeGeneratorRequest::file_to_generate_size() const {
+  return _internal_file_to_generate_size();
+}
 inline void CodeGeneratorRequest::clear_file_to_generate() {
   file_to_generate_.Clear();
 }
@@ -993,9 +1032,12 @@ inline std::string* CodeGeneratorRequest::add_file_to_generate() {
   // @@protoc_insertion_point(field_add_mutable:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
   return _internal_add_file_to_generate();
 }
+inline const std::string& CodeGeneratorRequest::_internal_file_to_generate(int index) const {
+  return file_to_generate_.Get(index);
+}
 inline const std::string& CodeGeneratorRequest::file_to_generate(int index) const {
   // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
-  return file_to_generate_.Get(index);
+  return _internal_file_to_generate(index);
 }
 inline std::string* CodeGeneratorRequest::mutable_file_to_generate(int index) {
   // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
@@ -1052,7 +1094,8 @@ CodeGeneratorRequest::mutable_file_to_generate() {
 
 // optional string parameter = 2;
 inline bool CodeGeneratorRequest::_internal_has_parameter() const {
-  return (_has_bits_[0] & 0x00000001u) != 0;
+  bool value = (_has_bits_[0] & 0x00000001u) != 0;
+  return value;
 }
 inline bool CodeGeneratorRequest::has_parameter() const {
   return _internal_has_parameter();
@@ -1121,9 +1164,12 @@ inline void CodeGeneratorRequest::set_allocated_parameter(std::string* parameter
 }
 
 // repeated .google.protobuf.FileDescriptorProto proto_file = 15;
-inline int CodeGeneratorRequest::proto_file_size() const {
+inline int CodeGeneratorRequest::_internal_proto_file_size() const {
   return proto_file_.size();
 }
+inline int CodeGeneratorRequest::proto_file_size() const {
+  return _internal_proto_file_size();
+}
 inline PROTOBUF_NAMESPACE_ID::FileDescriptorProto* CodeGeneratorRequest::mutable_proto_file(int index) {
   // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
   return proto_file_.Mutable(index);
@@ -1133,13 +1179,19 @@ CodeGeneratorRequest::mutable_proto_file() {
   // @@protoc_insertion_point(field_mutable_list:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
   return &proto_file_;
 }
+inline const PROTOBUF_NAMESPACE_ID::FileDescriptorProto& CodeGeneratorRequest::_internal_proto_file(int index) const {
+  return proto_file_.Get(index);
+}
 inline const PROTOBUF_NAMESPACE_ID::FileDescriptorProto& CodeGeneratorRequest::proto_file(int index) const {
   // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
-  return proto_file_.Get(index);
+  return _internal_proto_file(index);
+}
+inline PROTOBUF_NAMESPACE_ID::FileDescriptorProto* CodeGeneratorRequest::_internal_add_proto_file() {
+  return proto_file_.Add();
 }
 inline PROTOBUF_NAMESPACE_ID::FileDescriptorProto* CodeGeneratorRequest::add_proto_file() {
   // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
-  return proto_file_.Add();
+  return _internal_add_proto_file();
 }
 inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::FileDescriptorProto >&
 CodeGeneratorRequest::proto_file() const {
@@ -1149,7 +1201,9 @@ CodeGeneratorRequest::proto_file() const {
 
 // optional .google.protobuf.compiler.Version compiler_version = 3;
 inline bool CodeGeneratorRequest::_internal_has_compiler_version() const {
-  return (_has_bits_[0] & 0x00000002u) != 0;
+  bool value = (_has_bits_[0] & 0x00000002u) != 0;
+  PROTOBUF_ASSUME(!value || compiler_version_ != nullptr);
+  return value;
 }
 inline bool CodeGeneratorRequest::has_compiler_version() const {
   return _internal_has_compiler_version();
@@ -1158,12 +1212,15 @@ inline void CodeGeneratorRequest::clear_compiler_version() {
   if (compiler_version_ != nullptr) compiler_version_->Clear();
   _has_bits_[0] &= ~0x00000002u;
 }
-inline const PROTOBUF_NAMESPACE_ID::compiler::Version& CodeGeneratorRequest::compiler_version() const {
+inline const PROTOBUF_NAMESPACE_ID::compiler::Version& CodeGeneratorRequest::_internal_compiler_version() const {
   const PROTOBUF_NAMESPACE_ID::compiler::Version* p = compiler_version_;
-  // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.compiler_version)
   return p != nullptr ? *p : *reinterpret_cast<const PROTOBUF_NAMESPACE_ID::compiler::Version*>(
       &PROTOBUF_NAMESPACE_ID::compiler::_Version_default_instance_);
 }
+inline const PROTOBUF_NAMESPACE_ID::compiler::Version& CodeGeneratorRequest::compiler_version() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.compiler_version)
+  return _internal_compiler_version();
+}
 inline PROTOBUF_NAMESPACE_ID::compiler::Version* CodeGeneratorRequest::release_compiler_version() {
   // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorRequest.compiler_version)
   _has_bits_[0] &= ~0x00000002u;
@@ -1171,15 +1228,18 @@ inline PROTOBUF_NAMESPACE_ID::compiler::Version* CodeGeneratorRequest::release_c
   compiler_version_ = nullptr;
   return temp;
 }
-inline PROTOBUF_NAMESPACE_ID::compiler::Version* CodeGeneratorRequest::mutable_compiler_version() {
+inline PROTOBUF_NAMESPACE_ID::compiler::Version* CodeGeneratorRequest::_internal_mutable_compiler_version() {
   _has_bits_[0] |= 0x00000002u;
   if (compiler_version_ == nullptr) {
     auto* p = CreateMaybeMessage<PROTOBUF_NAMESPACE_ID::compiler::Version>(GetArenaNoVirtual());
     compiler_version_ = p;
   }
-  // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.compiler_version)
   return compiler_version_;
 }
+inline PROTOBUF_NAMESPACE_ID::compiler::Version* CodeGeneratorRequest::mutable_compiler_version() {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.compiler_version)
+  return _internal_mutable_compiler_version();
+}
 inline void CodeGeneratorRequest::set_allocated_compiler_version(PROTOBUF_NAMESPACE_ID::compiler::Version* compiler_version) {
   ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArenaNoVirtual();
   if (message_arena == nullptr) {
@@ -1205,7 +1265,8 @@ inline void CodeGeneratorRequest::set_allocated_compiler_version(PROTOBUF_NAMESP
 
 // optional string name = 1;
 inline bool CodeGeneratorResponse_File::_internal_has_name() const {
-  return (_has_bits_[0] & 0x00000001u) != 0;
+  bool value = (_has_bits_[0] & 0x00000001u) != 0;
+  return value;
 }
 inline bool CodeGeneratorResponse_File::has_name() const {
   return _internal_has_name();
@@ -1275,7 +1336,8 @@ inline void CodeGeneratorResponse_File::set_allocated_name(std::string* name) {
 
 // optional string insertion_point = 2;
 inline bool CodeGeneratorResponse_File::_internal_has_insertion_point() const {
-  return (_has_bits_[0] & 0x00000002u) != 0;
+  bool value = (_has_bits_[0] & 0x00000002u) != 0;
+  return value;
 }
 inline bool CodeGeneratorResponse_File::has_insertion_point() const {
   return _internal_has_insertion_point();
@@ -1345,7 +1407,8 @@ inline void CodeGeneratorResponse_File::set_allocated_insertion_point(std::strin
 
 // optional string content = 15;
 inline bool CodeGeneratorResponse_File::_internal_has_content() const {
-  return (_has_bits_[0] & 0x00000004u) != 0;
+  bool value = (_has_bits_[0] & 0x00000004u) != 0;
+  return value;
 }
 inline bool CodeGeneratorResponse_File::has_content() const {
   return _internal_has_content();
@@ -1419,7 +1482,8 @@ inline void CodeGeneratorResponse_File::set_allocated_content(std::string* conte
 
 // optional string error = 1;
 inline bool CodeGeneratorResponse::_internal_has_error() const {
-  return (_has_bits_[0] & 0x00000001u) != 0;
+  bool value = (_has_bits_[0] & 0x00000001u) != 0;
+  return value;
 }
 inline bool CodeGeneratorResponse::has_error() const {
   return _internal_has_error();
@@ -1488,9 +1552,12 @@ inline void CodeGeneratorResponse::set_allocated_error(std::string* error) {
 }
 
 // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
-inline int CodeGeneratorResponse::file_size() const {
+inline int CodeGeneratorResponse::_internal_file_size() const {
   return file_.size();
 }
+inline int CodeGeneratorResponse::file_size() const {
+  return _internal_file_size();
+}
 inline void CodeGeneratorResponse::clear_file() {
   file_.Clear();
 }
@@ -1503,13 +1570,19 @@ CodeGeneratorResponse::mutable_file() {
   // @@protoc_insertion_point(field_mutable_list:google.protobuf.compiler.CodeGeneratorResponse.file)
   return &file_;
 }
+inline const PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File& CodeGeneratorResponse::_internal_file(int index) const {
+  return file_.Get(index);
+}
 inline const PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File& CodeGeneratorResponse::file(int index) const {
   // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.file)
-  return file_.Get(index);
+  return _internal_file(index);
+}
+inline PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File* CodeGeneratorResponse::_internal_add_file() {
+  return file_.Add();
 }
 inline PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File* CodeGeneratorResponse::add_file() {
   // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorResponse.file)
-  return file_.Add();
+  return _internal_add_file();
 }
 inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File >&
 CodeGeneratorResponse::file() const {

+ 3 - 3
src/google/protobuf/compiler/python/python_generator.cc

@@ -44,6 +44,8 @@
 // performance-minded Python code leverage the fast C++ implementation
 // directly.
 
+#include <google/protobuf/compiler/python/python_generator.h>
+
 #include <algorithm>
 #include <limits>
 #include <map>
@@ -52,12 +54,10 @@
 #include <utility>
 #include <vector>
 
-#include <google/protobuf/compiler/python/python_generator.h>
-#include <google/protobuf/descriptor.pb.h>
-
 #include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/stubs/stringprintf.h>
+#include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/io/printer.h>
 #include <google/protobuf/io/zero_copy_stream.h>
 #include <google/protobuf/descriptor.h>

+ 20 - 28
src/google/protobuf/descriptor.cc

@@ -59,8 +59,8 @@
 #include <google/protobuf/text_format.h>
 #include <google/protobuf/unknown_field_set.h>
 #include <google/protobuf/wire_format.h>
-#include <google/protobuf/stubs/substitute.h>
 #include <google/protobuf/stubs/casts.h>
+#include <google/protobuf/stubs/substitute.h>
 #include <google/protobuf/io/strtod.h>
 #include <google/protobuf/stubs/map_util.h>
 #include <google/protobuf/stubs/stl_util.h>
@@ -905,6 +905,14 @@ inline Symbol FileDescriptorTables::FindNestedSymbolOfType(
 
 Symbol DescriptorPool::Tables::FindByNameHelper(const DescriptorPool* pool,
                                                 const std::string& name) {
+  if (pool->mutex_ != nullptr) {
+    // Fast path: the Symbol is already cached.  This is just a hash lookup.
+    ReaderMutexLock lock(pool->mutex_);
+    if (known_bad_symbols_.empty() && known_bad_files_.empty()) {
+      Symbol result = FindSymbol(name);
+      if (!result.IsNull()) return result;
+    }
+  }
   MutexLockMaybe lock(pool->mutex_);
   if (pool->fallback_database_ != nullptr) {
     known_bad_symbols_.clear();
@@ -3681,7 +3689,14 @@ Symbol DescriptorBuilder::FindSymbolNotEnforcingDepsHelper(
 
 Symbol DescriptorBuilder::FindSymbolNotEnforcingDeps(const std::string& name,
                                                      bool build_it) {
-  return FindSymbolNotEnforcingDepsHelper(pool_, name, build_it);
+  Symbol result = FindSymbolNotEnforcingDepsHelper(pool_, name, build_it);
+  // Only find symbols which were defined in this file or one of its
+  // dependencies.
+  const FileDescriptor* file = result.GetFile();
+  if (file == file_ || dependencies_.count(file) > 0) {
+    unused_dependency_.erase(file);
+  }
+  return result;
 }
 
 Symbol DescriptorBuilder::FindSymbol(const std::string& name, bool build_it) {
@@ -3698,7 +3713,6 @@ Symbol DescriptorBuilder::FindSymbol(const std::string& name, bool build_it) {
   // dependencies.
   const FileDescriptor* file = result.GetFile();
   if (file == file_ || dependencies_.count(file) > 0) {
-    unused_dependency_.erase(file);
     return result;
   }
 
@@ -7104,35 +7118,13 @@ void DescriptorBuilder::LogUnusedDependency(const FileDescriptorProto& proto,
                                             const FileDescriptor* result) {
 
   if (!unused_dependency_.empty()) {
-    std::set<std::string> annotation_extensions;
-    annotation_extensions.insert("google.protobuf.MessageOptions");
-    annotation_extensions.insert("google.protobuf.FileOptions");
-    annotation_extensions.insert("google.protobuf.FieldOptions");
-    annotation_extensions.insert("google.protobuf.EnumOptions");
-    annotation_extensions.insert("google.protobuf.EnumValueOptions");
-    annotation_extensions.insert("google.protobuf.EnumValueOptions");
-    annotation_extensions.insert("google.protobuf.ServiceOptions");
-    annotation_extensions.insert("google.protobuf.MethodOptions");
-    annotation_extensions.insert("google.protobuf.StreamOptions");
     for (std::set<const FileDescriptor*>::const_iterator it =
              unused_dependency_.begin();
          it != unused_dependency_.end(); ++it) {
-      // Do not log warnings for proto files which extend annotations.
-      int i;
-      for (i = 0; i < (*it)->extension_count(); ++i) {
-        if (annotation_extensions.find(
-                (*it)->extension(i)->containing_type()->full_name()) !=
-            annotation_extensions.end()) {
-          break;
-        }
-      }
       // Log warnings for unused imported files.
-      if (i == (*it)->extension_count()) {
-        std::string error_message =
-            "Import " + (*it)->name() + " but not used.";
-        AddWarning((*it)->name(), proto, DescriptorPool::ErrorCollector::IMPORT,
-                   error_message);
-      }
+      std::string error_message = "Import " + (*it)->name() + " but not used.";
+      AddWarning((*it)->name(), proto, DescriptorPool::ErrorCollector::IMPORT,
+                 error_message);
     }
   }
 }

File diff suppressed because it is too large
+ 63 - 576
src/google/protobuf/descriptor.pb.cc


File diff suppressed because it is too large
+ 304 - 75
src/google/protobuf/descriptor.pb.h


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

@@ -42,6 +42,10 @@
 #include <google/protobuf/compiler/parser.h>
 #include <google/protobuf/unittest.pb.h>
 #include <google/protobuf/unittest_custom_options.pb.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/stringprintf.h>
 #include <google/protobuf/unittest_lazy_dependencies.pb.h>
 #include <google/protobuf/unittest_proto3_arena.pb.h>
 #include <google/protobuf/io/tokenizer.h>
@@ -51,15 +55,10 @@
 #include <google/protobuf/descriptor_database.h>
 #include <google/protobuf/dynamic_message.h>
 #include <google/protobuf/text_format.h>
-#include <google/protobuf/stubs/substitute.h>
-
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/stringprintf.h>
 #include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/testing/googletest.h>
 #include <gtest/gtest.h>
+#include <google/protobuf/stubs/substitute.h>
 
 
 #include <google/protobuf/port_def.inc>
@@ -3477,7 +3476,12 @@ TEST(CustomOptions, UnusedImportWarning) {
 
   MockErrorCollector error_collector;
   EXPECT_TRUE(pool.BuildFileCollectingErrors(file_proto, &error_collector));
-  EXPECT_EQ("", error_collector.warning_text_);
+  EXPECT_EQ(
+      "custom_options_import.proto: "
+      "google/protobuf/unittest_custom_options.proto: IMPORT: Import "
+      "google/protobuf/unittest_custom_options.proto but not used.\n",
+      error_collector.warning_text_);
+  EXPECT_EQ("", error_collector.text_);
 }
 
 // Verifies that proto files can correctly be parsed, even if the

+ 6 - 64
src/google/protobuf/duration.pb.cc

@@ -153,7 +153,6 @@ void Duration::Clear() {
   _internal_metadata_.Clear();
 }
 
-#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 const char* Duration::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArenaNoVirtual(); (void)arena;
@@ -195,63 +194,6 @@ failure:
   goto success;
 #undef CHK_
 }
-#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
-bool Duration::MergePartialFromCodedStream(
-    ::PROTOBUF_NAMESPACE_ID::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
-  ::PROTOBUF_NAMESPACE_ID::uint32 tag;
-  // @@protoc_insertion_point(parse_start:google.protobuf.Duration)
-  for (;;) {
-    ::std::pair<::PROTOBUF_NAMESPACE_ID::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
-    tag = p.first;
-    if (!p.second) goto handle_unusual;
-    switch (::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::GetTagFieldNumber(tag)) {
-      // int64 seconds = 1;
-      case 1: {
-        if (static_cast< ::PROTOBUF_NAMESPACE_ID::uint8>(tag) == (8 & 0xFF)) {
-
-          DO_((::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::ReadPrimitive<
-                   ::PROTOBUF_NAMESPACE_ID::int64, ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::TYPE_INT64>(
-                 input, &seconds_)));
-        } else {
-          goto handle_unusual;
-        }
-        break;
-      }
-
-      // int32 nanos = 2;
-      case 2: {
-        if (static_cast< ::PROTOBUF_NAMESPACE_ID::uint8>(tag) == (16 & 0xFF)) {
-
-          DO_((::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::ReadPrimitive<
-                   ::PROTOBUF_NAMESPACE_ID::int32, ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::TYPE_INT32>(
-                 input, &nanos_)));
-        } else {
-          goto handle_unusual;
-        }
-        break;
-      }
-
-      default: {
-      handle_unusual:
-        if (tag == 0) {
-          goto success;
-        }
-        DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SkipField(
-              input, tag, _internal_metadata_.mutable_unknown_fields()));
-        break;
-      }
-    }
-  }
-success:
-  // @@protoc_insertion_point(parse_success:google.protobuf.Duration)
-  return true;
-failure:
-  // @@protoc_insertion_point(parse_failure:google.protobuf.Duration)
-  return false;
-#undef DO_
-}
-#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 
 ::PROTOBUF_NAMESPACE_ID::uint8* Duration::InternalSerializeWithCachedSizesToArray(
     ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
@@ -262,13 +204,13 @@ failure:
   // int64 seconds = 1;
   if (this->seconds() != 0) {
     stream->EnsureSpace(&target);
-    target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt64ToArray(1, this->seconds(), target);
+    target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt64ToArray(1, this->_internal_seconds(), target);
   }
 
   // int32 nanos = 2;
   if (this->nanos() != 0) {
     stream->EnsureSpace(&target);
-    target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(2, this->nanos(), target);
+    target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(2, this->_internal_nanos(), target);
   }
 
   if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) {
@@ -291,14 +233,14 @@ size_t Duration::ByteSizeLong() const {
   if (this->seconds() != 0) {
     total_size += 1 +
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int64Size(
-        this->seconds());
+        this->_internal_seconds());
   }
 
   // int32 nanos = 2;
   if (this->nanos() != 0) {
     total_size += 1 +
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size(
-        this->nanos());
+        this->_internal_nanos());
   }
 
   if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) {
@@ -333,10 +275,10 @@ void Duration::MergeFrom(const Duration& from) {
   (void) cached_has_bits;
 
   if (from.seconds() != 0) {
-    set_seconds(from.seconds());
+    _internal_set_seconds(from._internal_seconds());
   }
   if (from.nanos() != 0) {
-    set_nanos(from.nanos());
+    _internal_set_nanos(from._internal_nanos());
   }
 }
 

+ 24 - 9
src/google/protobuf/duration.pb.h

@@ -150,12 +150,7 @@ class PROTOBUF_EXPORT Duration :
   bool IsInitialized() const final;
 
   size_t ByteSizeLong() const final;
-  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
   const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
-  #else
-  bool MergePartialFromCodedStream(
-      ::PROTOBUF_NAMESPACE_ID::io::CodedInputStream* input) final;
-  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
   ::PROTOBUF_NAMESPACE_ID::uint8* InternalSerializeWithCachedSizesToArray(
       ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
   int GetCachedSize() const final { return _cached_size_.Get(); }
@@ -204,11 +199,19 @@ class PROTOBUF_EXPORT Duration :
   void clear_seconds();
   ::PROTOBUF_NAMESPACE_ID::int64 seconds() const;
   void set_seconds(::PROTOBUF_NAMESPACE_ID::int64 value);
+  private:
+  ::PROTOBUF_NAMESPACE_ID::int64 _internal_seconds() const;
+  void _internal_set_seconds(::PROTOBUF_NAMESPACE_ID::int64 value);
+  public:
 
   // int32 nanos = 2;
   void clear_nanos();
   ::PROTOBUF_NAMESPACE_ID::int32 nanos() const;
   void set_nanos(::PROTOBUF_NAMESPACE_ID::int32 value);
+  private:
+  ::PROTOBUF_NAMESPACE_ID::int32 _internal_nanos() const;
+  void _internal_set_nanos(::PROTOBUF_NAMESPACE_ID::int32 value);
+  public:
 
   // @@protoc_insertion_point(class_scope:google.protobuf.Duration)
  private:
@@ -238,13 +241,19 @@ class PROTOBUF_EXPORT Duration :
 inline void Duration::clear_seconds() {
   seconds_ = PROTOBUF_LONGLONG(0);
 }
+inline ::PROTOBUF_NAMESPACE_ID::int64 Duration::_internal_seconds() const {
+  return seconds_;
+}
 inline ::PROTOBUF_NAMESPACE_ID::int64 Duration::seconds() const {
   // @@protoc_insertion_point(field_get:google.protobuf.Duration.seconds)
-  return seconds_;
+  return _internal_seconds();
 }
-inline void Duration::set_seconds(::PROTOBUF_NAMESPACE_ID::int64 value) {
+inline void Duration::_internal_set_seconds(::PROTOBUF_NAMESPACE_ID::int64 value) {
   
   seconds_ = value;
+}
+inline void Duration::set_seconds(::PROTOBUF_NAMESPACE_ID::int64 value) {
+  _internal_set_seconds(value);
   // @@protoc_insertion_point(field_set:google.protobuf.Duration.seconds)
 }
 
@@ -252,13 +261,19 @@ inline void Duration::set_seconds(::PROTOBUF_NAMESPACE_ID::int64 value) {
 inline void Duration::clear_nanos() {
   nanos_ = 0;
 }
+inline ::PROTOBUF_NAMESPACE_ID::int32 Duration::_internal_nanos() const {
+  return nanos_;
+}
 inline ::PROTOBUF_NAMESPACE_ID::int32 Duration::nanos() const {
   // @@protoc_insertion_point(field_get:google.protobuf.Duration.nanos)
-  return nanos_;
+  return _internal_nanos();
 }
-inline void Duration::set_nanos(::PROTOBUF_NAMESPACE_ID::int32 value) {
+inline void Duration::_internal_set_nanos(::PROTOBUF_NAMESPACE_ID::int32 value) {
   
   nanos_ = value;
+}
+inline void Duration::set_nanos(::PROTOBUF_NAMESPACE_ID::int32 value) {
+  _internal_set_nanos(value);
   // @@protoc_insertion_point(field_set:google.protobuf.Duration.nanos)
 }
 

+ 0 - 27
src/google/protobuf/empty.pb.cc

@@ -141,7 +141,6 @@ void Empty::Clear() {
   _internal_metadata_.Clear();
 }
 
-#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 const char* Empty::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArenaNoVirtual(); (void)arena;
@@ -168,32 +167,6 @@ failure:
   goto success;
 #undef CHK_
 }
-#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
-bool Empty::MergePartialFromCodedStream(
-    ::PROTOBUF_NAMESPACE_ID::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
-  ::PROTOBUF_NAMESPACE_ID::uint32 tag;
-  // @@protoc_insertion_point(parse_start:google.protobuf.Empty)
-  for (;;) {
-    ::std::pair<::PROTOBUF_NAMESPACE_ID::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
-    tag = p.first;
-    if (!p.second) goto handle_unusual;
-  handle_unusual:
-    if (tag == 0) {
-      goto success;
-    }
-    DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SkipField(
-          input, tag, _internal_metadata_.mutable_unknown_fields()));
-  }
-success:
-  // @@protoc_insertion_point(parse_success:google.protobuf.Empty)
-  return true;
-failure:
-  // @@protoc_insertion_point(parse_failure:google.protobuf.Empty)
-  return false;
-#undef DO_
-}
-#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 
 ::PROTOBUF_NAMESPACE_ID::uint8* Empty::InternalSerializeWithCachedSizesToArray(
     ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {

+ 0 - 5
src/google/protobuf/empty.pb.h

@@ -150,12 +150,7 @@ class PROTOBUF_EXPORT Empty :
   bool IsInitialized() const final;
 
   size_t ByteSizeLong() const final;
-  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
   const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
-  #else
-  bool MergePartialFromCodedStream(
-      ::PROTOBUF_NAMESPACE_ID::io::CodedInputStream* input) final;
-  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
   ::PROTOBUF_NAMESPACE_ID::uint8* InternalSerializeWithCachedSizesToArray(
       ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
   int GetCachedSize() const final { return _cached_size_.Get(); }

+ 0 - 3
src/google/protobuf/extension_set.cc

@@ -1196,7 +1196,6 @@ bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input,
   }
 }
 
-#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 const char* ExtensionSet::ParseField(
     uint64 tag, const char* ptr, const MessageLite* containing_type,
     internal::InternalMetadataWithArenaLite* metadata,
@@ -1220,8 +1219,6 @@ const char* ExtensionSet::ParseMessageSetItem(
   return ParseMessageSetItemTmpl(ptr, containing_type, metadata, ctx);
 }
 
-#endif
-
 bool ExtensionSet::ParseFieldWithExtensionInfo(int number,
                                                bool was_packed_on_wire,
                                                const ExtensionInfo& extension,

+ 2 - 9
src/google/protobuf/extension_set.h

@@ -146,7 +146,7 @@ class PROTOBUF_EXPORT GeneratedExtensionFinder : public ExtensionFinder {
  public:
   GeneratedExtensionFinder(const MessageLite* containing_type)
       : containing_type_(containing_type) {}
-  virtual ~GeneratedExtensionFinder() {}
+  ~GeneratedExtensionFinder() override {}
 
   // Returns true and fills in *output if found, otherwise returns false.
   bool Find(int number, ExtensionInfo* output) override;
@@ -394,7 +394,6 @@ class PROTOBUF_EXPORT ExtensionSet {
                   const MessageLite* containing_type,
                   io::CodedOutputStream* unknown_fields);
 
-#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
   // Lite parser
   const char* ParseField(uint64 tag, const char* ptr,
                          const MessageLite* containing_type,
@@ -434,7 +433,6 @@ class PROTOBUF_EXPORT ExtensionSet {
     }
     return ptr;
   }
-#endif
 
   // Parse an entire message in MessageSet format.  Such messages have no
   // fields, only extensions.
@@ -541,9 +539,7 @@ class PROTOBUF_EXPORT ExtensionSet {
 
     virtual bool ReadMessage(const MessageLite& prototype,
                              io::CodedInputStream* input) = 0;
-#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
     virtual const char* _InternalParse(const char* ptr, ParseContext* ctx) = 0;
-#endif
     virtual uint8* WriteMessageToArray(
         int number, uint8* target, io::EpsCopyOutputStream* stream) const = 0;
 
@@ -762,7 +758,6 @@ class PROTOBUF_EXPORT ExtensionSet {
                            ExtensionFinder* extension_finder,
                            MessageSetFieldSkipper* field_skipper);
 
-#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
   bool FindExtension(int wire_type, uint32 field,
                      const MessageLite* containing_type,
                      const internal::ParseContext* ctx,
@@ -807,7 +802,6 @@ class PROTOBUF_EXPORT ExtensionSet {
                                       const Msg* containing_type,
                                       Metadata* metadata,
                                       internal::ParseContext* ctx);
-#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 
   // Hack:  RepeatedPtrFieldBase declares ExtensionSet as a friend.  This
   //   friendship should automatically extend to ExtensionSet::Extension, but
@@ -1583,8 +1577,7 @@ template <typename ExtendeeType, typename TypeTraitsType,
 void LinkExtensionReflection(
     const google::protobuf::internal::ExtensionIdentifier<
         ExtendeeType, TypeTraitsType, field_type, is_packed>& extension) {
-  const void* volatile unused = &extension;
-  (void)&unused;  // Use address to avoid an extra load of volatile variable.
+  internal::StrongReference(extension);
 }
 
 }  // namespace protobuf

+ 0 - 3
src/google/protobuf/extension_set_heavy.cc

@@ -318,7 +318,6 @@ bool DescriptorPoolExtensionFinder::Find(int number, ExtensionInfo* output) {
 }
 
 
-#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 bool ExtensionSet::FindExtension(int wire_type, uint32 field,
                                  const Message* containing_type,
                                  const internal::ParseContext* ctx,
@@ -370,8 +369,6 @@ const char* ExtensionSet::ParseMessageSetItem(
   return ParseMessageSetItemTmpl(ptr, containing_type, metadata, ctx);
 }
 
-#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
-
 bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input,
                               const Message* containing_type,
                               UnknownFieldSet* unknown_fields) {

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

@@ -38,7 +38,6 @@ namespace google {
 namespace protobuf {
 namespace internal {
 
-#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 template <typename T>
 const char* ExtensionSet::ParseFieldWithExtensionInfo(
     int number, bool was_packed_on_wire, const ExtensionInfo& extension,
@@ -267,7 +266,6 @@ const char* ExtensionSet::ParseMessageSetItemTmpl(const char* ptr,
   }
   return ptr;
 }
-#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 
 }  // namespace internal
 }  // namespace protobuf

+ 2 - 51
src/google/protobuf/field_mask.pb.cc

@@ -147,7 +147,6 @@ void FieldMask::Clear() {
   _internal_metadata_.Clear();
 }
 
-#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 const char* FieldMask::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArenaNoVirtual(); (void)arena;
@@ -187,53 +186,6 @@ failure:
   goto success;
 #undef CHK_
 }
-#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
-bool FieldMask::MergePartialFromCodedStream(
-    ::PROTOBUF_NAMESPACE_ID::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
-  ::PROTOBUF_NAMESPACE_ID::uint32 tag;
-  // @@protoc_insertion_point(parse_start:google.protobuf.FieldMask)
-  for (;;) {
-    ::std::pair<::PROTOBUF_NAMESPACE_ID::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
-    tag = p.first;
-    if (!p.second) goto handle_unusual;
-    switch (::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::GetTagFieldNumber(tag)) {
-      // repeated string paths = 1;
-      case 1: {
-        if (static_cast< ::PROTOBUF_NAMESPACE_ID::uint8>(tag) == (10 & 0xFF)) {
-          DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::ReadString(
-                input, this->_internal_add_paths()));
-          DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String(
-            paths_.Get(paths_.size() - 1).data(),
-            static_cast<int>(paths_.Get(paths_.size() - 1).length()),
-            ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::PARSE,
-            "google.protobuf.FieldMask.paths"));
-        } else {
-          goto handle_unusual;
-        }
-        break;
-      }
-
-      default: {
-      handle_unusual:
-        if (tag == 0) {
-          goto success;
-        }
-        DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SkipField(
-              input, tag, _internal_metadata_.mutable_unknown_fields()));
-        break;
-      }
-    }
-  }
-success:
-  // @@protoc_insertion_point(parse_success:google.protobuf.FieldMask)
-  return true;
-failure:
-  // @@protoc_insertion_point(parse_failure:google.protobuf.FieldMask)
-  return false;
-#undef DO_
-}
-#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 
 ::PROTOBUF_NAMESPACE_ID::uint8* FieldMask::InternalSerializeWithCachedSizesToArray(
     ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
@@ -242,9 +194,8 @@ failure:
   (void) cached_has_bits;
 
   // repeated string paths = 1;
-  for (auto it = paths_.pointer_begin(),
-            end = paths_.pointer_end(); it < end; ++it) {
-    const auto& s = **it;
+  for (int i = 0, n = this->_internal_paths_size(); i < n; i++) {
+    const auto& s = this->_internal_paths(i);
     ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String(
       s.data(), static_cast<int>(s.length()),
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE,

+ 12 - 7
src/google/protobuf/field_mask.pb.h

@@ -150,12 +150,7 @@ class PROTOBUF_EXPORT FieldMask :
   bool IsInitialized() const final;
 
   size_t ByteSizeLong() const final;
-  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
   const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
-  #else
-  bool MergePartialFromCodedStream(
-      ::PROTOBUF_NAMESPACE_ID::io::CodedInputStream* input) final;
-  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
   ::PROTOBUF_NAMESPACE_ID::uint8* InternalSerializeWithCachedSizesToArray(
       ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
   int GetCachedSize() const final { return _cached_size_.Get(); }
@@ -201,6 +196,9 @@ class PROTOBUF_EXPORT FieldMask :
   };
   // repeated string paths = 1;
   int paths_size() const;
+  private:
+  int _internal_paths_size() const;
+  public:
   void clear_paths();
   const std::string& paths(int index) const;
   std::string* mutable_paths(int index);
@@ -216,6 +214,7 @@ class PROTOBUF_EXPORT FieldMask :
   const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<std::string>& paths() const;
   ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<std::string>* mutable_paths();
   private:
+  const std::string& _internal_paths(int index) const;
   std::string* _internal_add_paths();
   public:
 
@@ -243,9 +242,12 @@ class PROTOBUF_EXPORT FieldMask :
 // FieldMask
 
 // repeated string paths = 1;
-inline int FieldMask::paths_size() const {
+inline int FieldMask::_internal_paths_size() const {
   return paths_.size();
 }
+inline int FieldMask::paths_size() const {
+  return _internal_paths_size();
+}
 inline void FieldMask::clear_paths() {
   paths_.Clear();
 }
@@ -253,9 +255,12 @@ inline std::string* FieldMask::add_paths() {
   // @@protoc_insertion_point(field_add_mutable:google.protobuf.FieldMask.paths)
   return _internal_add_paths();
 }
+inline const std::string& FieldMask::_internal_paths(int index) const {
+  return paths_.Get(index);
+}
 inline const std::string& FieldMask::paths(int index) const {
   // @@protoc_insertion_point(field_get:google.protobuf.FieldMask.paths)
-  return paths_.Get(index);
+  return _internal_paths(index);
 }
 inline std::string* FieldMask::mutable_paths(int index) {
   // @@protoc_insertion_point(field_mutable:google.protobuf.FieldMask.paths)

Some files were not shown because too many files changed in this diff