Przeglądaj źródła

Sync from Piper @305053102

PROTOBUF_SYNC_PIPER
Joshua Haberman 5 lat temu
rodzic
commit
503a2116aa
31 zmienionych plików z 798 dodań i 681 usunięć
  1. 1 0
      BUILD
  2. 1 3
      benchmarks/datasets/google_message3/benchmark_message3_2.proto
  3. 1 2
      benchmarks/python/py_benchmark.py
  4. 1 1
      conformance/text_format_failure_list_java.txt
  5. BIN
      csharp/src/Google.Protobuf.Test/testprotos.pb
  6. 152 98
      csharp/src/Google.Protobuf/Reflection/Descriptor.cs
  7. 4 0
      docs/options.md
  8. 8 0
      examples/README.md
  9. 1 0
      java/core/src/main/java/com/google/protobuf/AllocatedBuffer.java
  10. 69 0
      php/src/Google/Protobuf/Internal/FieldDescriptorProto.php
  11. 3 3
      php/src/Google/Protobuf/Internal/FileOptions.php
  12. 29 2
      php/tests/autoload.php
  13. 9 4
      python/google/protobuf/internal/message_factory_test.py
  14. 28 7
      python/google/protobuf/internal/well_known_types_test.py
  15. 9 5
      python/google/protobuf/message.py
  16. 8 12
      ruby/ext/google/protobuf_c/extconf.rb
  17. 3 0
      src/google/protobuf/compiler/command_line_interface.cc
  18. 2 1
      src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc
  19. 15 2
      src/google/protobuf/compiler/cpp/cpp_helpers.h
  20. 82 85
      src/google/protobuf/compiler/cpp/cpp_message.cc
  21. 1 1
      src/google/protobuf/compiler/java/java_generator.h
  22. 0 30
      src/google/protobuf/compiler/zip_writer.cc
  23. 0 30
      src/google/protobuf/compiler/zip_writer.h
  24. 32 57
      src/google/protobuf/descriptor.pb.cc
  25. 5 10
      src/google/protobuf/descriptor.pb.h
  26. 95 39
      src/google/protobuf/generated_enum_util.cc
  27. 206 206
      src/google/protobuf/map_field.h
  28. 0 30
      src/google/protobuf/map_test_util.inc
  29. 0 30
      src/google/protobuf/test_messages_proto3.proto
  30. 21 15
      src/google/protobuf/unittest_proto3_optional.proto
  31. 12 8
      src/google/protobuf/util/internal/mock_error_listener.h

+ 1 - 0
BUILD

@@ -524,6 +524,7 @@ RELATIVE_TEST_PROTOS = [
     "google/protobuf/unittest_proto3_arena.proto",
     "google/protobuf/unittest_proto3_arena.proto",
     "google/protobuf/unittest_proto3_arena_lite.proto",
     "google/protobuf/unittest_proto3_arena_lite.proto",
     "google/protobuf/unittest_proto3_lite.proto",
     "google/protobuf/unittest_proto3_lite.proto",
+    "google/protobuf/unittest_proto3_optional.proto",
     "google/protobuf/unittest_well_known_types.proto",
     "google/protobuf/unittest_well_known_types.proto",
     "google/protobuf/util/internal/testdata/anys.proto",
     "google/protobuf/util/internal/testdata/anys.proto",
     "google/protobuf/util/internal/testdata/books.proto",
     "google/protobuf/util/internal/testdata/books.proto",

+ 1 - 3
benchmarks/datasets/google_message3/benchmark_message3_2.proto

@@ -58,9 +58,7 @@ message Message24345 {
   optional string field24536 = 3;
   optional string field24536 = 3;
   optional string field24537 = 4;
   optional string field24537 = 4;
   optional .benchmarks.google_message3.UnusedEnum field24538 = 23;
   optional .benchmarks.google_message3.UnusedEnum field24538 = 23;
-
-  // LINT: ALLOW_GROUPS
-
+  optional string field24539 = 5;
   required string field24540 = 6;
   required string field24540 = 6;
   optional string field24541 = 7;
   optional string field24541 = 7;
   optional string field24542 = 8;
   optional string field24542 = 8;

+ 1 - 2
benchmarks/python/py_benchmark.py

@@ -157,8 +157,7 @@ def do_test(request):
 
 
     elif request.requested_output_format == conformance_pb2.JSON:
     elif request.requested_output_format == conformance_pb2.JSON:
       try:
       try:
-        response.json_payload = json_format.MessageToJson(
-            test_message, float_precision=None)
+        response.json_payload = json_format.MessageToJson(test_message)
       except Exception as e:
       except Exception as e:
         response.serialize_error = str(e)
         response.serialize_error = str(e)
         return response
         return response

+ 1 - 1
conformance/text_format_failure_list_java.txt

@@ -4314,7 +4314,7 @@ namespace Google.Protobuf.TestProtos.Proto2 {
   }
   }
 
 
   /// <summary>
   /// <summary>
-  /// This proto includes a recusively nested message.
+  /// This proto includes a recursively nested message.
   /// </summary>
   /// </summary>
   public sealed partial class NestedTestAllTypes : pb::IMessage<NestedTestAllTypes> {
   public sealed partial class NestedTestAllTypes : pb::IMessage<NestedTestAllTypes> {
     private static readonly pb::MessageParser<NestedTestAllTypes> _parser = new pb::MessageParser<NestedTestAllTypes>(() => new NestedTestAllTypes());
     private static readonly pb::MessageParser<NestedTestAllTypes> _parser = new pb::MessageParser<NestedTestAllTypes>(() => new NestedTestAllTypes());

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


+ 152 - 98
csharp/src/Google.Protobuf/Reflection/Descriptor.cs

@@ -54,7 +54,7 @@ namespace Google.Protobuf.Reflection {
             "b2J1Zi5FeHRlbnNpb25SYW5nZU9wdGlvbnMaKwoNUmVzZXJ2ZWRSYW5nZRIN",
             "b2J1Zi5FeHRlbnNpb25SYW5nZU9wdGlvbnMaKwoNUmVzZXJ2ZWRSYW5nZRIN",
             "CgVzdGFydBgBIAEoBRILCgNlbmQYAiABKAUiZwoVRXh0ZW5zaW9uUmFuZ2VP",
             "CgVzdGFydBgBIAEoBRILCgNlbmQYAiABKAUiZwoVRXh0ZW5zaW9uUmFuZ2VP",
             "cHRpb25zEkMKFHVuaW50ZXJwcmV0ZWRfb3B0aW9uGOcHIAMoCzIkLmdvb2ds",
             "cHRpb25zEkMKFHVuaW50ZXJwcmV0ZWRfb3B0aW9uGOcHIAMoCzIkLmdvb2ds",
-            "ZS5wcm90b2J1Zi5VbmludGVycHJldGVkT3B0aW9uKgkI6AcQgICAgAIivAUK",
+            "ZS5wcm90b2J1Zi5VbmludGVycHJldGVkT3B0aW9uKgkI6AcQgICAgAIi1QUK",
             "FEZpZWxkRGVzY3JpcHRvclByb3RvEgwKBG5hbWUYASABKAkSDgoGbnVtYmVy",
             "FEZpZWxkRGVzY3JpcHRvclByb3RvEgwKBG5hbWUYASABKAkSDgoGbnVtYmVy",
             "GAMgASgFEjoKBWxhYmVsGAQgASgOMisuZ29vZ2xlLnByb3RvYnVmLkZpZWxk",
             "GAMgASgFEjoKBWxhYmVsGAQgASgOMisuZ29vZ2xlLnByb3RvYnVmLkZpZWxk",
             "RGVzY3JpcHRvclByb3RvLkxhYmVsEjgKBHR5cGUYBSABKA4yKi5nb29nbGUu",
             "RGVzY3JpcHRvclByb3RvLkxhYmVsEjgKBHR5cGUYBSABKA4yKi5nb29nbGUu",
@@ -62,102 +62,103 @@ namespace Google.Protobuf.Reflection {
             "bWUYBiABKAkSEAoIZXh0ZW5kZWUYAiABKAkSFQoNZGVmYXVsdF92YWx1ZRgH",
             "bWUYBiABKAkSEAoIZXh0ZW5kZWUYAiABKAkSFQoNZGVmYXVsdF92YWx1ZRgH",
             "IAEoCRITCgtvbmVvZl9pbmRleBgJIAEoBRIRCglqc29uX25hbWUYCiABKAkS",
             "IAEoCRITCgtvbmVvZl9pbmRleBgJIAEoBRIRCglqc29uX25hbWUYCiABKAkS",
             "LgoHb3B0aW9ucxgIIAEoCzIdLmdvb2dsZS5wcm90b2J1Zi5GaWVsZE9wdGlv",
             "LgoHb3B0aW9ucxgIIAEoCzIdLmdvb2dsZS5wcm90b2J1Zi5GaWVsZE9wdGlv",
-            "bnMitgIKBFR5cGUSDwoLVFlQRV9ET1VCTEUQARIOCgpUWVBFX0ZMT0FUEAIS",
-            "DgoKVFlQRV9JTlQ2NBADEg8KC1RZUEVfVUlOVDY0EAQSDgoKVFlQRV9JTlQz",
-            "MhAFEhAKDFRZUEVfRklYRUQ2NBAGEhAKDFRZUEVfRklYRUQzMhAHEg0KCVRZ",
-            "UEVfQk9PTBAIEg8KC1RZUEVfU1RSSU5HEAkSDgoKVFlQRV9HUk9VUBAKEhAK",
-            "DFRZUEVfTUVTU0FHRRALEg4KClRZUEVfQllURVMQDBIPCgtUWVBFX1VJTlQz",
-            "MhANEg0KCVRZUEVfRU5VTRAOEhEKDVRZUEVfU0ZJWEVEMzIQDxIRCg1UWVBF",
-            "X1NGSVhFRDY0EBASDwoLVFlQRV9TSU5UMzIQERIPCgtUWVBFX1NJTlQ2NBAS",
-            "IkMKBUxhYmVsEhIKDkxBQkVMX09QVElPTkFMEAESEgoOTEFCRUxfUkVRVUlS",
-            "RUQQAhISCg5MQUJFTF9SRVBFQVRFRBADIlQKFE9uZW9mRGVzY3JpcHRvclBy",
-            "b3RvEgwKBG5hbWUYASABKAkSLgoHb3B0aW9ucxgCIAEoCzIdLmdvb2dsZS5w",
-            "cm90b2J1Zi5PbmVvZk9wdGlvbnMipAIKE0VudW1EZXNjcmlwdG9yUHJvdG8S",
-            "DAoEbmFtZRgBIAEoCRI4CgV2YWx1ZRgCIAMoCzIpLmdvb2dsZS5wcm90b2J1",
-            "Zi5FbnVtVmFsdWVEZXNjcmlwdG9yUHJvdG8SLQoHb3B0aW9ucxgDIAEoCzIc",
-            "Lmdvb2dsZS5wcm90b2J1Zi5FbnVtT3B0aW9ucxJOCg5yZXNlcnZlZF9yYW5n",
-            "ZRgEIAMoCzI2Lmdvb2dsZS5wcm90b2J1Zi5FbnVtRGVzY3JpcHRvclByb3Rv",
-            "LkVudW1SZXNlcnZlZFJhbmdlEhUKDXJlc2VydmVkX25hbWUYBSADKAkaLwoR",
-            "RW51bVJlc2VydmVkUmFuZ2USDQoFc3RhcnQYASABKAUSCwoDZW5kGAIgASgF",
-            "ImwKGEVudW1WYWx1ZURlc2NyaXB0b3JQcm90bxIMCgRuYW1lGAEgASgJEg4K",
-            "Bm51bWJlchgCIAEoBRIyCgdvcHRpb25zGAMgASgLMiEuZ29vZ2xlLnByb3Rv",
-            "YnVmLkVudW1WYWx1ZU9wdGlvbnMikAEKFlNlcnZpY2VEZXNjcmlwdG9yUHJv",
-            "dG8SDAoEbmFtZRgBIAEoCRI2CgZtZXRob2QYAiADKAsyJi5nb29nbGUucHJv",
-            "dG9idWYuTWV0aG9kRGVzY3JpcHRvclByb3RvEjAKB29wdGlvbnMYAyABKAsy",
-            "Hy5nb29nbGUucHJvdG9idWYuU2VydmljZU9wdGlvbnMiwQEKFU1ldGhvZERl",
-            "c2NyaXB0b3JQcm90bxIMCgRuYW1lGAEgASgJEhIKCmlucHV0X3R5cGUYAiAB",
-            "KAkSEwoLb3V0cHV0X3R5cGUYAyABKAkSLwoHb3B0aW9ucxgEIAEoCzIeLmdv",
-            "b2dsZS5wcm90b2J1Zi5NZXRob2RPcHRpb25zEh8KEGNsaWVudF9zdHJlYW1p",
-            "bmcYBSABKAg6BWZhbHNlEh8KEHNlcnZlcl9zdHJlYW1pbmcYBiABKAg6BWZh",
-            "bHNlIqYGCgtGaWxlT3B0aW9ucxIUCgxqYXZhX3BhY2thZ2UYASABKAkSHAoU",
-            "amF2YV9vdXRlcl9jbGFzc25hbWUYCCABKAkSIgoTamF2YV9tdWx0aXBsZV9m",
-            "aWxlcxgKIAEoCDoFZmFsc2USKQodamF2YV9nZW5lcmF0ZV9lcXVhbHNfYW5k",
-            "X2hhc2gYFCABKAhCAhgBEiUKFmphdmFfc3RyaW5nX2NoZWNrX3V0ZjgYGyAB",
-            "KAg6BWZhbHNlEkYKDG9wdGltaXplX2ZvchgJIAEoDjIpLmdvb2dsZS5wcm90",
-            "b2J1Zi5GaWxlT3B0aW9ucy5PcHRpbWl6ZU1vZGU6BVNQRUVEEhIKCmdvX3Bh",
-            "Y2thZ2UYCyABKAkSIgoTY2NfZ2VuZXJpY19zZXJ2aWNlcxgQIAEoCDoFZmFs",
-            "c2USJAoVamF2YV9nZW5lcmljX3NlcnZpY2VzGBEgASgIOgVmYWxzZRIiChNw",
-            "eV9nZW5lcmljX3NlcnZpY2VzGBIgASgIOgVmYWxzZRIjChRwaHBfZ2VuZXJp",
-            "Y19zZXJ2aWNlcxgqIAEoCDoFZmFsc2USGQoKZGVwcmVjYXRlZBgXIAEoCDoF",
-            "ZmFsc2USHwoQY2NfZW5hYmxlX2FyZW5hcxgfIAEoCDoFZmFsc2USGQoRb2Jq",
-            "Y19jbGFzc19wcmVmaXgYJCABKAkSGAoQY3NoYXJwX25hbWVzcGFjZRglIAEo",
-            "CRIUCgxzd2lmdF9wcmVmaXgYJyABKAkSGAoQcGhwX2NsYXNzX3ByZWZpeBgo",
-            "IAEoCRIVCg1waHBfbmFtZXNwYWNlGCkgASgJEh4KFnBocF9tZXRhZGF0YV9u",
-            "YW1lc3BhY2UYLCABKAkSFAoMcnVieV9wYWNrYWdlGC0gASgJEkMKFHVuaW50",
-            "ZXJwcmV0ZWRfb3B0aW9uGOcHIAMoCzIkLmdvb2dsZS5wcm90b2J1Zi5Vbmlu",
-            "dGVycHJldGVkT3B0aW9uIjoKDE9wdGltaXplTW9kZRIJCgVTUEVFRBABEg0K",
-            "CUNPREVfU0laRRACEhAKDExJVEVfUlVOVElNRRADKgkI6AcQgICAgAJKBAgm",
-            "ECci8gEKDk1lc3NhZ2VPcHRpb25zEiYKF21lc3NhZ2Vfc2V0X3dpcmVfZm9y",
-            "bWF0GAEgASgIOgVmYWxzZRIuCh9ub19zdGFuZGFyZF9kZXNjcmlwdG9yX2Fj",
-            "Y2Vzc29yGAIgASgIOgVmYWxzZRIZCgpkZXByZWNhdGVkGAMgASgIOgVmYWxz",
-            "ZRIRCgltYXBfZW50cnkYByABKAgSQwoUdW5pbnRlcnByZXRlZF9vcHRpb24Y",
-            "5wcgAygLMiQuZ29vZ2xlLnByb3RvYnVmLlVuaW50ZXJwcmV0ZWRPcHRpb24q",
-            "CQjoBxCAgICAAkoECAgQCUoECAkQCiKeAwoMRmllbGRPcHRpb25zEjoKBWN0",
-            "eXBlGAEgASgOMiMuZ29vZ2xlLnByb3RvYnVmLkZpZWxkT3B0aW9ucy5DVHlw",
-            "ZToGU1RSSU5HEg4KBnBhY2tlZBgCIAEoCBI/CgZqc3R5cGUYBiABKA4yJC5n",
-            "b29nbGUucHJvdG9idWYuRmllbGRPcHRpb25zLkpTVHlwZToJSlNfTk9STUFM",
-            "EhMKBGxhenkYBSABKAg6BWZhbHNlEhkKCmRlcHJlY2F0ZWQYAyABKAg6BWZh",
-            "bHNlEhMKBHdlYWsYCiABKAg6BWZhbHNlEkMKFHVuaW50ZXJwcmV0ZWRfb3B0",
-            "aW9uGOcHIAMoCzIkLmdvb2dsZS5wcm90b2J1Zi5VbmludGVycHJldGVkT3B0",
-            "aW9uIi8KBUNUeXBlEgoKBlNUUklORxAAEggKBENPUkQQARIQCgxTVFJJTkdf",
-            "UElFQ0UQAiI1CgZKU1R5cGUSDQoJSlNfTk9STUFMEAASDQoJSlNfU1RSSU5H",
-            "EAESDQoJSlNfTlVNQkVSEAIqCQjoBxCAgICAAkoECAQQBSJeCgxPbmVvZk9w",
-            "dGlvbnMSQwoUdW5pbnRlcnByZXRlZF9vcHRpb24Y5wcgAygLMiQuZ29vZ2xl",
-            "LnByb3RvYnVmLlVuaW50ZXJwcmV0ZWRPcHRpb24qCQjoBxCAgICAAiKTAQoL",
-            "RW51bU9wdGlvbnMSEwoLYWxsb3dfYWxpYXMYAiABKAgSGQoKZGVwcmVjYXRl",
-            "ZBgDIAEoCDoFZmFsc2USQwoUdW5pbnRlcnByZXRlZF9vcHRpb24Y5wcgAygL",
-            "MiQuZ29vZ2xlLnByb3RvYnVmLlVuaW50ZXJwcmV0ZWRPcHRpb24qCQjoBxCA",
-            "gICAAkoECAUQBiJ9ChBFbnVtVmFsdWVPcHRpb25zEhkKCmRlcHJlY2F0ZWQY",
-            "ASABKAg6BWZhbHNlEkMKFHVuaW50ZXJwcmV0ZWRfb3B0aW9uGOcHIAMoCzIk",
-            "Lmdvb2dsZS5wcm90b2J1Zi5VbmludGVycHJldGVkT3B0aW9uKgkI6AcQgICA",
-            "gAIiewoOU2VydmljZU9wdGlvbnMSGQoKZGVwcmVjYXRlZBghIAEoCDoFZmFs",
-            "c2USQwoUdW5pbnRlcnByZXRlZF9vcHRpb24Y5wcgAygLMiQuZ29vZ2xlLnBy",
-            "b3RvYnVmLlVuaW50ZXJwcmV0ZWRPcHRpb24qCQjoBxCAgICAAiKtAgoNTWV0",
-            "aG9kT3B0aW9ucxIZCgpkZXByZWNhdGVkGCEgASgIOgVmYWxzZRJfChFpZGVt",
-            "cG90ZW5jeV9sZXZlbBgiIAEoDjIvLmdvb2dsZS5wcm90b2J1Zi5NZXRob2RP",
-            "cHRpb25zLklkZW1wb3RlbmN5TGV2ZWw6E0lERU1QT1RFTkNZX1VOS05PV04S",
+            "bnMSFwoPcHJvdG8zX29wdGlvbmFsGBEgASgIIrYCCgRUeXBlEg8KC1RZUEVf",
+            "RE9VQkxFEAESDgoKVFlQRV9GTE9BVBACEg4KClRZUEVfSU5UNjQQAxIPCgtU",
+            "WVBFX1VJTlQ2NBAEEg4KClRZUEVfSU5UMzIQBRIQCgxUWVBFX0ZJWEVENjQQ",
+            "BhIQCgxUWVBFX0ZJWEVEMzIQBxINCglUWVBFX0JPT0wQCBIPCgtUWVBFX1NU",
+            "UklORxAJEg4KClRZUEVfR1JPVVAQChIQCgxUWVBFX01FU1NBR0UQCxIOCgpU",
+            "WVBFX0JZVEVTEAwSDwoLVFlQRV9VSU5UMzIQDRINCglUWVBFX0VOVU0QDhIR",
+            "Cg1UWVBFX1NGSVhFRDMyEA8SEQoNVFlQRV9TRklYRUQ2NBAQEg8KC1RZUEVf",
+            "U0lOVDMyEBESDwoLVFlQRV9TSU5UNjQQEiJDCgVMYWJlbBISCg5MQUJFTF9P",
+            "UFRJT05BTBABEhIKDkxBQkVMX1JFUVVJUkVEEAISEgoOTEFCRUxfUkVQRUFU",
+            "RUQQAyJUChRPbmVvZkRlc2NyaXB0b3JQcm90bxIMCgRuYW1lGAEgASgJEi4K",
+            "B29wdGlvbnMYAiABKAsyHS5nb29nbGUucHJvdG9idWYuT25lb2ZPcHRpb25z",
+            "IqQCChNFbnVtRGVzY3JpcHRvclByb3RvEgwKBG5hbWUYASABKAkSOAoFdmFs",
+            "dWUYAiADKAsyKS5nb29nbGUucHJvdG9idWYuRW51bVZhbHVlRGVzY3JpcHRv",
+            "clByb3RvEi0KB29wdGlvbnMYAyABKAsyHC5nb29nbGUucHJvdG9idWYuRW51",
+            "bU9wdGlvbnMSTgoOcmVzZXJ2ZWRfcmFuZ2UYBCADKAsyNi5nb29nbGUucHJv",
+            "dG9idWYuRW51bURlc2NyaXB0b3JQcm90by5FbnVtUmVzZXJ2ZWRSYW5nZRIV",
+            "Cg1yZXNlcnZlZF9uYW1lGAUgAygJGi8KEUVudW1SZXNlcnZlZFJhbmdlEg0K",
+            "BXN0YXJ0GAEgASgFEgsKA2VuZBgCIAEoBSJsChhFbnVtVmFsdWVEZXNjcmlw",
+            "dG9yUHJvdG8SDAoEbmFtZRgBIAEoCRIOCgZudW1iZXIYAiABKAUSMgoHb3B0",
+            "aW9ucxgDIAEoCzIhLmdvb2dsZS5wcm90b2J1Zi5FbnVtVmFsdWVPcHRpb25z",
+            "IpABChZTZXJ2aWNlRGVzY3JpcHRvclByb3RvEgwKBG5hbWUYASABKAkSNgoG",
+            "bWV0aG9kGAIgAygLMiYuZ29vZ2xlLnByb3RvYnVmLk1ldGhvZERlc2NyaXB0",
+            "b3JQcm90bxIwCgdvcHRpb25zGAMgASgLMh8uZ29vZ2xlLnByb3RvYnVmLlNl",
+            "cnZpY2VPcHRpb25zIsEBChVNZXRob2REZXNjcmlwdG9yUHJvdG8SDAoEbmFt",
+            "ZRgBIAEoCRISCgppbnB1dF90eXBlGAIgASgJEhMKC291dHB1dF90eXBlGAMg",
+            "ASgJEi8KB29wdGlvbnMYBCABKAsyHi5nb29nbGUucHJvdG9idWYuTWV0aG9k",
+            "T3B0aW9ucxIfChBjbGllbnRfc3RyZWFtaW5nGAUgASgIOgVmYWxzZRIfChBz",
+            "ZXJ2ZXJfc3RyZWFtaW5nGAYgASgIOgVmYWxzZSKlBgoLRmlsZU9wdGlvbnMS",
+            "FAoMamF2YV9wYWNrYWdlGAEgASgJEhwKFGphdmFfb3V0ZXJfY2xhc3NuYW1l",
+            "GAggASgJEiIKE2phdmFfbXVsdGlwbGVfZmlsZXMYCiABKAg6BWZhbHNlEikK",
+            "HWphdmFfZ2VuZXJhdGVfZXF1YWxzX2FuZF9oYXNoGBQgASgIQgIYARIlChZq",
+            "YXZhX3N0cmluZ19jaGVja191dGY4GBsgASgIOgVmYWxzZRJGCgxvcHRpbWl6",
+            "ZV9mb3IYCSABKA4yKS5nb29nbGUucHJvdG9idWYuRmlsZU9wdGlvbnMuT3B0",
+            "aW1pemVNb2RlOgVTUEVFRBISCgpnb19wYWNrYWdlGAsgASgJEiIKE2NjX2dl",
+            "bmVyaWNfc2VydmljZXMYECABKAg6BWZhbHNlEiQKFWphdmFfZ2VuZXJpY19z",
+            "ZXJ2aWNlcxgRIAEoCDoFZmFsc2USIgoTcHlfZ2VuZXJpY19zZXJ2aWNlcxgS",
+            "IAEoCDoFZmFsc2USIwoUcGhwX2dlbmVyaWNfc2VydmljZXMYKiABKAg6BWZh",
+            "bHNlEhkKCmRlcHJlY2F0ZWQYFyABKAg6BWZhbHNlEh4KEGNjX2VuYWJsZV9h",
+            "cmVuYXMYHyABKAg6BHRydWUSGQoRb2JqY19jbGFzc19wcmVmaXgYJCABKAkS",
+            "GAoQY3NoYXJwX25hbWVzcGFjZRglIAEoCRIUCgxzd2lmdF9wcmVmaXgYJyAB",
+            "KAkSGAoQcGhwX2NsYXNzX3ByZWZpeBgoIAEoCRIVCg1waHBfbmFtZXNwYWNl",
+            "GCkgASgJEh4KFnBocF9tZXRhZGF0YV9uYW1lc3BhY2UYLCABKAkSFAoMcnVi",
+            "eV9wYWNrYWdlGC0gASgJEkMKFHVuaW50ZXJwcmV0ZWRfb3B0aW9uGOcHIAMo",
+            "CzIkLmdvb2dsZS5wcm90b2J1Zi5VbmludGVycHJldGVkT3B0aW9uIjoKDE9w",
+            "dGltaXplTW9kZRIJCgVTUEVFRBABEg0KCUNPREVfU0laRRACEhAKDExJVEVf",
+            "UlVOVElNRRADKgkI6AcQgICAgAJKBAgmECci8gEKDk1lc3NhZ2VPcHRpb25z",
+            "EiYKF21lc3NhZ2Vfc2V0X3dpcmVfZm9ybWF0GAEgASgIOgVmYWxzZRIuCh9u",
+            "b19zdGFuZGFyZF9kZXNjcmlwdG9yX2FjY2Vzc29yGAIgASgIOgVmYWxzZRIZ",
+            "CgpkZXByZWNhdGVkGAMgASgIOgVmYWxzZRIRCgltYXBfZW50cnkYByABKAgS",
             "QwoUdW5pbnRlcnByZXRlZF9vcHRpb24Y5wcgAygLMiQuZ29vZ2xlLnByb3Rv",
             "QwoUdW5pbnRlcnByZXRlZF9vcHRpb24Y5wcgAygLMiQuZ29vZ2xlLnByb3Rv",
-            "YnVmLlVuaW50ZXJwcmV0ZWRPcHRpb24iUAoQSWRlbXBvdGVuY3lMZXZlbBIX",
-            "ChNJREVNUE9URU5DWV9VTktOT1dOEAASEwoPTk9fU0lERV9FRkZFQ1RTEAES",
-            "DgoKSURFTVBPVEVOVBACKgkI6AcQgICAgAIingIKE1VuaW50ZXJwcmV0ZWRP",
-            "cHRpb24SOwoEbmFtZRgCIAMoCzItLmdvb2dsZS5wcm90b2J1Zi5VbmludGVy",
-            "cHJldGVkT3B0aW9uLk5hbWVQYXJ0EhgKEGlkZW50aWZpZXJfdmFsdWUYAyAB",
-            "KAkSGgoScG9zaXRpdmVfaW50X3ZhbHVlGAQgASgEEhoKEm5lZ2F0aXZlX2lu",
-            "dF92YWx1ZRgFIAEoAxIUCgxkb3VibGVfdmFsdWUYBiABKAESFAoMc3RyaW5n",
-            "X3ZhbHVlGAcgASgMEhcKD2FnZ3JlZ2F0ZV92YWx1ZRgIIAEoCRozCghOYW1l",
-            "UGFydBIRCgluYW1lX3BhcnQYASACKAkSFAoMaXNfZXh0ZW5zaW9uGAIgAigI",
-            "ItUBCg5Tb3VyY2VDb2RlSW5mbxI6Cghsb2NhdGlvbhgBIAMoCzIoLmdvb2ds",
-            "ZS5wcm90b2J1Zi5Tb3VyY2VDb2RlSW5mby5Mb2NhdGlvbhqGAQoITG9jYXRp",
-            "b24SEAoEcGF0aBgBIAMoBUICEAESEAoEc3BhbhgCIAMoBUICEAESGAoQbGVh",
-            "ZGluZ19jb21tZW50cxgDIAEoCRIZChF0cmFpbGluZ19jb21tZW50cxgEIAEo",
-            "CRIhChlsZWFkaW5nX2RldGFjaGVkX2NvbW1lbnRzGAYgAygJIqcBChFHZW5l",
-            "cmF0ZWRDb2RlSW5mbxJBCgphbm5vdGF0aW9uGAEgAygLMi0uZ29vZ2xlLnBy",
-            "b3RvYnVmLkdlbmVyYXRlZENvZGVJbmZvLkFubm90YXRpb24aTwoKQW5ub3Rh",
-            "dGlvbhIQCgRwYXRoGAEgAygFQgIQARITCgtzb3VyY2VfZmlsZRgCIAEoCRIN",
-            "CgViZWdpbhgDIAEoBRILCgNlbmQYBCABKAVCjwEKE2NvbS5nb29nbGUucHJv",
-            "dG9idWZCEERlc2NyaXB0b3JQcm90b3NIAVo+Z2l0aHViLmNvbS9nb2xhbmcv",
-            "cHJvdG9idWYvcHJvdG9jLWdlbi1nby9kZXNjcmlwdG9yO2Rlc2NyaXB0b3L4",
-            "AQGiAgNHUEKqAhpHb29nbGUuUHJvdG9idWYuUmVmbGVjdGlvbg=="));
+            "YnVmLlVuaW50ZXJwcmV0ZWRPcHRpb24qCQjoBxCAgICAAkoECAgQCUoECAkQ",
+            "CiKeAwoMRmllbGRPcHRpb25zEjoKBWN0eXBlGAEgASgOMiMuZ29vZ2xlLnBy",
+            "b3RvYnVmLkZpZWxkT3B0aW9ucy5DVHlwZToGU1RSSU5HEg4KBnBhY2tlZBgC",
+            "IAEoCBI/CgZqc3R5cGUYBiABKA4yJC5nb29nbGUucHJvdG9idWYuRmllbGRP",
+            "cHRpb25zLkpTVHlwZToJSlNfTk9STUFMEhMKBGxhenkYBSABKAg6BWZhbHNl",
+            "EhkKCmRlcHJlY2F0ZWQYAyABKAg6BWZhbHNlEhMKBHdlYWsYCiABKAg6BWZh",
+            "bHNlEkMKFHVuaW50ZXJwcmV0ZWRfb3B0aW9uGOcHIAMoCzIkLmdvb2dsZS5w",
+            "cm90b2J1Zi5VbmludGVycHJldGVkT3B0aW9uIi8KBUNUeXBlEgoKBlNUUklO",
+            "RxAAEggKBENPUkQQARIQCgxTVFJJTkdfUElFQ0UQAiI1CgZKU1R5cGUSDQoJ",
+            "SlNfTk9STUFMEAASDQoJSlNfU1RSSU5HEAESDQoJSlNfTlVNQkVSEAIqCQjo",
+            "BxCAgICAAkoECAQQBSJeCgxPbmVvZk9wdGlvbnMSQwoUdW5pbnRlcnByZXRl",
+            "ZF9vcHRpb24Y5wcgAygLMiQuZ29vZ2xlLnByb3RvYnVmLlVuaW50ZXJwcmV0",
+            "ZWRPcHRpb24qCQjoBxCAgICAAiKTAQoLRW51bU9wdGlvbnMSEwoLYWxsb3df",
+            "YWxpYXMYAiABKAgSGQoKZGVwcmVjYXRlZBgDIAEoCDoFZmFsc2USQwoUdW5p",
+            "bnRlcnByZXRlZF9vcHRpb24Y5wcgAygLMiQuZ29vZ2xlLnByb3RvYnVmLlVu",
+            "aW50ZXJwcmV0ZWRPcHRpb24qCQjoBxCAgICAAkoECAUQBiJ9ChBFbnVtVmFs",
+            "dWVPcHRpb25zEhkKCmRlcHJlY2F0ZWQYASABKAg6BWZhbHNlEkMKFHVuaW50",
+            "ZXJwcmV0ZWRfb3B0aW9uGOcHIAMoCzIkLmdvb2dsZS5wcm90b2J1Zi5Vbmlu",
+            "dGVycHJldGVkT3B0aW9uKgkI6AcQgICAgAIiewoOU2VydmljZU9wdGlvbnMS",
+            "GQoKZGVwcmVjYXRlZBghIAEoCDoFZmFsc2USQwoUdW5pbnRlcnByZXRlZF9v",
+            "cHRpb24Y5wcgAygLMiQuZ29vZ2xlLnByb3RvYnVmLlVuaW50ZXJwcmV0ZWRP",
+            "cHRpb24qCQjoBxCAgICAAiKtAgoNTWV0aG9kT3B0aW9ucxIZCgpkZXByZWNh",
+            "dGVkGCEgASgIOgVmYWxzZRJfChFpZGVtcG90ZW5jeV9sZXZlbBgiIAEoDjIv",
+            "Lmdvb2dsZS5wcm90b2J1Zi5NZXRob2RPcHRpb25zLklkZW1wb3RlbmN5TGV2",
+            "ZWw6E0lERU1QT1RFTkNZX1VOS05PV04SQwoUdW5pbnRlcnByZXRlZF9vcHRp",
+            "b24Y5wcgAygLMiQuZ29vZ2xlLnByb3RvYnVmLlVuaW50ZXJwcmV0ZWRPcHRp",
+            "b24iUAoQSWRlbXBvdGVuY3lMZXZlbBIXChNJREVNUE9URU5DWV9VTktOT1dO",
+            "EAASEwoPTk9fU0lERV9FRkZFQ1RTEAESDgoKSURFTVBPVEVOVBACKgkI6AcQ",
+            "gICAgAIingIKE1VuaW50ZXJwcmV0ZWRPcHRpb24SOwoEbmFtZRgCIAMoCzIt",
+            "Lmdvb2dsZS5wcm90b2J1Zi5VbmludGVycHJldGVkT3B0aW9uLk5hbWVQYXJ0",
+            "EhgKEGlkZW50aWZpZXJfdmFsdWUYAyABKAkSGgoScG9zaXRpdmVfaW50X3Zh",
+            "bHVlGAQgASgEEhoKEm5lZ2F0aXZlX2ludF92YWx1ZRgFIAEoAxIUCgxkb3Vi",
+            "bGVfdmFsdWUYBiABKAESFAoMc3RyaW5nX3ZhbHVlGAcgASgMEhcKD2FnZ3Jl",
+            "Z2F0ZV92YWx1ZRgIIAEoCRozCghOYW1lUGFydBIRCgluYW1lX3BhcnQYASAC",
+            "KAkSFAoMaXNfZXh0ZW5zaW9uGAIgAigIItUBCg5Tb3VyY2VDb2RlSW5mbxI6",
+            "Cghsb2NhdGlvbhgBIAMoCzIoLmdvb2dsZS5wcm90b2J1Zi5Tb3VyY2VDb2Rl",
+            "SW5mby5Mb2NhdGlvbhqGAQoITG9jYXRpb24SEAoEcGF0aBgBIAMoBUICEAES",
+            "EAoEc3BhbhgCIAMoBUICEAESGAoQbGVhZGluZ19jb21tZW50cxgDIAEoCRIZ",
+            "ChF0cmFpbGluZ19jb21tZW50cxgEIAEoCRIhChlsZWFkaW5nX2RldGFjaGVk",
+            "X2NvbW1lbnRzGAYgAygJIqcBChFHZW5lcmF0ZWRDb2RlSW5mbxJBCgphbm5v",
+            "dGF0aW9uGAEgAygLMi0uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZENvZGVJ",
+            "bmZvLkFubm90YXRpb24aTwoKQW5ub3RhdGlvbhIQCgRwYXRoGAEgAygFQgIQ",
+            "ARITCgtzb3VyY2VfZmlsZRgCIAEoCRINCgViZWdpbhgDIAEoBRILCgNlbmQY",
+            "BCABKAVCjwEKE2NvbS5nb29nbGUucHJvdG9idWZCEERlc2NyaXB0b3JQcm90",
+            "b3NIAVo+Z2l0aHViLmNvbS9nb2xhbmcvcHJvdG9idWYvcHJvdG9jLWdlbi1n",
+            "by9kZXNjcmlwdG9yO2Rlc2NyaXB0b3L4AQGiAgNHUEKqAhpHb29nbGUuUHJv",
+            "dG9idWYuUmVmbGVjdGlvbg=="));
       descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
       descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
           new pbr::FileDescriptor[] { },
           new pbr::FileDescriptor[] { },
           new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] {
           new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] {
@@ -166,7 +167,7 @@ namespace Google.Protobuf.Reflection {
             new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.DescriptorProto), global::Google.Protobuf.Reflection.DescriptorProto.Parser, new[]{ "Name", "Field", "Extension", "NestedType", "EnumType", "ExtensionRange", "OneofDecl", "Options", "ReservedRange", "ReservedName" }, null, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.DescriptorProto.Types.ExtensionRange), global::Google.Protobuf.Reflection.DescriptorProto.Types.ExtensionRange.Parser, new[]{ "Start", "End", "Options" }, null, null, null, null),
             new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.DescriptorProto), global::Google.Protobuf.Reflection.DescriptorProto.Parser, new[]{ "Name", "Field", "Extension", "NestedType", "EnumType", "ExtensionRange", "OneofDecl", "Options", "ReservedRange", "ReservedName" }, null, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.DescriptorProto.Types.ExtensionRange), global::Google.Protobuf.Reflection.DescriptorProto.Types.ExtensionRange.Parser, new[]{ "Start", "End", "Options" }, null, null, null, null),
             new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.DescriptorProto.Types.ReservedRange), global::Google.Protobuf.Reflection.DescriptorProto.Types.ReservedRange.Parser, new[]{ "Start", "End" }, null, null, null, null)}),
             new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.DescriptorProto.Types.ReservedRange), global::Google.Protobuf.Reflection.DescriptorProto.Types.ReservedRange.Parser, new[]{ "Start", "End" }, null, null, null, null)}),
             new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.ExtensionRangeOptions), global::Google.Protobuf.Reflection.ExtensionRangeOptions.Parser, new[]{ "UninterpretedOption" }, null, null, null, null),
             new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.ExtensionRangeOptions), global::Google.Protobuf.Reflection.ExtensionRangeOptions.Parser, new[]{ "UninterpretedOption" }, null, null, null, null),
-            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.FieldDescriptorProto), global::Google.Protobuf.Reflection.FieldDescriptorProto.Parser, new[]{ "Name", "Number", "Label", "Type", "TypeName", "Extendee", "DefaultValue", "OneofIndex", "JsonName", "Options" }, null, new[]{ typeof(global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Type), typeof(global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Label) }, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.FieldDescriptorProto), global::Google.Protobuf.Reflection.FieldDescriptorProto.Parser, new[]{ "Name", "Number", "Label", "Type", "TypeName", "Extendee", "DefaultValue", "OneofIndex", "JsonName", "Options", "Proto3Optional" }, null, new[]{ typeof(global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Type), typeof(global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Label) }, null, null),
             new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.OneofDescriptorProto), global::Google.Protobuf.Reflection.OneofDescriptorProto.Parser, new[]{ "Name", "Options" }, null, null, null, null),
             new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.OneofDescriptorProto), global::Google.Protobuf.Reflection.OneofDescriptorProto.Parser, new[]{ "Name", "Options" }, null, null, null, null),
             new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.EnumDescriptorProto), global::Google.Protobuf.Reflection.EnumDescriptorProto.Parser, new[]{ "Name", "Value", "Options", "ReservedRange", "ReservedName" }, null, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.EnumDescriptorProto.Types.EnumReservedRange), global::Google.Protobuf.Reflection.EnumDescriptorProto.Types.EnumReservedRange.Parser, new[]{ "Start", "End" }, null, null, null, null)}),
             new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.EnumDescriptorProto), global::Google.Protobuf.Reflection.EnumDescriptorProto.Parser, new[]{ "Name", "Value", "Options", "ReservedRange", "ReservedName" }, null, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.EnumDescriptorProto.Types.EnumReservedRange), global::Google.Protobuf.Reflection.EnumDescriptorProto.Types.EnumReservedRange.Parser, new[]{ "Start", "End" }, null, null, null, null)}),
             new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.EnumValueDescriptorProto), global::Google.Protobuf.Reflection.EnumValueDescriptorProto.Parser, new[]{ "Name", "Number", "Options" }, null, null, null, null),
             new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.EnumValueDescriptorProto), global::Google.Protobuf.Reflection.EnumValueDescriptorProto.Parser, new[]{ "Name", "Number", "Options" }, null, null, null, null),
@@ -1791,6 +1792,7 @@ namespace Google.Protobuf.Reflection {
       oneofIndex_ = other.oneofIndex_;
       oneofIndex_ = other.oneofIndex_;
       jsonName_ = other.jsonName_;
       jsonName_ = other.jsonName_;
       options_ = other.HasOptions ? other.options_.Clone() : null;
       options_ = other.HasOptions ? other.options_.Clone() : null;
+      proto3Optional_ = other.proto3Optional_;
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
     }
 
 
@@ -2063,6 +2065,42 @@ namespace Google.Protobuf.Reflection {
       options_ = null;
       options_ = null;
     }
     }
 
 
+    /// <summary>Field number for the "proto3_optional" field.</summary>
+    public const int Proto3OptionalFieldNumber = 17;
+    private readonly static bool Proto3OptionalDefaultValue = false;
+
+    private bool proto3Optional_;
+    /// <summary>
+    /// If true, this is a proto3 "optional". When a proto3 field is optional, it
+    /// tracks presence regardless of field type.
+    ///
+    /// For message fields this doesn't create any semantic change, since
+    /// non-repeated message fields always track presence. However it still
+    /// indicates the semantic detail of whether the user wrote "optional" or not.
+    /// This can be useful for round-tripping the .proto file.
+    ///
+    /// Proto2 optional fields do not set this flag, because they already indicate
+    /// optional with `LABEL_OPTIONAL`.
+    /// </summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool Proto3Optional {
+      get { if ((_hasBits0 & 16) != 0) { return proto3Optional_; } else { return Proto3OptionalDefaultValue; } }
+      set {
+        _hasBits0 |= 16;
+        proto3Optional_ = value;
+      }
+    }
+    /// <summary>Gets whether the "proto3_optional" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasProto3Optional {
+      get { return (_hasBits0 & 16) != 0; }
+    }
+    /// <summary>Clears the value of the "proto3_optional" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearProto3Optional() {
+      _hasBits0 &= ~16;
+    }
+
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override bool Equals(object other) {
     public override bool Equals(object other) {
       return Equals(other as FieldDescriptorProto);
       return Equals(other as FieldDescriptorProto);
@@ -2086,6 +2124,7 @@ namespace Google.Protobuf.Reflection {
       if (OneofIndex != other.OneofIndex) return false;
       if (OneofIndex != other.OneofIndex) return false;
       if (JsonName != other.JsonName) return false;
       if (JsonName != other.JsonName) return false;
       if (!object.Equals(Options, other.Options)) return false;
       if (!object.Equals(Options, other.Options)) return false;
+      if (Proto3Optional != other.Proto3Optional) return false;
       return Equals(_unknownFields, other._unknownFields);
       return Equals(_unknownFields, other._unknownFields);
     }
     }
 
 
@@ -2102,6 +2141,7 @@ namespace Google.Protobuf.Reflection {
       if (HasOneofIndex) hash ^= OneofIndex.GetHashCode();
       if (HasOneofIndex) hash ^= OneofIndex.GetHashCode();
       if (HasJsonName) hash ^= JsonName.GetHashCode();
       if (HasJsonName) hash ^= JsonName.GetHashCode();
       if (HasOptions) hash ^= Options.GetHashCode();
       if (HasOptions) hash ^= Options.GetHashCode();
+      if (HasProto3Optional) hash ^= Proto3Optional.GetHashCode();
       if (_unknownFields != null) {
       if (_unknownFields != null) {
         hash ^= _unknownFields.GetHashCode();
         hash ^= _unknownFields.GetHashCode();
       }
       }
@@ -2155,6 +2195,10 @@ namespace Google.Protobuf.Reflection {
         output.WriteRawTag(82);
         output.WriteRawTag(82);
         output.WriteString(JsonName);
         output.WriteString(JsonName);
       }
       }
+      if (HasProto3Optional) {
+        output.WriteRawTag(136, 1);
+        output.WriteBool(Proto3Optional);
+      }
       if (_unknownFields != null) {
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
         _unknownFields.WriteTo(output);
       }
       }
@@ -2193,6 +2237,9 @@ namespace Google.Protobuf.Reflection {
       if (HasOptions) {
       if (HasOptions) {
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(Options);
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(Options);
       }
       }
+      if (HasProto3Optional) {
+        size += 2 + 1;
+      }
       if (_unknownFields != null) {
       if (_unknownFields != null) {
         size += _unknownFields.CalculateSize();
         size += _unknownFields.CalculateSize();
       }
       }
@@ -2237,6 +2284,9 @@ namespace Google.Protobuf.Reflection {
         }
         }
         Options.MergeFrom(other.Options);
         Options.MergeFrom(other.Options);
       }
       }
+      if (other.HasProto3Optional) {
+        Proto3Optional = other.Proto3Optional;
+      }
       _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
       _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
     }
 
 
@@ -2291,6 +2341,10 @@ namespace Google.Protobuf.Reflection {
             JsonName = input.ReadString();
             JsonName = input.ReadString();
             break;
             break;
           }
           }
+          case 136: {
+            Proto3Optional = input.ReadBool();
+            break;
+          }
         }
         }
       }
       }
     }
     }
@@ -4222,7 +4276,7 @@ namespace Google.Protobuf.Reflection {
 
 
     /// <summary>Field number for the "cc_enable_arenas" field.</summary>
     /// <summary>Field number for the "cc_enable_arenas" field.</summary>
     public const int CcEnableArenasFieldNumber = 31;
     public const int CcEnableArenasFieldNumber = 31;
-    private readonly static bool CcEnableArenasDefaultValue = false;
+    private readonly static bool CcEnableArenasDefaultValue = true;
 
 
     private bool ccEnableArenas_;
     private bool ccEnableArenas_;
     /// <summary>
     /// <summary>

+ 4 - 0
docs/options.md

@@ -240,3 +240,7 @@ with info about your project (name and website) so we can add an entry for you.
 1. SummaFT protoc-plugins
 1. SummaFT protoc-plugins
    * Website: https://summaft.com/
    * Website: https://summaft.com/
    * Extensions: 1085
    * Extensions: 1085
+
+1. ADLINK EdgeSDK
+   * Website: https://www.adlinktech.com/en/Edge-SDK-IoT
+   * Extensions: 1086

+ 8 - 0
examples/README.md

@@ -0,0 +1,8 @@
+#!/bin/bash
+for file in $(find . -type f); do
+  if [ "$(head -c 2 $file)" == "#!" ]; then
+    chmod u+x $file
+  else
+    chmod a-x $file
+  fi
+done

+ 1 - 0
java/core/src/main/java/com/google/protobuf/AllocatedBuffer.java

@@ -72,6 +72,7 @@ class Descriptor
             ->optional('oneof_index', \Google\Protobuf\Internal\GPBType::INT32, 9)
             ->optional('oneof_index', \Google\Protobuf\Internal\GPBType::INT32, 9)
             ->optional('json_name', \Google\Protobuf\Internal\GPBType::STRING, 10)
             ->optional('json_name', \Google\Protobuf\Internal\GPBType::STRING, 10)
             ->optional('options', \Google\Protobuf\Internal\GPBType::MESSAGE, 8, 'google.protobuf.internal.FieldOptions')
             ->optional('options', \Google\Protobuf\Internal\GPBType::MESSAGE, 8, 'google.protobuf.internal.FieldOptions')
+            ->optional('proto3_optional', \Google\Protobuf\Internal\GPBType::BOOL, 17)
             ->finalizeToPool();
             ->finalizeToPool();
 
 
         $pool->addEnum('google.protobuf.internal.FieldDescriptorProto.Type', \Google\Protobuf\Internal\Type::class)
         $pool->addEnum('google.protobuf.internal.FieldDescriptorProto.Type', \Google\Protobuf\Internal\Type::class)

+ 69 - 0
php/src/Google/Protobuf/Internal/FieldDescriptorProto.php

@@ -93,6 +93,20 @@ class FieldDescriptorProto extends \Google\Protobuf\Internal\Message
      */
      */
     protected $options = null;
     protected $options = null;
     private $has_options = false;
     private $has_options = false;
+    /**
+     * If true, this is a proto3 "optional". When a proto3 field is optional, it
+     * tracks presence regardless of field type.
+     * For message fields this doesn't create any semantic change, since
+     * non-repeated message fields always track presence. However it still
+     * indicates the semantic detail of whether the user wrote "optional" or not.
+     * This can be useful for round-tripping the .proto file.
+     * Proto2 optional fields do not set this flag, because they already indicate
+     * optional with `LABEL_OPTIONAL`.
+     *
+     * Generated from protobuf field <code>optional bool proto3_optional = 17;</code>
+     */
+    protected $proto3_optional = false;
+    private $has_proto3_optional = false;
 
 
     /**
     /**
      * Constructor.
      * Constructor.
@@ -130,6 +144,15 @@ class FieldDescriptorProto extends \Google\Protobuf\Internal\Message
      *           will be used. Otherwise, it's deduced from the field's name by converting
      *           will be used. Otherwise, it's deduced from the field's name by converting
      *           it to camelCase.
      *           it to camelCase.
      *     @type \Google\Protobuf\Internal\FieldOptions $options
      *     @type \Google\Protobuf\Internal\FieldOptions $options
+     *     @type bool $proto3_optional
+     *           If true, this is a proto3 "optional". When a proto3 field is optional, it
+     *           tracks presence regardless of field type.
+     *           For message fields this doesn't create any semantic change, since
+     *           non-repeated message fields always track presence. However it still
+     *           indicates the semantic detail of whether the user wrote "optional" or not.
+     *           This can be useful for round-tripping the .proto file.
+     *           Proto2 optional fields do not set this flag, because they already indicate
+     *           optional with `LABEL_OPTIONAL`.
      * }
      * }
      */
      */
     public function __construct($data = NULL) {
     public function __construct($data = NULL) {
@@ -469,5 +492,51 @@ class FieldDescriptorProto extends \Google\Protobuf\Internal\Message
         return $this->has_options;
         return $this->has_options;
     }
     }
 
 
+    /**
+     * If true, this is a proto3 "optional". When a proto3 field is optional, it
+     * tracks presence regardless of field type.
+     * For message fields this doesn't create any semantic change, since
+     * non-repeated message fields always track presence. However it still
+     * indicates the semantic detail of whether the user wrote "optional" or not.
+     * This can be useful for round-tripping the .proto file.
+     * Proto2 optional fields do not set this flag, because they already indicate
+     * optional with `LABEL_OPTIONAL`.
+     *
+     * Generated from protobuf field <code>optional bool proto3_optional = 17;</code>
+     * @return bool
+     */
+    public function getProto3Optional()
+    {
+        return $this->proto3_optional;
+    }
+
+    /**
+     * If true, this is a proto3 "optional". When a proto3 field is optional, it
+     * tracks presence regardless of field type.
+     * For message fields this doesn't create any semantic change, since
+     * non-repeated message fields always track presence. However it still
+     * indicates the semantic detail of whether the user wrote "optional" or not.
+     * This can be useful for round-tripping the .proto file.
+     * Proto2 optional fields do not set this flag, because they already indicate
+     * optional with `LABEL_OPTIONAL`.
+     *
+     * Generated from protobuf field <code>optional bool proto3_optional = 17;</code>
+     * @param bool $var
+     * @return $this
+     */
+    public function setProto3Optional($var)
+    {
+        GPBUtil::checkBool($var);
+        $this->proto3_optional = $var;
+        $this->has_proto3_optional = true;
+
+        return $this;
+    }
+
+    public function hasProto3Optional()
+    {
+        return $this->has_proto3_optional;
+    }
+
 }
 }
 
 

+ 3 - 3
php/src/Google/Protobuf/Internal/FileOptions.php

@@ -127,7 +127,7 @@ class FileOptions extends \Google\Protobuf\Internal\Message
      * Enables the use of arenas for the proto messages in this file. This applies
      * Enables the use of arenas for the proto messages in this file. This applies
      * only to generated classes for C++.
      * only to generated classes for C++.
      *
      *
-     * Generated from protobuf field <code>optional bool cc_enable_arenas = 31 [default = false];</code>
+     * Generated from protobuf field <code>optional bool cc_enable_arenas = 31 [default = true];</code>
      */
      */
     protected $cc_enable_arenas = false;
     protected $cc_enable_arenas = false;
     private $has_cc_enable_arenas = false;
     private $has_cc_enable_arenas = false;
@@ -732,7 +732,7 @@ class FileOptions extends \Google\Protobuf\Internal\Message
      * Enables the use of arenas for the proto messages in this file. This applies
      * Enables the use of arenas for the proto messages in this file. This applies
      * only to generated classes for C++.
      * only to generated classes for C++.
      *
      *
-     * Generated from protobuf field <code>optional bool cc_enable_arenas = 31 [default = false];</code>
+     * Generated from protobuf field <code>optional bool cc_enable_arenas = 31 [default = true];</code>
      * @return bool
      * @return bool
      */
      */
     public function getCcEnableArenas()
     public function getCcEnableArenas()
@@ -744,7 +744,7 @@ class FileOptions extends \Google\Protobuf\Internal\Message
      * Enables the use of arenas for the proto messages in this file. This applies
      * Enables the use of arenas for the proto messages in this file. This applies
      * only to generated classes for C++.
      * only to generated classes for C++.
      *
      *
-     * Generated from protobuf field <code>optional bool cc_enable_arenas = 31 [default = false];</code>
+     * Generated from protobuf field <code>optional bool cc_enable_arenas = 31 [default = true];</code>
      * @param bool $var
      * @param bool $var
      * @return $this
      * @return $this
      */
      */

+ 29 - 2
php/tests/autoload.php

@@ -36,6 +36,7 @@ __author__ = 'jieluo@google.com (Jie Luo)'
 
 
 import json
 import json
 import math
 import math
+import struct
 import sys
 import sys
 
 
 try:
 try:
@@ -821,15 +822,41 @@ class JsonFormatTest(JsonFormatBase):
   def testFloatPrecision(self):
   def testFloatPrecision(self):
     message = json_format_proto3_pb2.TestMessage()
     message = json_format_proto3_pb2.TestMessage()
     message.float_value = 1.123456789
     message.float_value = 1.123456789
-    # Default to 8 valid digits.
+    # Set to 8 valid digits.
     text = '{\n  "floatValue": 1.1234568\n}'
     text = '{\n  "floatValue": 1.1234568\n}'
     self.assertEqual(
     self.assertEqual(
-        json_format.MessageToJson(message), text)
+        json_format.MessageToJson(message, float_precision=8), text)
     # Set to 7 valid digits.
     # Set to 7 valid digits.
     text = '{\n  "floatValue": 1.123457\n}'
     text = '{\n  "floatValue": 1.123457\n}'
     self.assertEqual(
     self.assertEqual(
         json_format.MessageToJson(message, float_precision=7), text)
         json_format.MessageToJson(message, float_precision=7), text)
 
 
+    # Default float_precision will automatic print shortest float.
+    message.float_value = 1.1000000011
+    text = '{\n  "floatValue": 1.1\n}'
+    self.assertEqual(
+        json_format.MessageToJson(message), text)
+    message.float_value = 1.00000075e-36
+    text = '{\n  "floatValue": 1.00000075e-36\n}'
+    self.assertEqual(
+        json_format.MessageToJson(message), text)
+    message.float_value = 12345678912345e+11
+    text = '{\n  "floatValue": 1.234568e+24\n}'
+    self.assertEqual(
+        json_format.MessageToJson(message), text)
+
+    # Test a bunch of data and check json encode/decode do not
+    # lose precision
+    value_list = [0x00, 0xD8, 0x6E, 0x00]
+    msg2 = json_format_proto3_pb2.TestMessage()
+    for a in range(0, 256):
+      value_list[3] = a
+      for b in range(0, 256):
+        value_list[0] = b
+        byte_array = bytearray(value_list)
+        message.float_value = struct.unpack('<f', byte_array)[0]
+        self.CheckParseBack(message, msg2)
+
   def testParseEmptyText(self):
   def testParseEmptyText(self):
     self.CheckError('',
     self.CheckError('',
                     r'Failed to load JSON: (Expecting value)|(No JSON).')
                     r'Failed to load JSON: (Expecting value)|(No JSON).')

+ 9 - 4
python/google/protobuf/internal/message_factory_test.py

@@ -64,6 +64,14 @@ from google.protobuf import descriptor
 
 
 _FieldDescriptor = descriptor.FieldDescriptor
 _FieldDescriptor = descriptor.FieldDescriptor
 
 
+
+def TruncateToFourByteFloat(original):
+  if ctypes:
+    return ctypes.c_float(original).value
+  else:
+    return struct.unpack('<f', struct.pack('<f', original))[0]
+
+
 def SupportsOpenEnums(field_descriptor):
 def SupportsOpenEnums(field_descriptor):
   return field_descriptor.containing_type.syntax == "proto3"
   return field_descriptor.containing_type.syntax == "proto3"
 
 
@@ -262,10 +270,7 @@ class FloatValueChecker(object):
     if converted_value < _FLOAT_MIN:
     if converted_value < _FLOAT_MIN:
       return _NEG_INF
       return _NEG_INF
 
 
-    if ctypes:
-      return ctypes.c_float(converted_value).value
-    else:
-      return struct.unpack('<f', struct.pack('<f', converted_value))[0]
+    return TruncateToFourByteFloat(converted_value)
 
 
   def DefaultValue(self):
   def DefaultValue(self):
     return 0.0
     return 0.0

+ 28 - 7
python/google/protobuf/internal/well_known_types_test.py

@@ -60,6 +60,7 @@ import sys
 
 
 import six
 import six
 
 
+from google.protobuf.internal import type_checkers
 from google.protobuf import descriptor
 from google.protobuf import descriptor
 from google.protobuf import symbol_database
 from google.protobuf import symbol_database
 
 
@@ -104,7 +105,7 @@ def MessageToJson(
     sort_keys=False,
     sort_keys=False,
     use_integers_for_enums=False,
     use_integers_for_enums=False,
     descriptor_pool=None,
     descriptor_pool=None,
-    float_precision=8):
+    float_precision=None):
   """Converts protobuf message to JSON format.
   """Converts protobuf message to JSON format.
 
 
   Args:
   Args:
@@ -123,7 +124,6 @@ def MessageToJson(
     descriptor_pool: A Descriptor Pool for resolving types. If None use the
     descriptor_pool: A Descriptor Pool for resolving types. If None use the
         default.
         default.
     float_precision: If set, use this to specify float field valid digits.
     float_precision: If set, use this to specify float field valid digits.
-        Otherwise, 8 valid digits is used (default '.8g').
 
 
   Returns:
   Returns:
     A string containing the JSON formatted protocol buffer message.
     A string containing the JSON formatted protocol buffer message.
@@ -143,7 +143,7 @@ def MessageToDict(
     preserving_proto_field_name=False,
     preserving_proto_field_name=False,
     use_integers_for_enums=False,
     use_integers_for_enums=False,
     descriptor_pool=None,
     descriptor_pool=None,
-    float_precision=8):
+    float_precision=None):
   """Converts protobuf message to a dictionary.
   """Converts protobuf message to a dictionary.
 
 
   When the dictionary is encoded to JSON, it conforms to proto3 JSON spec.
   When the dictionary is encoded to JSON, it conforms to proto3 JSON spec.
@@ -161,7 +161,6 @@ def MessageToDict(
     descriptor_pool: A Descriptor Pool for resolving types. If None use the
     descriptor_pool: A Descriptor Pool for resolving types. If None use the
         default.
         default.
     float_precision: If set, use this to specify float field valid digits.
     float_precision: If set, use this to specify float field valid digits.
-        Otherwise, 8 valid digits is used (default '.8g').
 
 
   Returns:
   Returns:
     A dict representation of the protocol buffer message.
     A dict representation of the protocol buffer message.
@@ -284,6 +283,25 @@ class _Printer(object):
 
 
   def _FieldToJsonObject(self, field, value):
   def _FieldToJsonObject(self, field, value):
     """Converts field value according to Proto3 JSON Specification."""
     """Converts field value according to Proto3 JSON Specification."""
+
+    def _ToShortestFloat(original):
+      """Returns the shortest float that has same value in wire."""
+      # Return the original value if it is not truncated. This may happen
+      # if someone mixes this code with an old protobuf runtime.
+      if type_checkers.TruncateToFourByteFloat(original) != original:
+        return original
+      # All 4 byte floats have between 6 and 9 significant digits, so we
+      # start with 6 as the lower bound.
+      # It has to be iterative because use '.9g' directly can not get rid
+      # of the noises for most values. For example if set a float_field=0.9
+      # use '.9g' will print 0.899999976.
+      precision = 6
+      rounded = float('{0:.{1}g}'.format(original, precision))
+      while type_checkers.TruncateToFourByteFloat(rounded) != original:
+        precision += 1
+        rounded = float('{0:.{1}g}'.format(original, precision))
+      return rounded
+
     if field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE:
     if field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE:
       return self._MessageToJsonObject(value)
       return self._MessageToJsonObject(value)
     elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_ENUM:
     elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_ENUM:
@@ -315,9 +333,12 @@ class _Printer(object):
           return _INFINITY
           return _INFINITY
       if math.isnan(value):
       if math.isnan(value):
         return _NAN
         return _NAN
-      if (self.float_format and
-          field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_FLOAT):
-        return float(format(value, self.float_format))
+      if field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_FLOAT:
+        if self.float_format:
+          return float(format(value, self.float_format))
+        else:
+          return _ToShortestFloat(value)
+
     return value
     return value
 
 
   def _AnyMessageToJsonObject(self, message):
   def _AnyMessageToJsonObject(self, message):

+ 9 - 5
python/google/protobuf/message.py

@@ -30,6 +30,10 @@
 
 
 #include "protobuf.h"
 #include "protobuf.h"
 
 
+VALUE initialize_rb_class_with_no_args(VALUE klass) {
+  return rb_funcall(klass, rb_intern("new"), 0);
+}
+
 // This function is equivalent to rb_str_cat(), but unlike the real
 // This function is equivalent to rb_str_cat(), but unlike the real
 // rb_str_cat(), it doesn't leak memory in some versions of Ruby.
 // rb_str_cat(), it doesn't leak memory in some versions of Ruby.
 // For more information, see:
 // For more information, see:
@@ -295,7 +299,7 @@ static void *appendsubmsg_handler(void *closure, const void *hd) {
   const submsg_handlerdata_t *submsgdata = hd;
   const submsg_handlerdata_t *submsgdata = hd;
   MessageHeader* submsg;
   MessageHeader* submsg;
 
 
-  VALUE submsg_rb = rb_class_new_instance(0, NULL, submsgdata->subklass);
+  VALUE submsg_rb = initialize_rb_class_with_no_args(submsgdata->subklass);
   RepeatedField_push(ary, submsg_rb);
   RepeatedField_push(ary, submsg_rb);
 
 
   TypedData_Get_Struct(submsg_rb, MessageHeader, &Message_type, submsg);
   TypedData_Get_Struct(submsg_rb, MessageHeader, &Message_type, submsg);
@@ -322,7 +326,7 @@ static void *submsg_handler(void *closure, const void *hd) {
 
 
   if (DEREF(msg, submsgdata->ofs, VALUE) == Qnil) {
   if (DEREF(msg, submsgdata->ofs, VALUE) == Qnil) {
     DEREF(msg, submsgdata->ofs, VALUE) =
     DEREF(msg, submsgdata->ofs, VALUE) =
-        rb_class_new_instance(0, NULL, submsgdata->subklass);
+        initialize_rb_class_with_no_args(submsgdata->subklass);
   }
   }
 
 
   set_hasbit(closure, submsgdata->hasbit);
   set_hasbit(closure, submsgdata->hasbit);
@@ -549,7 +553,7 @@ static void *oneofsubmsg_handler(void *closure,
   if (oldcase != oneofdata->oneof_case_num ||
   if (oldcase != oneofdata->oneof_case_num ||
       DEREF(msg, oneofdata->ofs, VALUE) == Qnil) {
       DEREF(msg, oneofdata->ofs, VALUE) == Qnil) {
     DEREF(msg, oneofdata->ofs, VALUE) =
     DEREF(msg, oneofdata->ofs, VALUE) =
-        rb_class_new_instance(0, NULL, oneofdata->subklass);
+        initialize_rb_class_with_no_args(oneofdata->subklass);
   }
   }
   // Set the oneof case *after* allocating the new class instance -- otherwise,
   // Set the oneof case *after* allocating the new class instance -- otherwise,
   // if the Ruby GC is invoked as part of a call into the VM, it might invoke
   // if the Ruby GC is invoked as part of a call into the VM, it might invoke
@@ -1038,7 +1042,7 @@ VALUE Message_decode(VALUE klass, VALUE data) {
     rb_raise(rb_eArgError, "Expected string for binary protobuf data.");
     rb_raise(rb_eArgError, "Expected string for binary protobuf data.");
   }
   }
 
 
-  msg_rb = rb_class_new_instance(0, NULL, msgklass);
+  msg_rb = initialize_rb_class_with_no_args(msgklass);
   TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);
   TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);
 
 
   {
   {
@@ -1114,7 +1118,7 @@ VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass) {
   // convert, because string handlers pass data directly to message string
   // convert, because string handlers pass data directly to message string
   // fields.
   // fields.
 
 
-  msg_rb = rb_class_new_instance(0, NULL, msgklass);
+  msg_rb = initialize_rb_class_with_no_args(msgklass);
   TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);
   TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);
 
 
   {
   {

+ 8 - 12
ruby/ext/google/protobuf_c/extconf.rb

@@ -219,14 +219,15 @@ struct ArenaOptions {
 // any special requirements on the type T, and will invoke the object's
 // any special requirements on the type T, and will invoke the object's
 // destructor when the arena is destroyed.
 // destructor when the arena is destroyed.
 //
 //
-// The arena message allocation protocol, required by CreateMessage<T>, is as
-// follows:
+// The arena message allocation protocol, required by
+// CreateMessage<T>(Arena* arena, Args&&... args), is as follows:
 //
 //
-// - The type T must have (at least) two constructors: a constructor with no
-//   arguments, called when a T is allocated on the heap; and a constructor with
-//   a Arena* argument, called when a T is allocated on an arena. If the
-//   second constructor is called with a NULL arena pointer, it must be
-//   equivalent to invoking the first (no-argument) constructor.
+// - The type T must have (at least) two constructors: a constructor callable
+//   with `args` (without `arena`), called when a T is allocated on the heap;
+//   and a constructor callable with `Arena* arena, Args&&... args`, called when
+//   a T is allocated on an arena. If the second constructor is called with a
+//   NULL arena pointer, it must be equivalent to invoking the first
+//   (`args`-only) constructor.
 //
 //
 // - The type T must have a particular type trait: a nested type
 // - The type T must have a particular type trait: a nested type
 //   |InternalArenaConstructable_|. This is usually a typedef to |void|. If no
 //   |InternalArenaConstructable_|. This is usually a typedef to |void|. If no
@@ -239,11 +240,6 @@ struct ArenaOptions {
 //   present on the type, then its destructor is always called when the
 //   present on the type, then its destructor is always called when the
 //   containing arena is destroyed.
 //   containing arena is destroyed.
 //
 //
-// - One- and two-user-argument forms of CreateMessage<T>() also exist that
-//   forward these constructor arguments to T's constructor: for example,
-//   CreateMessage<T>(Arena*, arg1, arg2) forwards to a constructor T(Arena*,
-//   arg1, arg2).
-//
 // This protocol is implemented by all arena-enabled proto2 message classes as
 // This protocol is implemented by all arena-enabled proto2 message classes as
 // well as protobuf container types like RepeatedPtrField and Map. The protocol
 // well as protobuf container types like RepeatedPtrField and Map. The protocol
 // is internal to protobuf and is not guaranteed to be stable. Non-proto types
 // is internal to protobuf and is not guaranteed to be stable. Non-proto types

+ 3 - 0
src/google/protobuf/compiler/command_line_interface.cc

@@ -1105,6 +1105,9 @@ PopulateSingleSimpleDescriptorDatabase(const std::string& descriptor_set_name) {
 bool CommandLineInterface::AllowProto3Optional(
 bool CommandLineInterface::AllowProto3Optional(
     const FileDescriptor& file) const {
     const FileDescriptor& file) const {
   if (allow_proto3_optional_) return true;
   if (allow_proto3_optional_) return true;
+  if (file.name() == "google/protobuf/unittest_proto3_optional.proto") {
+    return true;
+  }
   return false;
   return false;
 }
 }
 
 

+ 2 - 1
src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc

@@ -81,7 +81,8 @@ class PROTOC_EXPORT CppGenerator : public CodeGenerator {
 
 
   // implements CodeGenerator ----------------------------------------
   // implements CodeGenerator ----------------------------------------
   bool Generate(const FileDescriptor* file, const std::string& parameter,
   bool Generate(const FileDescriptor* file, const std::string& parameter,
-                GeneratorContext* generator_context, std::string* error) const;
+                GeneratorContext* generator_context,
+                std::string* error) const override;
 
 
   uint64 GetSupportedFeatures() const override {
   uint64 GetSupportedFeatures() const override {
     // We don't fully support this yet, but this is needed to unblock the tests,
     // We don't fully support this yet, but this is needed to unblock the tests,

+ 15 - 2
src/google/protobuf/compiler/cpp/cpp_helpers.h

@@ -429,9 +429,22 @@ inline bool HasFieldPresence(const FileDescriptor* file) {
 }
 }
 
 
 inline bool HasHasbit(const FieldDescriptor* field) {
 inline bool HasHasbit(const FieldDescriptor* field) {
-  // TODO(haberman): remove, and give some proto3 fields hasbits.
+  // TODO(haberman): remove, so proto3 optional fields have hasbits.
   if (field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3) return false;
   if (field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3) return false;
-  return field->is_singular_with_presence();
+
+  // This predicate includes proto3 message fields only if they have "optional".
+  //   Foo submsg1 = 1;           // HasHasbit() == false
+  //   optional Foo submsg2 = 2;  // HasHasbit() == true
+  // This is slightly odd, as adding "optional" to a singular proto3 field does
+  // not change the semantics or API. However whenever any field in a message
+  // has a hasbit, it forces reflection to include hasbit offsets for *all*
+  // fields, even if almost all of them are set to -1 (no hasbit). So to avoid
+  // causing a sudden size regression for ~all proto3 messages, we give proto3
+  // message fields a hasbit only if "optional" is present. If the user is
+  // explicitly writing "optional", it is likely they are writing it on
+  // primitive fields also.
+  return (field->has_optional_keyword() || field->is_required()) &&
+         !field->options().weak();
 }
 }
 
 
 // Returns true if 'enum' semantics are such that unknown values are preserved
 // Returns true if 'enum' semantics are such that unknown values are preserved

+ 82 - 85
src/google/protobuf/compiler/cpp/cpp_message.cc

@@ -69,6 +69,8 @@ using internal::WireFormatLite;
 
 
 namespace {
 namespace {
 
 
+static constexpr int kNoHasbit = -1;
+
 // Create an expression that evaluates to
 // Create an expression that evaluates to
 //  "for all i, (_has_bits_[i] & masks[i]) == masks[i]"
 //  "for all i, (_has_bits_[i] & masks[i]) == masks[i]"
 // masks is allowed to be shorter than _has_bits_, but at least one element of
 // masks is allowed to be shorter than _has_bits_, but at least one element of
@@ -239,7 +241,8 @@ bool HasHasMethod(const FieldDescriptor* field) {
   }
   }
   // For message types without true field presence, only fields with a message
   // For message types without true field presence, only fields with a message
   // type have a has_$name$() method.
   // type have a has_$name$() method.
-  return field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE;
+  return field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE ||
+         field->has_optional_keyword();
 }
 }
 
 
 // Collects map entry message type information.
 // Collects map entry message type information.
@@ -329,10 +332,16 @@ bool TableDrivenParsingEnabled(const Descriptor* descriptor,
   // Consider table-driven parsing.  We only do this if:
   // Consider table-driven parsing.  We only do this if:
   // - We have has_bits for fields.  This avoids a check on every field we set
   // - We have has_bits for fields.  This avoids a check on every field we set
   //   when are present (the common case).
   //   when are present (the common case).
-  if (!HasFieldPresence(descriptor->file())) {
-    return false;
+  bool has_hasbit = false;
+  for (int i = 0; i < descriptor->field_count(); i++) {
+    if (HasHasbit(descriptor->field(i))) {
+      has_hasbit = true;
+      break;
+    }
   }
   }
 
 
+  if (!has_hasbit) return false;
+
   const double table_sparseness = 0.5;
   const double table_sparseness = 0.5;
   int max_field_number = 0;
   int max_field_number = 0;
   for (auto field : FieldRange(descriptor)) {
   for (auto field : FieldRange(descriptor)) {
@@ -488,7 +497,7 @@ void ColdChunkSkipper::OnStartChunk(int chunk, int cached_has_word_index,
                                     const std::string& from,
                                     const std::string& from,
                                     io::Printer* printer) {
                                     io::Printer* printer) {
   Formatter format(printer, variables_);
   Formatter format(printer, variables_);
-  if (!access_info_map_ || has_bit_indices_.empty()) {
+  if (!access_info_map_) {
     return;
     return;
   } else if (chunk < limit_chunk_) {
   } else if (chunk < limit_chunk_) {
     // We are already inside a run of cold chunks.
     // We are already inside a run of cold chunks.
@@ -595,17 +604,18 @@ MessageGenerator::MessageGenerator(
 
 
   message_layout_helper_->OptimizeLayout(&optimized_order_, options_);
   message_layout_helper_->OptimizeLayout(&optimized_order_, options_);
 
 
-  if (HasFieldPresence(descriptor_->file())) {
-    // We use -1 as a sentinel.
-    has_bit_indices_.resize(descriptor_->field_count(), -1);
-    for (auto field : optimized_order_) {
-      // Skip fields that do not have has bits.
-      if (field->is_repeated()) {
-        continue;
+  // This message has hasbits iff one or more fields need one.
+  for (auto field : optimized_order_) {
+    if (HasHasbit(field)) {
+      if (has_bit_indices_.empty()) {
+        has_bit_indices_.resize(descriptor_->field_count(), kNoHasbit);
       }
       }
-
       has_bit_indices_[field->index()] = max_has_bit_index_++;
       has_bit_indices_[field->index()] = max_has_bit_index_++;
     }
     }
+  }
+
+
+  if (!has_bit_indices_.empty()) {
     field_generators_.SetHasBitIndices(has_bit_indices_);
     field_generators_.SetHasBitIndices(has_bit_indices_);
   }
   }
 
 
@@ -635,17 +645,18 @@ size_t MessageGenerator::HasBitsSize() const {
 }
 }
 
 
 int MessageGenerator::HasBitIndex(const FieldDescriptor* field) const {
 int MessageGenerator::HasBitIndex(const FieldDescriptor* field) const {
-  return has_bit_indices_.empty() ? -1 : has_bit_indices_[field->index()];
+  return has_bit_indices_.empty() ? kNoHasbit
+                                  : has_bit_indices_[field->index()];
 }
 }
 
 
 int MessageGenerator::HasByteIndex(const FieldDescriptor* field) const {
 int MessageGenerator::HasByteIndex(const FieldDescriptor* field) const {
   int hasbit = HasBitIndex(field);
   int hasbit = HasBitIndex(field);
-  return hasbit == -1 ? -1 : hasbit / 8;
+  return hasbit == kNoHasbit ? kNoHasbit : hasbit / 8;
 }
 }
 
 
 int MessageGenerator::HasWordIndex(const FieldDescriptor* field) const {
 int MessageGenerator::HasWordIndex(const FieldDescriptor* field) const {
   int hasbit = HasBitIndex(field);
   int hasbit = HasBitIndex(field);
-  return hasbit == -1 ? -1 : hasbit / 32;
+  return hasbit == kNoHasbit ? kNoHasbit : hasbit / 32;
 }
 }
 
 
 void MessageGenerator::AddGenerators(
 void MessageGenerator::AddGenerators(
@@ -784,11 +795,9 @@ void MessageGenerator::GenerateSingularFieldHasBits(
         "}\n");
         "}\n");
     return;
     return;
   }
   }
-  if (HasFieldPresence(descriptor_->file())) {
-    // N.B.: without field presence, we do not use has-bits or generate
-    // has_$name$() methods.
-    int has_bit_index = has_bit_indices_[field->index()];
-    GOOGLE_CHECK_GE(has_bit_index, 0);
+  if (HasHasbit(field)) {
+    int has_bit_index = HasBitIndex(field);
+    GOOGLE_CHECK_NE(has_bit_index, kNoHasbit);
 
 
     format.Set("has_array_index", has_bit_index / 32);
     format.Set("has_array_index", has_bit_index / 32);
     format.Set("has_mask",
     format.Set("has_mask",
@@ -813,27 +822,25 @@ void MessageGenerator::GenerateSingularFieldHasBits(
         "$annotate_accessor$"
         "$annotate_accessor$"
         "  return _internal_has_$name$();\n"
         "  return _internal_has_$name$();\n"
         "}\n");
         "}\n");
-  } else {
+  } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
     // Message fields have a has_$name$() method.
     // Message fields have a has_$name$() method.
-    if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
-      if (IsLazy(field, options_)) {
-        format(
-            "inline bool $classname$::_internal_has_$name$() const {\n"
-            "  return !$name$_.IsCleared();\n"
-            "}\n");
-      } else {
-        format(
-            "inline bool $classname$::_internal_has_$name$() const {\n"
-            "  return this != internal_default_instance() "
-            "&& $name$_ != nullptr;\n"
-            "}\n");
-      }
+    if (IsLazy(field, options_)) {
+      format(
+          "inline bool $classname$::_internal_has_$name$() const {\n"
+          "  return !$name$_.IsCleared();\n"
+          "}\n");
+    } else {
       format(
       format(
-          "inline bool $classname$::has_$name$() const {\n"
-          "$annotate_accessor$"
-          "  return _internal_has_$name$();\n"
+          "inline bool $classname$::_internal_has_$name$() const {\n"
+          "  return this != internal_default_instance() "
+          "&& $name$_ != nullptr;\n"
           "}\n");
           "}\n");
     }
     }
+    format(
+        "inline bool $classname$::has_$name$() const {\n"
+        "$annotate_accessor$"
+        "  return _internal_has_$name$();\n"
+        "}\n");
   }
   }
 }
 }
 
 
@@ -926,16 +933,12 @@ void MessageGenerator::GenerateFieldClear(const FieldDescriptor* field,
     format("}\n");
     format("}\n");
   } else {
   } else {
     field_generators_.get(field).GenerateClearingCode(format.printer());
     field_generators_.get(field).GenerateClearingCode(format.printer());
-    if (HasFieldPresence(descriptor_->file())) {
-      if (!field->is_repeated() && !field->options().weak()) {
-        int has_bit_index = has_bit_indices_[field->index()];
-        GOOGLE_CHECK_GE(has_bit_index, 0);
-
-        format.Set("has_array_index", has_bit_index / 32);
-        format.Set("has_mask",
-                   strings::Hex(1u << (has_bit_index % 32), strings::ZERO_PAD_8));
-        format("_has_bits_[$has_array_index$] &= ~0x$has_mask$u;\n");
-      }
+    if (HasHasbit(field)) {
+      int has_bit_index = HasBitIndex(field);
+      format.Set("has_array_index", has_bit_index / 32);
+      format.Set("has_mask",
+                 strings::Hex(1u << (has_bit_index % 32), strings::ZERO_PAD_8));
+      format("_has_bits_[$has_array_index$] &= ~0x$has_mask$u;\n");
     }
     }
   }
   }
 
 
@@ -1540,7 +1543,7 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) {
         "typedef void DestructorSkippable_;\n");
         "typedef void DestructorSkippable_;\n");
   }
   }
 
 
-  if (HasFieldPresence(descriptor_->file())) {
+  if (!has_bit_indices_.empty()) {
     // _has_bits_ is frequently accessed, so to reduce code size and improve
     // _has_bits_ is frequently accessed, so to reduce code size and improve
     // speed, it should be close to the start of the object. Placing
     // speed, it should be close to the start of the object. Placing
     // _cached_size_ together with _has_bits_ improves cache locality despite
     // _cached_size_ together with _has_bits_ improves cache locality despite
@@ -1686,8 +1689,8 @@ bool MessageGenerator::GenerateParseTable(io::Printer* printer, size_t offset,
       "$3$,\n",
       "$3$,\n",
       offset, aux_offset, max_field_number);
       offset, aux_offset, max_field_number);
 
 
-  if (!HasFieldPresence(descriptor_->file())) {
-    // If we don't have field presence, then _has_bits_ does not exist.
+  if (has_bit_indices_.empty()) {
+    // If no fields have hasbits, then _has_bits_ does not exist.
     format("-1,\n");
     format("-1,\n");
   } else {
   } else {
     format("PROTOBUF_FIELD_OFFSET($classtype$, _has_bits_),\n");
     format("PROTOBUF_FIELD_OFFSET($classtype$, _has_bits_),\n");
@@ -1725,10 +1728,9 @@ bool MessageGenerator::GenerateParseTable(io::Printer* printer, size_t offset,
 void MessageGenerator::GenerateSchema(io::Printer* printer, int offset,
 void MessageGenerator::GenerateSchema(io::Printer* printer, int offset,
                                       int has_offset) {
                                       int has_offset) {
   Formatter format(printer, variables_);
   Formatter format(printer, variables_);
-  has_offset =
-      HasFieldPresence(descriptor_->file()) || IsMapEntryMessage(descriptor_)
-          ? offset + has_offset
-          : -1;
+  has_offset = !has_bit_indices_.empty() || IsMapEntryMessage(descriptor_)
+                   ? offset + has_offset
+                   : -1;
 
 
   format("{ $1$, $2$, sizeof($classtype$)},\n", offset, has_offset);
   format("{ $1$, $2$, sizeof($classtype$)},\n", offset, has_offset);
 }
 }
@@ -1763,13 +1765,12 @@ uint32 CalcFieldNum(const FieldGenerator& generator,
   } else if (field->is_repeated()) {
   } else if (field->is_repeated()) {
     return internal::FieldMetadata::CalculateType(
     return internal::FieldMetadata::CalculateType(
         type, internal::FieldMetadata::kRepeated);
         type, internal::FieldMetadata::kRepeated);
-  } else if (!HasFieldPresence(field->file()) &&
-             field->containing_oneof() == NULL && !is_a_map) {
+  } else if (HasHasbit(field) || field->containing_oneof() || is_a_map) {
     return internal::FieldMetadata::CalculateType(
     return internal::FieldMetadata::CalculateType(
-        type, internal::FieldMetadata::kNoPresence);
+        type, internal::FieldMetadata::kPresence);
   } else {
   } else {
     return internal::FieldMetadata::CalculateType(
     return internal::FieldMetadata::CalculateType(
-        type, internal::FieldMetadata::kPresence);
+        type, internal::FieldMetadata::kNoPresence);
   }
   }
 }
 }
 
 
@@ -1897,8 +1898,7 @@ int MessageGenerator::GenerateFieldMetadata(io::Printer* printer) {
             "::internal::LazyFieldSerializer";
             "::internal::LazyFieldSerializer";
       if (field->containing_oneof()) {
       if (field->containing_oneof()) {
         ptr += "OneOf";
         ptr += "OneOf";
-      } else if (!HasFieldPresence(descriptor_->file()) ||
-                 has_bit_indices_[field->index()] == -1) {
+      } else if (!HasHasbit(field)) {
         ptr += "NoPresence";
         ptr += "NoPresence";
       }
       }
       ptr += ")";
       ptr += ")";
@@ -1921,8 +1921,7 @@ int MessageGenerator::GenerateFieldMetadata(io::Printer* printer) {
           " PROTOBUF_FIELD_OFFSET($classtype$, _oneof_case_) + "
           " PROTOBUF_FIELD_OFFSET($classtype$, _oneof_case_) + "
           "$oneofoffset$, $2$, $3$},\n",
           "$oneofoffset$, $2$, $3$},\n",
           tag, type, ptr);
           tag, type, ptr);
-    } else if (HasFieldPresence(descriptor_->file()) &&
-               has_bit_indices_[field->index()] != -1) {
+    } else if (HasHasbit(field)) {
       format.Set("hasbitsoffset", has_bit_indices_[field->index()]);
       format.Set("hasbitsoffset", has_bit_indices_[field->index()]);
       format(
       format(
           "{PROTOBUF_FIELD_OFFSET($classtype$, $field_name$_), "
           "{PROTOBUF_FIELD_OFFSET($classtype$, $field_name$_), "
@@ -2073,7 +2072,7 @@ void MessageGenerator::GenerateClassMethods(io::Printer* printer) {
       "class $classname$::_Internal {\n"
       "class $classname$::_Internal {\n"
       " public:\n");
       " public:\n");
   format.Indent();
   format.Indent();
-  if (HasFieldPresence(descriptor_->file()) && HasBitsSize() != 0) {
+  if (!has_bit_indices_.empty()) {
     format(
     format(
         "using HasBits = decltype(std::declval<$classname$>()._has_bits_);\n");
         "using HasBits = decltype(std::declval<$classname$>()._has_bits_);\n");
   }
   }
@@ -2082,10 +2081,8 @@ void MessageGenerator::GenerateClassMethods(io::Printer* printer) {
     if (!IsFieldUsed(field, options_)) {
     if (!IsFieldUsed(field, options_)) {
       continue;
       continue;
     }
     }
-    if (HasFieldPresence(descriptor_->file()) && !field->is_repeated() &&
-        !field->options().weak() && !field->containing_oneof()) {
-      int has_bit_index = has_bit_indices_[field->index()];
-      GOOGLE_CHECK_GE(has_bit_index, 0);
+    if (HasHasbit(field)) {
+      int has_bit_index = HasBitIndex(field);
       format(
       format(
           "static void set_has_$1$(HasBits* has_bits) {\n"
           "static void set_has_$1$(HasBits* has_bits) {\n"
           "  (*has_bits)[$2$] |= $3$u;\n"
           "  (*has_bits)[$2$] |= $3$u;\n"
@@ -2093,7 +2090,7 @@ void MessageGenerator::GenerateClassMethods(io::Printer* printer) {
           FieldName(field), has_bit_index / 32, (1u << (has_bit_index % 32)));
           FieldName(field), has_bit_index / 32, (1u << (has_bit_index % 32)));
     }
     }
   }
   }
-  if (num_required_fields_ > 0 && HasFieldPresence(descriptor_->file())) {
+  if (num_required_fields_ > 0) {
     const std::vector<uint32> masks_for_has_bits = RequiredFieldsBitMask();
     const std::vector<uint32> masks_for_has_bits = RequiredFieldsBitMask();
     format(
     format(
         "static bool MissingRequiredFields(const HasBits& has_bits) "
         "static bool MissingRequiredFields(const HasBits& has_bits) "
@@ -2392,7 +2389,7 @@ std::pair<size_t, size_t> MessageGenerator::GenerateOffsets(
     io::Printer* printer) {
     io::Printer* printer) {
   Formatter format(printer, variables_);
   Formatter format(printer, variables_);
 
 
-  if (HasFieldPresence(descriptor_->file()) || IsMapEntryMessage(descriptor_)) {
+  if (!has_bit_indices_.empty() || IsMapEntryMessage(descriptor_)) {
     format("PROTOBUF_FIELD_OFFSET($classtype$, _has_bits_),\n");
     format("PROTOBUF_FIELD_OFFSET($classtype$, _has_bits_),\n");
   } else {
   } else {
     format("~0u,  // no _has_bits_\n");
     format("~0u,  // no _has_bits_\n");
@@ -2451,7 +2448,7 @@ std::pair<size_t, size_t> MessageGenerator::GenerateOffsets(
     format(
     format(
         "0,\n"
         "0,\n"
         "1,\n");
         "1,\n");
-  } else if (HasFieldPresence(descriptor_->file())) {
+  } else if (!has_bit_indices_.empty()) {
     entries += has_bit_indices_.size() - num_stripped;
     entries += has_bit_indices_.size() - num_stripped;
     for (int i = 0; i < has_bit_indices_.size(); i++) {
     for (int i = 0; i < has_bit_indices_.size(); i++) {
       if (!IsFieldUsed(descriptor_->field(i), options_)) {
       if (!IsFieldUsed(descriptor_->field(i), options_)) {
@@ -2723,10 +2720,8 @@ void MessageGenerator::GenerateStructors(io::Printer* printer) {
     format.Indent();
     format.Indent();
     format.Indent();
     format.Indent();
 
 
-    if (HasFieldPresence(descriptor_->file())) {
-      if (!IsProto2MessageSet(descriptor_, options_)) {
-        format(",\n_has_bits_(from._has_bits_)");
-      }
+    if (!has_bit_indices_.empty()) {
+      format(",\n_has_bits_(from._has_bits_)");
     }
     }
 
 
     std::vector<bool> processed(optimized_order_.size(), false);
     std::vector<bool> processed(optimized_order_.size(), false);
@@ -2916,7 +2911,7 @@ void MessageGenerator::GenerateClear(io::Printer* printer) {
     // We can omit the if() for chunk size 1, or if our fields do not have
     // We can omit the if() for chunk size 1, or if our fields do not have
     // hasbits. I don't understand the rationale for the last part of the
     // hasbits. I don't understand the rationale for the last part of the
     // condition, but it matches the old logic.
     // condition, but it matches the old logic.
-    const bool have_outer_if = HasBitIndex(chunk.front()) != -1 &&
+    const bool have_outer_if = HasBitIndex(chunk.front()) != kNoHasbit &&
                                chunk.size() > 1 &&
                                chunk.size() > 1 &&
                                (memset_end != chunk.back() || merge_zero_init);
                                (memset_end != chunk.back() || merge_zero_init);
 
 
@@ -2962,7 +2957,7 @@ void MessageGenerator::GenerateClear(io::Printer* printer) {
       //
       //
       // TODO(kenton):  Let the CppFieldGenerator decide this somehow.
       // TODO(kenton):  Let the CppFieldGenerator decide this somehow.
       bool have_enclosing_if =
       bool have_enclosing_if =
-          HasBitIndex(field) != -1 &&
+          HasBitIndex(field) != kNoHasbit &&
           (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE ||
           (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE ||
            field->cpp_type() == FieldDescriptor::CPPTYPE_STRING);
            field->cpp_type() == FieldDescriptor::CPPTYPE_STRING);
 
 
@@ -2999,7 +2994,7 @@ void MessageGenerator::GenerateClear(io::Printer* printer) {
     format("_weak_field_map_.ClearAll();\n");
     format("_weak_field_map_.ClearAll();\n");
   }
   }
 
 
-  if (HasFieldPresence(descriptor_->file())) {
+  if (!has_bit_indices_.empty()) {
     // Step 5: Everything else.
     // Step 5: Everything else.
     format("_has_bits_.Clear();\n");
     format("_has_bits_.Clear();\n");
   }
   }
@@ -3075,7 +3070,7 @@ void MessageGenerator::GenerateSwap(io::Printer* printer) {
         "_internal_metadata_.Swap<$unknown_fields_type$>(&other->_internal_"
         "_internal_metadata_.Swap<$unknown_fields_type$>(&other->_internal_"
         "metadata_);\n");
         "metadata_);\n");
 
 
-    if (HasFieldPresence(descriptor_->file())) {
+    if (!has_bit_indices_.empty()) {
       for (int i = 0; i < HasBitsSize() / 4; ++i) {
       for (int i = 0; i < HasBitsSize() / 4; ++i) {
         format("swap(_has_bits_[$1$], other->_has_bits_[$1$]);\n", i);
         format("swap(_has_bits_[$1$], other->_has_bits_[$1$]);\n", i);
       }
       }
@@ -3218,7 +3213,8 @@ void MessageGenerator::GenerateClassSpecificMergeFrom(io::Printer* printer) {
 
 
   for (int chunk_index = 0; chunk_index < chunks.size(); chunk_index++) {
   for (int chunk_index = 0; chunk_index < chunks.size(); chunk_index++) {
     const std::vector<const FieldDescriptor*>& chunk = chunks[chunk_index];
     const std::vector<const FieldDescriptor*>& chunk = chunks[chunk_index];
-    bool have_outer_if = chunk.size() > 1 && HasByteIndex(chunk.front()) != -1;
+    bool have_outer_if =
+        chunk.size() > 1 && HasByteIndex(chunk.front()) != kNoHasbit;
     cold_skipper.OnStartChunk(chunk_index, cached_has_word_index, "from.",
     cold_skipper.OnStartChunk(chunk_index, cached_has_word_index, "from.",
                               printer);
                               printer);
 
 
@@ -3466,9 +3462,9 @@ void MessageGenerator::GenerateSerializeOneField(io::Printer* printer,
 
 
   bool have_enclosing_if = false;
   bool have_enclosing_if = false;
   if (field->options().weak()) {
   if (field->options().weak()) {
-  } else if (!field->is_repeated() && HasFieldPresence(descriptor_->file())) {
+  } else if (HasHasbit(field)) {
     // Attempt to use the state of cached_has_bits, if possible.
     // Attempt to use the state of cached_has_bits, if possible.
-    int has_bit_index = has_bit_indices_[field->index()];
+    int has_bit_index = HasBitIndex(field);
     if (cached_has_bits_index == has_bit_index / 32) {
     if (cached_has_bits_index == has_bit_index / 32) {
       const std::string mask =
       const std::string mask =
           StrCat(strings::Hex(1u << (has_bit_index % 32), strings::ZERO_PAD_8));
           StrCat(strings::Hex(1u << (has_bit_index % 32), strings::ZERO_PAD_8));
@@ -3480,7 +3476,7 @@ void MessageGenerator::GenerateSerializeOneField(io::Printer* printer,
 
 
     format.Indent();
     format.Indent();
     have_enclosing_if = true;
     have_enclosing_if = true;
-  } else if (!HasFieldPresence(descriptor_->file())) {
+  } else if (field->is_optional() && !HasHasbit(field)) {
     have_enclosing_if = EmitFieldNonDefaultCondition(printer, "this->", field);
     have_enclosing_if = EmitFieldNonDefaultCondition(printer, "this->", field);
   }
   }
 
 
@@ -3561,7 +3557,7 @@ void MessageGenerator::GenerateSerializeWithCachedSizesBody(
         : mg_(mg),
         : mg_(mg),
           format_(printer),
           format_(printer),
           eager_(!HasFieldPresence(mg->descriptor_->file())),
           eager_(!HasFieldPresence(mg->descriptor_->file())),
-          cached_has_bit_index_(-1) {}
+          cached_has_bit_index_(kNoHasbit) {}
 
 
     ~LazySerializerEmitter() { Flush(); }
     ~LazySerializerEmitter() { Flush(); }
 
 
@@ -3841,7 +3837,8 @@ void MessageGenerator::GenerateByteSize(io::Printer* printer) {
 
 
   for (int chunk_index = 0; chunk_index < chunks.size(); chunk_index++) {
   for (int chunk_index = 0; chunk_index < chunks.size(); chunk_index++) {
     const std::vector<const FieldDescriptor*>& chunk = chunks[chunk_index];
     const std::vector<const FieldDescriptor*>& chunk = chunks[chunk_index];
-    const bool have_outer_if = chunk.size() > 1 && HasWordIndex(chunk[0]) != -1;
+    const bool have_outer_if =
+        chunk.size() > 1 && HasWordIndex(chunk[0]) != kNoHasbit;
     cold_skipper.OnStartChunk(chunk_index, cached_has_word_index, "", printer);
     cold_skipper.OnStartChunk(chunk_index, cached_has_word_index, "", printer);
 
 
     if (have_outer_if) {
     if (have_outer_if) {
@@ -3983,7 +3980,7 @@ void MessageGenerator::GenerateIsInitialized(io::Printer* printer) {
         "}\n\n");
         "}\n\n");
   }
   }
 
 
-  if (num_required_fields_ > 0 && HasFieldPresence(descriptor_->file())) {
+  if (num_required_fields_ > 0) {
     format(
     format(
         "if (_Internal::MissingRequiredFields(_has_bits_))"
         "if (_Internal::MissingRequiredFields(_has_bits_))"
         " return false;\n");
         " return false;\n");

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

@@ -58,7 +58,7 @@ class PROTOC_EXPORT JavaGenerator : public CodeGenerator {
 
 
   // implements CodeGenerator ----------------------------------------
   // implements CodeGenerator ----------------------------------------
   bool Generate(const FileDescriptor* file, const std::string& parameter,
   bool Generate(const FileDescriptor* file, const std::string& parameter,
-                GeneratorContext* context, std::string* error) const;
+                GeneratorContext* context, std::string* error) const override;
 
 
   uint64 GetSupportedFeatures() const override;
   uint64 GetSupportedFeatures() const override;
 
 

+ 0 - 30
src/google/protobuf/compiler/zip_writer.cc

@@ -28,36 +28,6 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// https://developers.google.com/protocol-buffers/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
 // Author: ambrose@google.com (Ambrose Feinstein),
 // Author: ambrose@google.com (Ambrose Feinstein),
 //         kenton@google.com (Kenton Varda)
 //         kenton@google.com (Kenton Varda)
 //
 //

+ 0 - 30
src/google/protobuf/compiler/zip_writer.h

@@ -28,36 +28,6 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// https://developers.google.com/protocol-buffers/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
 // Author: kenton@google.com (Kenton Varda)
 // Author: kenton@google.com (Kenton Varda)
 
 
 #include <vector>
 #include <vector>

+ 32 - 57
src/google/protobuf/descriptor.pb.cc

@@ -567,13 +567,12 @@ static const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* file_level_enum_descriptor
 static constexpr ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2fdescriptor_2eproto = nullptr;
 static constexpr ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2fdescriptor_2eproto = nullptr;
 
 
 const ::PROTOBUF_NAMESPACE_ID::uint32 TableStruct_google_2fprotobuf_2fdescriptor_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
 const ::PROTOBUF_NAMESPACE_ID::uint32 TableStruct_google_2fprotobuf_2fdescriptor_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
-  PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FileDescriptorSet, _has_bits_),
+  ~0u,  // no _has_bits_
   PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FileDescriptorSet, _internal_metadata_),
   PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FileDescriptorSet, _internal_metadata_),
   ~0u,  // no _extensions_
   ~0u,  // no _extensions_
   ~0u,  // no _oneof_case_
   ~0u,  // no _oneof_case_
   ~0u,  // no _weak_field_map_
   ~0u,  // no _weak_field_map_
   PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FileDescriptorSet, file_),
   PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FileDescriptorSet, file_),
-  ~0u,
   PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FileDescriptorProto, _has_bits_),
   PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FileDescriptorProto, _has_bits_),
   PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FileDescriptorProto, _internal_metadata_),
   PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FileDescriptorProto, _internal_metadata_),
   ~0u,  // no _extensions_
   ~0u,  // no _extensions_
@@ -648,13 +647,12 @@ const ::PROTOBUF_NAMESPACE_ID::uint32 TableStruct_google_2fprotobuf_2fdescriptor
   1,
   1,
   ~0u,
   ~0u,
   ~0u,
   ~0u,
-  PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions, _has_bits_),
+  ~0u,  // no _has_bits_
   PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions, _internal_metadata_),
   PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions, _internal_metadata_),
   PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions, _extensions_),
   PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions, _extensions_),
   ~0u,  // no _oneof_case_
   ~0u,  // no _oneof_case_
   ~0u,  // no _weak_field_map_
   ~0u,  // no _weak_field_map_
   PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions, uninterpreted_option_),
   PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions, uninterpreted_option_),
-  ~0u,
   PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FieldDescriptorProto, _has_bits_),
   PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FieldDescriptorProto, _has_bits_),
   PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FieldDescriptorProto, _internal_metadata_),
   PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FieldDescriptorProto, _internal_metadata_),
   ~0u,  // no _extensions_
   ~0u,  // no _extensions_
@@ -835,13 +833,12 @@ const ::PROTOBUF_NAMESPACE_ID::uint32 TableStruct_google_2fprotobuf_2fdescriptor
   3,
   3,
   4,
   4,
   ~0u,
   ~0u,
-  PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::OneofOptions, _has_bits_),
+  ~0u,  // no _has_bits_
   PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::OneofOptions, _internal_metadata_),
   PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::OneofOptions, _internal_metadata_),
   PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::OneofOptions, _extensions_),
   PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::OneofOptions, _extensions_),
   ~0u,  // no _oneof_case_
   ~0u,  // no _oneof_case_
   ~0u,  // no _weak_field_map_
   ~0u,  // no _weak_field_map_
   PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::OneofOptions, uninterpreted_option_),
   PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::OneofOptions, uninterpreted_option_),
-  ~0u,
   PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::EnumOptions, _has_bits_),
   PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::EnumOptions, _has_bits_),
   PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::EnumOptions, _internal_metadata_),
   PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::EnumOptions, _internal_metadata_),
   PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::EnumOptions, _extensions_),
   PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::EnumOptions, _extensions_),
@@ -925,13 +922,12 @@ const ::PROTOBUF_NAMESPACE_ID::uint32 TableStruct_google_2fprotobuf_2fdescriptor
   0,
   0,
   1,
   1,
   ~0u,
   ~0u,
-  PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::SourceCodeInfo, _has_bits_),
+  ~0u,  // no _has_bits_
   PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::SourceCodeInfo, _internal_metadata_),
   PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::SourceCodeInfo, _internal_metadata_),
   ~0u,  // no _extensions_
   ~0u,  // no _extensions_
   ~0u,  // no _oneof_case_
   ~0u,  // no _oneof_case_
   ~0u,  // no _weak_field_map_
   ~0u,  // no _weak_field_map_
   PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::SourceCodeInfo, location_),
   PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::SourceCodeInfo, location_),
-  ~0u,
   PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation, _has_bits_),
   PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation, _has_bits_),
   PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation, _internal_metadata_),
   PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation, _internal_metadata_),
   ~0u,  // no _extensions_
   ~0u,  // no _extensions_
@@ -945,42 +941,41 @@ const ::PROTOBUF_NAMESPACE_ID::uint32 TableStruct_google_2fprotobuf_2fdescriptor
   0,
   0,
   1,
   1,
   2,
   2,
-  PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo, _has_bits_),
+  ~0u,  // no _has_bits_
   PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo, _internal_metadata_),
   PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo, _internal_metadata_),
   ~0u,  // no _extensions_
   ~0u,  // no _extensions_
   ~0u,  // no _oneof_case_
   ~0u,  // no _oneof_case_
   ~0u,  // no _weak_field_map_
   ~0u,  // no _weak_field_map_
   PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo, annotation_),
   PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo, annotation_),
-  ~0u,
 };
 };
 static const ::PROTOBUF_NAMESPACE_ID::internal::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
 static const ::PROTOBUF_NAMESPACE_ID::internal::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
-  { 0, 6, sizeof(PROTOBUF_NAMESPACE_ID::FileDescriptorSet)},
-  { 7, 24, sizeof(PROTOBUF_NAMESPACE_ID::FileDescriptorProto)},
-  { 36, 44, sizeof(PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange)},
-  { 47, 54, sizeof(PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange)},
-  { 56, 71, sizeof(PROTOBUF_NAMESPACE_ID::DescriptorProto)},
-  { 81, 87, sizeof(PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions)},
-  { 88, 104, sizeof(PROTOBUF_NAMESPACE_ID::FieldDescriptorProto)},
-  { 115, 122, sizeof(PROTOBUF_NAMESPACE_ID::OneofDescriptorProto)},
-  { 124, 131, sizeof(PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange)},
-  { 133, 143, sizeof(PROTOBUF_NAMESPACE_ID::EnumDescriptorProto)},
-  { 148, 156, sizeof(PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto)},
-  { 159, 167, sizeof(PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto)},
-  { 170, 181, sizeof(PROTOBUF_NAMESPACE_ID::MethodDescriptorProto)},
-  { 187, 213, sizeof(PROTOBUF_NAMESPACE_ID::FileOptions)},
-  { 234, 244, sizeof(PROTOBUF_NAMESPACE_ID::MessageOptions)},
-  { 249, 261, sizeof(PROTOBUF_NAMESPACE_ID::FieldOptions)},
-  { 268, 274, sizeof(PROTOBUF_NAMESPACE_ID::OneofOptions)},
-  { 275, 283, sizeof(PROTOBUF_NAMESPACE_ID::EnumOptions)},
-  { 286, 293, sizeof(PROTOBUF_NAMESPACE_ID::EnumValueOptions)},
-  { 295, 302, sizeof(PROTOBUF_NAMESPACE_ID::ServiceOptions)},
-  { 304, 312, sizeof(PROTOBUF_NAMESPACE_ID::MethodOptions)},
-  { 315, 322, sizeof(PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart)},
-  { 324, 336, sizeof(PROTOBUF_NAMESPACE_ID::UninterpretedOption)},
-  { 343, 353, sizeof(PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location)},
-  { 358, 364, sizeof(PROTOBUF_NAMESPACE_ID::SourceCodeInfo)},
-  { 365, 374, sizeof(PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation)},
-  { 378, 384, sizeof(PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo)},
+  { 0, -1, sizeof(PROTOBUF_NAMESPACE_ID::FileDescriptorSet)},
+  { 6, 23, sizeof(PROTOBUF_NAMESPACE_ID::FileDescriptorProto)},
+  { 35, 43, sizeof(PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange)},
+  { 46, 53, sizeof(PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange)},
+  { 55, 70, sizeof(PROTOBUF_NAMESPACE_ID::DescriptorProto)},
+  { 80, -1, sizeof(PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions)},
+  { 86, 102, sizeof(PROTOBUF_NAMESPACE_ID::FieldDescriptorProto)},
+  { 113, 120, sizeof(PROTOBUF_NAMESPACE_ID::OneofDescriptorProto)},
+  { 122, 129, sizeof(PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange)},
+  { 131, 141, sizeof(PROTOBUF_NAMESPACE_ID::EnumDescriptorProto)},
+  { 146, 154, sizeof(PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto)},
+  { 157, 165, sizeof(PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto)},
+  { 168, 179, sizeof(PROTOBUF_NAMESPACE_ID::MethodDescriptorProto)},
+  { 185, 211, sizeof(PROTOBUF_NAMESPACE_ID::FileOptions)},
+  { 232, 242, sizeof(PROTOBUF_NAMESPACE_ID::MessageOptions)},
+  { 247, 259, sizeof(PROTOBUF_NAMESPACE_ID::FieldOptions)},
+  { 266, -1, sizeof(PROTOBUF_NAMESPACE_ID::OneofOptions)},
+  { 272, 280, sizeof(PROTOBUF_NAMESPACE_ID::EnumOptions)},
+  { 283, 290, sizeof(PROTOBUF_NAMESPACE_ID::EnumValueOptions)},
+  { 292, 299, sizeof(PROTOBUF_NAMESPACE_ID::ServiceOptions)},
+  { 301, 309, sizeof(PROTOBUF_NAMESPACE_ID::MethodOptions)},
+  { 312, 319, sizeof(PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart)},
+  { 321, 333, sizeof(PROTOBUF_NAMESPACE_ID::UninterpretedOption)},
+  { 340, 350, sizeof(PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location)},
+  { 355, -1, sizeof(PROTOBUF_NAMESPACE_ID::SourceCodeInfo)},
+  { 361, 370, sizeof(PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation)},
+  { 374, -1, sizeof(PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo)},
 };
 };
 
 
 static ::PROTOBUF_NAMESPACE_ID::Message const * const file_default_instances[] = {
 static ::PROTOBUF_NAMESPACE_ID::Message const * const file_default_instances[] = {
@@ -1384,7 +1379,6 @@ void FileDescriptorSet::InitAsDefaultInstance() {
 }
 }
 class FileDescriptorSet::_Internal {
 class FileDescriptorSet::_Internal {
  public:
  public:
-  using HasBits = decltype(std::declval<FileDescriptorSet>()._has_bits_);
 };
 };
 
 
 FileDescriptorSet::FileDescriptorSet(::PROTOBUF_NAMESPACE_ID::Arena* arena)
 FileDescriptorSet::FileDescriptorSet(::PROTOBUF_NAMESPACE_ID::Arena* arena)
@@ -1396,7 +1390,6 @@ FileDescriptorSet::FileDescriptorSet(::PROTOBUF_NAMESPACE_ID::Arena* arena)
 }
 }
 FileDescriptorSet::FileDescriptorSet(const FileDescriptorSet& from)
 FileDescriptorSet::FileDescriptorSet(const FileDescriptorSet& from)
   : ::PROTOBUF_NAMESPACE_ID::Message(),
   : ::PROTOBUF_NAMESPACE_ID::Message(),
-      _has_bits_(from._has_bits_),
       file_(from.file_) {
       file_(from.file_) {
   _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   // @@protoc_insertion_point(copy_constructor:google.protobuf.FileDescriptorSet)
   // @@protoc_insertion_point(copy_constructor:google.protobuf.FileDescriptorSet)
@@ -1438,7 +1431,6 @@ void FileDescriptorSet::Clear() {
   (void) cached_has_bits;
   (void) cached_has_bits;
 
 
   file_.Clear();
   file_.Clear();
-  _has_bits_.Clear();
   _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
   _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 }
 
 
@@ -1577,7 +1569,6 @@ bool FileDescriptorSet::IsInitialized() const {
 void FileDescriptorSet::InternalSwap(FileDescriptorSet* other) {
 void FileDescriptorSet::InternalSwap(FileDescriptorSet* other) {
   using std::swap;
   using std::swap;
   _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
   _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
-  swap(_has_bits_[0], other->_has_bits_[0]);
   file_.InternalSwap(&other->file_);
   file_.InternalSwap(&other->file_);
 }
 }
 
 
@@ -3369,7 +3360,6 @@ void ExtensionRangeOptions::InitAsDefaultInstance() {
 }
 }
 class ExtensionRangeOptions::_Internal {
 class ExtensionRangeOptions::_Internal {
  public:
  public:
-  using HasBits = decltype(std::declval<ExtensionRangeOptions>()._has_bits_);
 };
 };
 
 
 ExtensionRangeOptions::ExtensionRangeOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena)
 ExtensionRangeOptions::ExtensionRangeOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena)
@@ -3382,7 +3372,6 @@ ExtensionRangeOptions::ExtensionRangeOptions(::PROTOBUF_NAMESPACE_ID::Arena* are
 }
 }
 ExtensionRangeOptions::ExtensionRangeOptions(const ExtensionRangeOptions& from)
 ExtensionRangeOptions::ExtensionRangeOptions(const ExtensionRangeOptions& from)
   : ::PROTOBUF_NAMESPACE_ID::Message(),
   : ::PROTOBUF_NAMESPACE_ID::Message(),
-      _has_bits_(from._has_bits_),
       uninterpreted_option_(from.uninterpreted_option_) {
       uninterpreted_option_(from.uninterpreted_option_) {
   _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   _extensions_.MergeFrom(from._extensions_);
   _extensions_.MergeFrom(from._extensions_);
@@ -3426,7 +3415,6 @@ void ExtensionRangeOptions::Clear() {
 
 
   _extensions_.Clear();
   _extensions_.Clear();
   uninterpreted_option_.Clear();
   uninterpreted_option_.Clear();
-  _has_bits_.Clear();
   _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
   _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 }
 
 
@@ -3583,7 +3571,6 @@ void ExtensionRangeOptions::InternalSwap(ExtensionRangeOptions* other) {
   using std::swap;
   using std::swap;
   _extensions_.Swap(&other->_extensions_);
   _extensions_.Swap(&other->_extensions_);
   _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
   _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
-  swap(_has_bits_[0], other->_has_bits_[0]);
   uninterpreted_option_.InternalSwap(&other->uninterpreted_option_);
   uninterpreted_option_.InternalSwap(&other->uninterpreted_option_);
 }
 }
 
 
@@ -7985,7 +7972,6 @@ void OneofOptions::InitAsDefaultInstance() {
 }
 }
 class OneofOptions::_Internal {
 class OneofOptions::_Internal {
  public:
  public:
-  using HasBits = decltype(std::declval<OneofOptions>()._has_bits_);
 };
 };
 
 
 OneofOptions::OneofOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena)
 OneofOptions::OneofOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena)
@@ -7998,7 +7984,6 @@ OneofOptions::OneofOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena)
 }
 }
 OneofOptions::OneofOptions(const OneofOptions& from)
 OneofOptions::OneofOptions(const OneofOptions& from)
   : ::PROTOBUF_NAMESPACE_ID::Message(),
   : ::PROTOBUF_NAMESPACE_ID::Message(),
-      _has_bits_(from._has_bits_),
       uninterpreted_option_(from.uninterpreted_option_) {
       uninterpreted_option_(from.uninterpreted_option_) {
   _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   _extensions_.MergeFrom(from._extensions_);
   _extensions_.MergeFrom(from._extensions_);
@@ -8042,7 +8027,6 @@ void OneofOptions::Clear() {
 
 
   _extensions_.Clear();
   _extensions_.Clear();
   uninterpreted_option_.Clear();
   uninterpreted_option_.Clear();
-  _has_bits_.Clear();
   _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
   _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 }
 
 
@@ -8199,7 +8183,6 @@ void OneofOptions::InternalSwap(OneofOptions* other) {
   using std::swap;
   using std::swap;
   _extensions_.Swap(&other->_extensions_);
   _extensions_.Swap(&other->_extensions_);
   _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
   _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
-  swap(_has_bits_[0], other->_has_bits_[0]);
   uninterpreted_option_.InternalSwap(&other->uninterpreted_option_);
   uninterpreted_option_.InternalSwap(&other->uninterpreted_option_);
 }
 }
 
 
@@ -10473,7 +10456,6 @@ void SourceCodeInfo::InitAsDefaultInstance() {
 }
 }
 class SourceCodeInfo::_Internal {
 class SourceCodeInfo::_Internal {
  public:
  public:
-  using HasBits = decltype(std::declval<SourceCodeInfo>()._has_bits_);
 };
 };
 
 
 SourceCodeInfo::SourceCodeInfo(::PROTOBUF_NAMESPACE_ID::Arena* arena)
 SourceCodeInfo::SourceCodeInfo(::PROTOBUF_NAMESPACE_ID::Arena* arena)
@@ -10485,7 +10467,6 @@ SourceCodeInfo::SourceCodeInfo(::PROTOBUF_NAMESPACE_ID::Arena* arena)
 }
 }
 SourceCodeInfo::SourceCodeInfo(const SourceCodeInfo& from)
 SourceCodeInfo::SourceCodeInfo(const SourceCodeInfo& from)
   : ::PROTOBUF_NAMESPACE_ID::Message(),
   : ::PROTOBUF_NAMESPACE_ID::Message(),
-      _has_bits_(from._has_bits_),
       location_(from.location_) {
       location_(from.location_) {
   _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   // @@protoc_insertion_point(copy_constructor:google.protobuf.SourceCodeInfo)
   // @@protoc_insertion_point(copy_constructor:google.protobuf.SourceCodeInfo)
@@ -10527,7 +10508,6 @@ void SourceCodeInfo::Clear() {
   (void) cached_has_bits;
   (void) cached_has_bits;
 
 
   location_.Clear();
   location_.Clear();
-  _has_bits_.Clear();
   _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
   _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 }
 
 
@@ -10665,7 +10645,6 @@ bool SourceCodeInfo::IsInitialized() const {
 void SourceCodeInfo::InternalSwap(SourceCodeInfo* other) {
 void SourceCodeInfo::InternalSwap(SourceCodeInfo* other) {
   using std::swap;
   using std::swap;
   _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
   _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
-  swap(_has_bits_[0], other->_has_bits_[0]);
   location_.InternalSwap(&other->location_);
   location_.InternalSwap(&other->location_);
 }
 }
 
 
@@ -11021,7 +11000,6 @@ void GeneratedCodeInfo::InitAsDefaultInstance() {
 }
 }
 class GeneratedCodeInfo::_Internal {
 class GeneratedCodeInfo::_Internal {
  public:
  public:
-  using HasBits = decltype(std::declval<GeneratedCodeInfo>()._has_bits_);
 };
 };
 
 
 GeneratedCodeInfo::GeneratedCodeInfo(::PROTOBUF_NAMESPACE_ID::Arena* arena)
 GeneratedCodeInfo::GeneratedCodeInfo(::PROTOBUF_NAMESPACE_ID::Arena* arena)
@@ -11033,7 +11011,6 @@ GeneratedCodeInfo::GeneratedCodeInfo(::PROTOBUF_NAMESPACE_ID::Arena* arena)
 }
 }
 GeneratedCodeInfo::GeneratedCodeInfo(const GeneratedCodeInfo& from)
 GeneratedCodeInfo::GeneratedCodeInfo(const GeneratedCodeInfo& from)
   : ::PROTOBUF_NAMESPACE_ID::Message(),
   : ::PROTOBUF_NAMESPACE_ID::Message(),
-      _has_bits_(from._has_bits_),
       annotation_(from.annotation_) {
       annotation_(from.annotation_) {
   _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   // @@protoc_insertion_point(copy_constructor:google.protobuf.GeneratedCodeInfo)
   // @@protoc_insertion_point(copy_constructor:google.protobuf.GeneratedCodeInfo)
@@ -11075,7 +11052,6 @@ void GeneratedCodeInfo::Clear() {
   (void) cached_has_bits;
   (void) cached_has_bits;
 
 
   annotation_.Clear();
   annotation_.Clear();
-  _has_bits_.Clear();
   _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
   _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 }
 
 
@@ -11213,7 +11189,6 @@ bool GeneratedCodeInfo::IsInitialized() const {
 void GeneratedCodeInfo::InternalSwap(GeneratedCodeInfo* other) {
 void GeneratedCodeInfo::InternalSwap(GeneratedCodeInfo* other) {
   using std::swap;
   using std::swap;
   _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
   _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
-  swap(_has_bits_[0], other->_has_bits_[0]);
   annotation_.InternalSwap(&other->annotation_);
   annotation_.InternalSwap(&other->annotation_);
 }
 }
 
 

+ 5 - 10
src/google/protobuf/descriptor.pb.h

@@ -477,9 +477,8 @@ class PROTOBUF_EXPORT FileDescriptorSet PROTOBUF_FINAL :
   template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper;
   template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper;
   typedef void InternalArenaConstructable_;
   typedef void InternalArenaConstructable_;
   typedef void DestructorSkippable_;
   typedef void DestructorSkippable_;
-  ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_;
-  mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
   ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::FileDescriptorProto > file_;
   ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::FileDescriptorProto > file_;
+  mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
   friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
   friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
 };
 };
 // -------------------------------------------------------------------
 // -------------------------------------------------------------------
@@ -1757,9 +1756,8 @@ class PROTOBUF_EXPORT ExtensionRangeOptions PROTOBUF_FINAL :
   template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper;
   template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper;
   typedef void InternalArenaConstructable_;
   typedef void InternalArenaConstructable_;
   typedef void DestructorSkippable_;
   typedef void DestructorSkippable_;
-  ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_;
-  mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
   ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::UninterpretedOption > uninterpreted_option_;
   ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::UninterpretedOption > uninterpreted_option_;
+  mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
   friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
   friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
 };
 };
 // -------------------------------------------------------------------
 // -------------------------------------------------------------------
@@ -4853,9 +4851,8 @@ class PROTOBUF_EXPORT OneofOptions PROTOBUF_FINAL :
   template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper;
   template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper;
   typedef void InternalArenaConstructable_;
   typedef void InternalArenaConstructable_;
   typedef void DestructorSkippable_;
   typedef void DestructorSkippable_;
-  ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_;
-  mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
   ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::UninterpretedOption > uninterpreted_option_;
   ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::UninterpretedOption > uninterpreted_option_;
+  mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
   friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
   friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
 };
 };
 // -------------------------------------------------------------------
 // -------------------------------------------------------------------
@@ -6508,9 +6505,8 @@ class PROTOBUF_EXPORT SourceCodeInfo PROTOBUF_FINAL :
   template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper;
   template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper;
   typedef void InternalArenaConstructable_;
   typedef void InternalArenaConstructable_;
   typedef void DestructorSkippable_;
   typedef void DestructorSkippable_;
-  ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_;
-  mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
   ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location > location_;
   ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location > location_;
+  mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
   friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
   friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
 };
 };
 // -------------------------------------------------------------------
 // -------------------------------------------------------------------
@@ -6884,9 +6880,8 @@ class PROTOBUF_EXPORT GeneratedCodeInfo PROTOBUF_FINAL :
   template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper;
   template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper;
   typedef void InternalArenaConstructable_;
   typedef void InternalArenaConstructable_;
   typedef void DestructorSkippable_;
   typedef void DestructorSkippable_;
-  ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_;
-  mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
   ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation > annotation_;
   ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation > annotation_;
+  mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
   friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
   friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
 };
 };
 // ===================================================================
 // ===================================================================

+ 95 - 39
src/google/protobuf/generated_enum_util.cc

@@ -41,6 +41,7 @@
 #include <iterator>
 #include <iterator>
 #include <limits>  // To support Visual Studio 2008
 #include <limits>  // To support Visual Studio 2008
 #include <set>
 #include <set>
+#include <type_traits>
 #include <utility>
 #include <utility>
 
 
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/stubs/common.h>
@@ -184,6 +185,35 @@ struct DerefCompare {
   bool operator()(const Key* n0, const Key* n1) const { return *n0 < *n1; }
   bool operator()(const Key* n0, const Key* n1) const { return *n0 < *n1; }
 };
 };
 
 
+// This class is used to get trivially destructible views of std::string and
+// MapKey, which are the only non-trivially destructible allowed key types.
+template <typename Key>
+class KeyView {
+ public:
+  KeyView(const Key& key) : key_(&key) {}  // NOLINT(runtime/explicit)
+
+  const Key& get() const { return *key_; }
+  // Allows implicit conversions to `const Key&`, which allows us to use the
+  // hasher defined for Key.
+  operator const Key&() const { return get(); }  // NOLINT(runtime/explicit)
+
+  bool operator==(const KeyView& other) const { return get() == other.get(); }
+  bool operator==(const Key& other) const { return get() == other; }
+  bool operator<(const KeyView& other) const { return get() < other.get(); }
+  bool operator<(const Key& other) const { return get() < other; }
+
+ private:
+  const Key* key_;
+};
+
+// Allows the InnerMap type to support skippable destruction.
+template <typename Key>
+struct GetTrivialKey {
+  using type =
+      typename std::conditional<std::is_trivially_destructible<Key>::value, Key,
+                                KeyView<Key>>::type;
+};
+
 }  // namespace internal
 }  // namespace internal
 
 
 // This is the class for Map's internal value_type. Instead of using
 // This is the class for Map's internal value_type. Instead of using
@@ -282,26 +312,27 @@ class Map {
   }
   }
 
 
  private:
  private:
-  void Init() {
-    elements_ =
-        Arena::Create<InnerMap>(arena_, 0u, hasher(), Allocator(arena_));
-  }
-
-  // InnerMap's key type is Key and its value type is value_type*.  We use a
-  // custom class here and for Node, below, to ensure that k_ is at offset 0,
-  // allowing safe conversion from pointer to Node to pointer to Key, and vice
-  // versa when appropriate.
+  void Init() { elements_ = Arena::CreateMessage<InnerMap>(arena_, 0u); }
+
+  // InnerMap's key type is TrivialKey and its value type is value_type*.  We
+  // use a custom class here and for Node, below, to ensure that k_ is at offset
+  // 0, allowing safe conversion from pointer to Node to pointer to TrivialKey,
+  // and vice versa when appropriate.  We use GetTrivialKey to adapt Key to
+  // be a trivially destructible view if Key is not already trivially
+  // destructible.  This view points into the Key inside v_ once it's
+  // initialized.
+  using TrivialKey = typename internal::GetTrivialKey<Key>::type;
   class KeyValuePair {
   class KeyValuePair {
    public:
    public:
-    KeyValuePair(const Key& k, value_type* v) : k_(k), v_(v) {}
+    KeyValuePair(const TrivialKey& k, value_type* v) : k_(k), v_(v) {}
 
 
-    const Key& key() const { return k_; }
-    Key& key() { return k_; }
+    const TrivialKey& key() const { return k_; }
+    TrivialKey& key() { return k_; }
     value_type* value() const { return v_; }
     value_type* value() const { return v_; }
     value_type*& value() { return v_; }
     value_type*& value() { return v_; }
 
 
    private:
    private:
-    Key k_;
+    TrivialKey k_;
     value_type* v_;
     value_type* v_;
   };
   };
 
 
@@ -336,19 +367,28 @@ class Map {
   // 8. Mutations to a map do not invalidate the map's iterators, pointers to
   // 8. Mutations to a map do not invalidate the map's iterators, pointers to
   //    elements, or references to elements.
   //    elements, or references to elements.
   // 9. Except for erase(iterator), any non-const method can reorder iterators.
   // 9. Except for erase(iterator), any non-const method can reorder iterators.
+  // 10. InnerMap's key is TrivialKey, which is either Key, if Key is trivially
+  //    destructible, or a trivially destructible view of Key otherwise. This
+  //    allows InnerMap's destructor to be skipped when InnerMap is
+  //    arena-allocated.
   class InnerMap : private hasher {
   class InnerMap : private hasher {
    public:
    public:
     using Value = value_type*;
     using Value = value_type*;
 
 
-    InnerMap(size_type n, hasher h, Allocator alloc)
-        : hasher(h),
+    explicit InnerMap(size_type n) : InnerMap(nullptr, n) {}
+    InnerMap(Arena* arena, size_type n)
+        : hasher(),
           num_elements_(0),
           num_elements_(0),
           seed_(Seed()),
           seed_(Seed()),
           table_(nullptr),
           table_(nullptr),
-          alloc_(alloc) {
+          alloc_(arena) {
       n = TableSize(n);
       n = TableSize(n);
       table_ = CreateEmptyTable(n);
       table_ = CreateEmptyTable(n);
       num_buckets_ = index_of_first_non_null_ = n;
       num_buckets_ = index_of_first_non_null_ = n;
+      static_assert(
+          std::is_trivially_destructible<KeyValuePair>::value,
+          "We require KeyValuePair to be trivially destructible so that we can "
+          "skip InnerMap's destructor when it's arena allocated.");
     }
     }
 
 
     ~InnerMap() {
     ~InnerMap() {
@@ -369,17 +409,19 @@ class Map {
 
 
     // This is safe only if the given pointer is known to point to a Key that is
     // This is safe only if the given pointer is known to point to a Key that is
     // part of a Node.
     // part of a Node.
-    static Node* NodePtrFromKeyPtr(Key* k) {
+    static Node* NodePtrFromKeyPtr(TrivialKey* k) {
       return reinterpret_cast<Node*>(k);
       return reinterpret_cast<Node*>(k);
     }
     }
 
 
-    static Key* KeyPtrFromNodePtr(Node* node) { return &node->kv.key(); }
+    static TrivialKey* KeyPtrFromNodePtr(Node* node) { return &node->kv.key(); }
 
 
     // Trees.  The payload type is pointer to Key, so that we can query the tree
     // Trees.  The payload type is pointer to Key, so that we can query the tree
     // with Keys that are not in any particular data structure.  When we insert,
     // with Keys that are not in any particular data structure.  When we insert,
     // though, the pointer is always pointing to a Key that is inside a Node.
     // though, the pointer is always pointing to a Key that is inside a Node.
-    using KeyPtrAllocator = typename Allocator::template rebind<Key*>::other;
-    using Tree = std::set<Key*, internal::DerefCompare<Key>, KeyPtrAllocator>;
+    using KeyPtrAllocator =
+        typename Allocator::template rebind<TrivialKey*>::other;
+    using Tree = std::set<TrivialKey*, internal::DerefCompare<TrivialKey>,
+                          KeyPtrAllocator>;
     using TreeIterator = typename Tree::iterator;
     using TreeIterator = typename Tree::iterator;
 
 
     // iterator and const_iterator are instantiations of iterator_base.
     // iterator and const_iterator are instantiations of iterator_base.
@@ -499,7 +541,7 @@ class Map {
         // Well, bucket_index_ still might be correct, but probably
         // Well, bucket_index_ still might be correct, but probably
         // not.  Revalidate just to be sure.  This case is rare enough that we
         // not.  Revalidate just to be sure.  This case is rare enough that we
         // don't worry about potential optimizations, such as having a custom
         // don't worry about potential optimizations, such as having a custom
-        // find-like method that compares Node* instead of const Key&.
+        // find-like method that compares Node* instead of TrivialKey.
         iterator_base i(m_->find(*KeyPtrFromNodePtr(node_), it));
         iterator_base i(m_->find(*KeyPtrFromNodePtr(node_), it));
         bucket_index_ = i.bucket_index_;
         bucket_index_ = i.bucket_index_;
         return m_->TableEntryIsList(bucket_index_);
         return m_->TableEntryIsList(bucket_index_);
@@ -558,9 +600,9 @@ class Map {
     size_type size() const { return num_elements_; }
     size_type size() const { return num_elements_; }
     bool empty() const { return size() == 0; }
     bool empty() const { return size() == 0; }
 
 
-    iterator find(const Key& k) { return iterator(FindHelper(k).first); }
-    const_iterator find(const Key& k) const { return find(k, nullptr); }
-    bool contains(const Key& k) const { return find(k) != end(); }
+    iterator find(const TrivialKey& k) { return iterator(FindHelper(k).first); }
+    const_iterator find(const TrivialKey& k) const { return find(k, nullptr); }
+    bool contains(const TrivialKey& k) const { return find(k) != end(); }
 
 
     // In traditional C++ style, this performs "insert if not present."
     // In traditional C++ style, this performs "insert if not present."
     std::pair<iterator, bool> insert(const KeyValuePair& kv) {
     std::pair<iterator, bool> insert(const KeyValuePair& kv) {
@@ -582,7 +624,7 @@ class Map {
 
 
     // The same, but if an insertion is necessary then the value portion of the
     // The same, but if an insertion is necessary then the value portion of the
     // inserted key-value pair is left uninitialized.
     // inserted key-value pair is left uninitialized.
-    std::pair<iterator, bool> insert(const Key& k) {
+    std::pair<iterator, bool> insert(const TrivialKey& k) {
       std::pair<const_iterator, size_type> p = FindHelper(k);
       std::pair<const_iterator, size_type> p = FindHelper(k);
       // Case 1: key was already present.
       // Case 1: key was already present.
       if (p.first.node_ != nullptr)
       if (p.first.node_ != nullptr)
@@ -593,16 +635,19 @@ class Map {
       }
       }
       const size_type b = p.second;  // bucket number
       const size_type b = p.second;  // bucket number
       Node* node = Alloc<Node>(1);
       Node* node = Alloc<Node>(1);
-      using KeyAllocator = typename Allocator::template rebind<Key>::other;
+      using KeyAllocator =
+          typename Allocator::template rebind<TrivialKey>::other;
       KeyAllocator(alloc_).construct(&node->kv.key(), k);
       KeyAllocator(alloc_).construct(&node->kv.key(), k);
       iterator result = InsertUnique(b, node);
       iterator result = InsertUnique(b, node);
       ++num_elements_;
       ++num_elements_;
       return std::make_pair(result, true);
       return std::make_pair(result, true);
     }
     }
 
 
-    Value& operator[](const Key& k) {
+    // Returns iterator so that outer map can update the TrivialKey to point to
+    // the Key inside value_type in case TrivialKey is a view type.
+    iterator operator[](const TrivialKey& k) {
       KeyValuePair kv(k, Value());
       KeyValuePair kv(k, Value());
-      return insert(kv).first->value();
+      return insert(kv).first;
     }
     }
 
 
     void erase(iterator it) {
     void erase(iterator it) {
@@ -639,13 +684,13 @@ class Map {
     }
     }
 
 
    private:
    private:
-    const_iterator find(const Key& k, TreeIterator* it) const {
+    const_iterator find(const TrivialKey& k, TreeIterator* it) const {
       return FindHelper(k, it).first;
       return FindHelper(k, it).first;
     }
     }
-    std::pair<const_iterator, size_type> FindHelper(const Key& k) const {
+    std::pair<const_iterator, size_type> FindHelper(const TrivialKey& k) const {
       return FindHelper(k, nullptr);
       return FindHelper(k, nullptr);
     }
     }
-    std::pair<const_iterator, size_type> FindHelper(const Key& k,
+    std::pair<const_iterator, size_type> FindHelper(const TrivialKey& k,
                                                     TreeIterator* it) const {
                                                     TreeIterator* it) const {
       size_type b = BucketNumber(k);
       size_type b = BucketNumber(k);
       if (TableEntryIsNonEmptyList(b)) {
       if (TableEntryIsNonEmptyList(b)) {
@@ -661,7 +706,7 @@ class Map {
         GOOGLE_DCHECK_EQ(table_[b], table_[b ^ 1]);
         GOOGLE_DCHECK_EQ(table_[b], table_[b ^ 1]);
         b &= ~static_cast<size_t>(1);
         b &= ~static_cast<size_t>(1);
         Tree* tree = static_cast<Tree*>(table_[b]);
         Tree* tree = static_cast<Tree*>(table_[b]);
-        Key* key = const_cast<Key*>(&k);
+        TrivialKey* key = const_cast<TrivialKey*>(&k);
         typename Tree::iterator tree_it = tree->find(key);
         typename Tree::iterator tree_it = tree->find(key);
         if (tree_it != tree->end()) {
         if (tree_it != tree->end()) {
           if (it != nullptr) *it = tree_it;
           if (it != nullptr) *it = tree_it;
@@ -886,14 +931,13 @@ class Map {
       return count >= kMaxLength;
       return count >= kMaxLength;
     }
     }
 
 
-    size_type BucketNumber(const Key& k) const {
-      // We inherit from hasher, so one-arg operator() provides a hash function.
-      size_type h = (*const_cast<InnerMap*>(this))(k);
+    size_type BucketNumber(const TrivialKey& k) const {
+      size_type h = hash_function()(k);
       return (h + seed_) & (num_buckets_ - 1);
       return (h + seed_) & (num_buckets_ - 1);
     }
     }
 
 
-    bool IsMatch(const Key& k0, const Key& k1) const {
-      return std::equal_to<Key>()(k0, k1);
+    bool IsMatch(const TrivialKey& k0, const TrivialKey& k1) const {
+      return k0 == k1;
     }
     }
 
 
     // Return a power of two no less than max(kMinTableSize, n).
     // Return a power of two no less than max(kMinTableSize, n).
@@ -949,6 +993,10 @@ class Map {
       return s;
       return s;
     }
     }
 
 
+    friend class Arena;
+    using InternalArenaConstructable_ = void;
+    using DestructorSkippable_ = void;
+
     size_type num_elements_;
     size_type num_elements_;
     size_type num_buckets_;
     size_type num_buckets_;
     size_type seed_;
     size_type seed_;
@@ -1050,9 +1098,12 @@ class Map {
 
 
   // Element access
   // Element access
   T& operator[](const key_type& key) {
   T& operator[](const key_type& key) {
-    value_type** value = &(*elements_)[key];
+    typename InnerMap::iterator it = (*elements_)[key];
+    value_type** value = &it->value();
     if (*value == nullptr) {
     if (*value == nullptr) {
       *value = CreateValueTypeInternal(key);
       *value = CreateValueTypeInternal(key);
+      // We need to update the key in case it's a view type.
+      it->key() = (*value)->first;
       internal::MapValueInitializer<is_proto_enum<T>::value, T>::Initialize(
       internal::MapValueInitializer<is_proto_enum<T>::value, T>::Initialize(
           (*value)->second, default_enum_value_);
           (*value)->second, default_enum_value_);
     }
     }
@@ -1106,6 +1157,8 @@ class Map {
         elements_->insert(value.first);
         elements_->insert(value.first);
     if (p.second) {
     if (p.second) {
       p.first->value() = CreateValueTypeInternal(value);
       p.first->value() = CreateValueTypeInternal(value);
+      // We need to update the key in case it's a view type.
+      p.first->key() = p.first->value()->first;
     }
     }
     return std::pair<iterator, bool>(iterator(p.first), p.second);
     return std::pair<iterator, bool>(iterator(p.first), p.second);
   }
   }
@@ -1133,9 +1186,12 @@ class Map {
     }
     }
   }
   }
   iterator erase(iterator pos) {
   iterator erase(iterator pos) {
-    if (arena_ == nullptr) delete pos.operator->();
+    value_type* value = pos.operator->();
     iterator i = pos++;
     iterator i = pos++;
     elements_->erase(i.it_);
     elements_->erase(i.it_);
+    // Note: we need to delete the value after erasing from the inner map
+    // because the inner map's key may be a view of the value's key.
+    if (arena_ == nullptr) delete value;
     return pos;
     return pos;
   }
   }
   void erase(iterator first, iterator last) {
   void erase(iterator first, iterator last) {

+ 206 - 206
src/google/protobuf/map_field.h

@@ -56,8 +56,213 @@
 namespace google {
 namespace google {
 namespace protobuf {
 namespace protobuf {
 class DynamicMessage;
 class DynamicMessage;
-class MapKey;
 class MapIterator;
 class MapIterator;
+
+#define TYPE_CHECK(EXPECTEDTYPE, METHOD)                                   \
+  if (type() != EXPECTEDTYPE) {                                            \
+    GOOGLE_LOG(FATAL) << "Protocol Buffer map usage error:\n"                     \
+               << METHOD << " type does not match\n"                       \
+               << "  Expected : "                                          \
+               << FieldDescriptor::CppTypeName(EXPECTEDTYPE) << "\n"       \
+               << "  Actual   : " << FieldDescriptor::CppTypeName(type()); \
+  }
+
+// MapKey is an union type for representing any possible
+// map key.
+class PROTOBUF_EXPORT MapKey {
+ public:
+  MapKey() : type_(0) {}
+  MapKey(const MapKey& other) : type_(0) { CopyFrom(other); }
+
+  MapKey& operator=(const MapKey& other) {
+    CopyFrom(other);
+    return *this;
+  }
+
+  ~MapKey() {
+    if (type_ == FieldDescriptor::CPPTYPE_STRING) {
+      val_.string_value_.Destruct();
+    }
+  }
+
+  FieldDescriptor::CppType type() const {
+    if (type_ == 0) {
+      GOOGLE_LOG(FATAL) << "Protocol Buffer map usage error:\n"
+                 << "MapKey::type MapKey is not initialized. "
+                 << "Call set methods to initialize MapKey.";
+    }
+    return (FieldDescriptor::CppType)type_;
+  }
+
+  void SetInt64Value(int64 value) {
+    SetType(FieldDescriptor::CPPTYPE_INT64);
+    val_.int64_value_ = value;
+  }
+  void SetUInt64Value(uint64 value) {
+    SetType(FieldDescriptor::CPPTYPE_UINT64);
+    val_.uint64_value_ = value;
+  }
+  void SetInt32Value(int32 value) {
+    SetType(FieldDescriptor::CPPTYPE_INT32);
+    val_.int32_value_ = value;
+  }
+  void SetUInt32Value(uint32 value) {
+    SetType(FieldDescriptor::CPPTYPE_UINT32);
+    val_.uint32_value_ = value;
+  }
+  void SetBoolValue(bool value) {
+    SetType(FieldDescriptor::CPPTYPE_BOOL);
+    val_.bool_value_ = value;
+  }
+  void SetStringValue(std::string val) {
+    SetType(FieldDescriptor::CPPTYPE_STRING);
+    *val_.string_value_.get_mutable() = std::move(val);
+  }
+
+  int64 GetInt64Value() const {
+    TYPE_CHECK(FieldDescriptor::CPPTYPE_INT64, "MapKey::GetInt64Value");
+    return val_.int64_value_;
+  }
+  uint64 GetUInt64Value() const {
+    TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT64, "MapKey::GetUInt64Value");
+    return val_.uint64_value_;
+  }
+  int32 GetInt32Value() const {
+    TYPE_CHECK(FieldDescriptor::CPPTYPE_INT32, "MapKey::GetInt32Value");
+    return val_.int32_value_;
+  }
+  uint32 GetUInt32Value() const {
+    TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT32, "MapKey::GetUInt32Value");
+    return val_.uint32_value_;
+  }
+  bool GetBoolValue() const {
+    TYPE_CHECK(FieldDescriptor::CPPTYPE_BOOL, "MapKey::GetBoolValue");
+    return val_.bool_value_;
+  }
+  const std::string& GetStringValue() const {
+    TYPE_CHECK(FieldDescriptor::CPPTYPE_STRING, "MapKey::GetStringValue");
+    return val_.string_value_.get();
+  }
+
+  bool operator<(const MapKey& other) const {
+    if (type_ != other.type_) {
+      // We could define a total order that handles this case, but
+      // there currently no need.  So, for now, fail.
+      GOOGLE_LOG(FATAL) << "Unsupported: type mismatch";
+    }
+    switch (type()) {
+      case FieldDescriptor::CPPTYPE_DOUBLE:
+      case FieldDescriptor::CPPTYPE_FLOAT:
+      case FieldDescriptor::CPPTYPE_ENUM:
+      case FieldDescriptor::CPPTYPE_MESSAGE:
+        GOOGLE_LOG(FATAL) << "Unsupported";
+        return false;
+      case FieldDescriptor::CPPTYPE_STRING:
+        return val_.string_value_.get() < other.val_.string_value_.get();
+      case FieldDescriptor::CPPTYPE_INT64:
+        return val_.int64_value_ < other.val_.int64_value_;
+      case FieldDescriptor::CPPTYPE_INT32:
+        return val_.int32_value_ < other.val_.int32_value_;
+      case FieldDescriptor::CPPTYPE_UINT64:
+        return val_.uint64_value_ < other.val_.uint64_value_;
+      case FieldDescriptor::CPPTYPE_UINT32:
+        return val_.uint32_value_ < other.val_.uint32_value_;
+      case FieldDescriptor::CPPTYPE_BOOL:
+        return val_.bool_value_ < other.val_.bool_value_;
+    }
+    return false;
+  }
+
+  bool operator==(const MapKey& other) const {
+    if (type_ != other.type_) {
+      // To be consistent with operator<, we don't allow this either.
+      GOOGLE_LOG(FATAL) << "Unsupported: type mismatch";
+    }
+    switch (type()) {
+      case FieldDescriptor::CPPTYPE_DOUBLE:
+      case FieldDescriptor::CPPTYPE_FLOAT:
+      case FieldDescriptor::CPPTYPE_ENUM:
+      case FieldDescriptor::CPPTYPE_MESSAGE:
+        GOOGLE_LOG(FATAL) << "Unsupported";
+        break;
+      case FieldDescriptor::CPPTYPE_STRING:
+        return val_.string_value_.get() == other.val_.string_value_.get();
+      case FieldDescriptor::CPPTYPE_INT64:
+        return val_.int64_value_ == other.val_.int64_value_;
+      case FieldDescriptor::CPPTYPE_INT32:
+        return val_.int32_value_ == other.val_.int32_value_;
+      case FieldDescriptor::CPPTYPE_UINT64:
+        return val_.uint64_value_ == other.val_.uint64_value_;
+      case FieldDescriptor::CPPTYPE_UINT32:
+        return val_.uint32_value_ == other.val_.uint32_value_;
+      case FieldDescriptor::CPPTYPE_BOOL:
+        return val_.bool_value_ == other.val_.bool_value_;
+    }
+    GOOGLE_LOG(FATAL) << "Can't get here.";
+    return false;
+  }
+
+  void CopyFrom(const MapKey& other) {
+    SetType(other.type());
+    switch (type_) {
+      case FieldDescriptor::CPPTYPE_DOUBLE:
+      case FieldDescriptor::CPPTYPE_FLOAT:
+      case FieldDescriptor::CPPTYPE_ENUM:
+      case FieldDescriptor::CPPTYPE_MESSAGE:
+        GOOGLE_LOG(FATAL) << "Unsupported";
+        break;
+      case FieldDescriptor::CPPTYPE_STRING:
+        *val_.string_value_.get_mutable() = other.val_.string_value_.get();
+        break;
+      case FieldDescriptor::CPPTYPE_INT64:
+        val_.int64_value_ = other.val_.int64_value_;
+        break;
+      case FieldDescriptor::CPPTYPE_INT32:
+        val_.int32_value_ = other.val_.int32_value_;
+        break;
+      case FieldDescriptor::CPPTYPE_UINT64:
+        val_.uint64_value_ = other.val_.uint64_value_;
+        break;
+      case FieldDescriptor::CPPTYPE_UINT32:
+        val_.uint32_value_ = other.val_.uint32_value_;
+        break;
+      case FieldDescriptor::CPPTYPE_BOOL:
+        val_.bool_value_ = other.val_.bool_value_;
+        break;
+    }
+  }
+
+ private:
+  template <typename K, typename V>
+  friend class internal::TypeDefinedMapFieldBase;
+  friend class ::PROTOBUF_NAMESPACE_ID::MapIterator;
+  friend class internal::DynamicMapField;
+
+  union KeyValue {
+    KeyValue() {}
+    internal::ExplicitlyConstructed<std::string> string_value_;
+    int64 int64_value_;
+    int32 int32_value_;
+    uint64 uint64_value_;
+    uint32 uint32_value_;
+    bool bool_value_;
+  } val_;
+
+  void SetType(FieldDescriptor::CppType type) {
+    if (type_ == type) return;
+    if (type_ == FieldDescriptor::CPPTYPE_STRING) {
+      val_.string_value_.Destruct();
+    }
+    type_ = type;
+    if (type_ == FieldDescriptor::CPPTYPE_STRING) {
+      val_.string_value_.DefaultConstruct();
+    }
+  }
+
+  // type_ is 0 or a valid FieldDescriptor::CppType.
+  int type_;
+};
+
 namespace internal {
 namespace internal {
 
 
 class ContendedMapCleanTest;
 class ContendedMapCleanTest;
@@ -374,211 +579,6 @@ class PROTOBUF_EXPORT DynamicMapField
 
 
 }  // namespace internal
 }  // namespace internal
 
 
-#define TYPE_CHECK(EXPECTEDTYPE, METHOD)                                   \
-  if (type() != EXPECTEDTYPE) {                                            \
-    GOOGLE_LOG(FATAL) << "Protocol Buffer map usage error:\n"                     \
-               << METHOD << " type does not match\n"                       \
-               << "  Expected : "                                          \
-               << FieldDescriptor::CppTypeName(EXPECTEDTYPE) << "\n"       \
-               << "  Actual   : " << FieldDescriptor::CppTypeName(type()); \
-  }
-
-// MapKey is an union type for representing any possible
-// map key.
-class PROTOBUF_EXPORT MapKey {
- public:
-  MapKey() : type_(0) {}
-  MapKey(const MapKey& other) : type_(0) { CopyFrom(other); }
-
-  MapKey& operator=(const MapKey& other) {
-    CopyFrom(other);
-    return *this;
-  }
-
-  ~MapKey() {
-    if (type_ == FieldDescriptor::CPPTYPE_STRING) {
-      val_.string_value_.Destruct();
-    }
-  }
-
-  FieldDescriptor::CppType type() const {
-    if (type_ == 0) {
-      GOOGLE_LOG(FATAL) << "Protocol Buffer map usage error:\n"
-                 << "MapKey::type MapKey is not initialized. "
-                 << "Call set methods to initialize MapKey.";
-    }
-    return (FieldDescriptor::CppType)type_;
-  }
-
-  void SetInt64Value(int64 value) {
-    SetType(FieldDescriptor::CPPTYPE_INT64);
-    val_.int64_value_ = value;
-  }
-  void SetUInt64Value(uint64 value) {
-    SetType(FieldDescriptor::CPPTYPE_UINT64);
-    val_.uint64_value_ = value;
-  }
-  void SetInt32Value(int32 value) {
-    SetType(FieldDescriptor::CPPTYPE_INT32);
-    val_.int32_value_ = value;
-  }
-  void SetUInt32Value(uint32 value) {
-    SetType(FieldDescriptor::CPPTYPE_UINT32);
-    val_.uint32_value_ = value;
-  }
-  void SetBoolValue(bool value) {
-    SetType(FieldDescriptor::CPPTYPE_BOOL);
-    val_.bool_value_ = value;
-  }
-  void SetStringValue(std::string val) {
-    SetType(FieldDescriptor::CPPTYPE_STRING);
-    *val_.string_value_.get_mutable() = std::move(val);
-  }
-
-  int64 GetInt64Value() const {
-    TYPE_CHECK(FieldDescriptor::CPPTYPE_INT64, "MapKey::GetInt64Value");
-    return val_.int64_value_;
-  }
-  uint64 GetUInt64Value() const {
-    TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT64, "MapKey::GetUInt64Value");
-    return val_.uint64_value_;
-  }
-  int32 GetInt32Value() const {
-    TYPE_CHECK(FieldDescriptor::CPPTYPE_INT32, "MapKey::GetInt32Value");
-    return val_.int32_value_;
-  }
-  uint32 GetUInt32Value() const {
-    TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT32, "MapKey::GetUInt32Value");
-    return val_.uint32_value_;
-  }
-  bool GetBoolValue() const {
-    TYPE_CHECK(FieldDescriptor::CPPTYPE_BOOL, "MapKey::GetBoolValue");
-    return val_.bool_value_;
-  }
-  const std::string& GetStringValue() const {
-    TYPE_CHECK(FieldDescriptor::CPPTYPE_STRING, "MapKey::GetStringValue");
-    return val_.string_value_.get();
-  }
-
-  bool operator<(const MapKey& other) const {
-    if (type_ != other.type_) {
-      // We could define a total order that handles this case, but
-      // there currently no need.  So, for now, fail.
-      GOOGLE_LOG(FATAL) << "Unsupported: type mismatch";
-    }
-    switch (type()) {
-      case FieldDescriptor::CPPTYPE_DOUBLE:
-      case FieldDescriptor::CPPTYPE_FLOAT:
-      case FieldDescriptor::CPPTYPE_ENUM:
-      case FieldDescriptor::CPPTYPE_MESSAGE:
-        GOOGLE_LOG(FATAL) << "Unsupported";
-        return false;
-      case FieldDescriptor::CPPTYPE_STRING:
-        return val_.string_value_.get() < other.val_.string_value_.get();
-      case FieldDescriptor::CPPTYPE_INT64:
-        return val_.int64_value_ < other.val_.int64_value_;
-      case FieldDescriptor::CPPTYPE_INT32:
-        return val_.int32_value_ < other.val_.int32_value_;
-      case FieldDescriptor::CPPTYPE_UINT64:
-        return val_.uint64_value_ < other.val_.uint64_value_;
-      case FieldDescriptor::CPPTYPE_UINT32:
-        return val_.uint32_value_ < other.val_.uint32_value_;
-      case FieldDescriptor::CPPTYPE_BOOL:
-        return val_.bool_value_ < other.val_.bool_value_;
-    }
-    return false;
-  }
-
-  bool operator==(const MapKey& other) const {
-    if (type_ != other.type_) {
-      // To be consistent with operator<, we don't allow this either.
-      GOOGLE_LOG(FATAL) << "Unsupported: type mismatch";
-    }
-    switch (type()) {
-      case FieldDescriptor::CPPTYPE_DOUBLE:
-      case FieldDescriptor::CPPTYPE_FLOAT:
-      case FieldDescriptor::CPPTYPE_ENUM:
-      case FieldDescriptor::CPPTYPE_MESSAGE:
-        GOOGLE_LOG(FATAL) << "Unsupported";
-        break;
-      case FieldDescriptor::CPPTYPE_STRING:
-        return val_.string_value_.get() == other.val_.string_value_.get();
-      case FieldDescriptor::CPPTYPE_INT64:
-        return val_.int64_value_ == other.val_.int64_value_;
-      case FieldDescriptor::CPPTYPE_INT32:
-        return val_.int32_value_ == other.val_.int32_value_;
-      case FieldDescriptor::CPPTYPE_UINT64:
-        return val_.uint64_value_ == other.val_.uint64_value_;
-      case FieldDescriptor::CPPTYPE_UINT32:
-        return val_.uint32_value_ == other.val_.uint32_value_;
-      case FieldDescriptor::CPPTYPE_BOOL:
-        return val_.bool_value_ == other.val_.bool_value_;
-    }
-    GOOGLE_LOG(FATAL) << "Can't get here.";
-    return false;
-  }
-
-  void CopyFrom(const MapKey& other) {
-    SetType(other.type());
-    switch (type_) {
-      case FieldDescriptor::CPPTYPE_DOUBLE:
-      case FieldDescriptor::CPPTYPE_FLOAT:
-      case FieldDescriptor::CPPTYPE_ENUM:
-      case FieldDescriptor::CPPTYPE_MESSAGE:
-        GOOGLE_LOG(FATAL) << "Unsupported";
-        break;
-      case FieldDescriptor::CPPTYPE_STRING:
-        *val_.string_value_.get_mutable() = other.val_.string_value_.get();
-        break;
-      case FieldDescriptor::CPPTYPE_INT64:
-        val_.int64_value_ = other.val_.int64_value_;
-        break;
-      case FieldDescriptor::CPPTYPE_INT32:
-        val_.int32_value_ = other.val_.int32_value_;
-        break;
-      case FieldDescriptor::CPPTYPE_UINT64:
-        val_.uint64_value_ = other.val_.uint64_value_;
-        break;
-      case FieldDescriptor::CPPTYPE_UINT32:
-        val_.uint32_value_ = other.val_.uint32_value_;
-        break;
-      case FieldDescriptor::CPPTYPE_BOOL:
-        val_.bool_value_ = other.val_.bool_value_;
-        break;
-    }
-  }
-
- private:
-  template <typename K, typename V>
-  friend class internal::TypeDefinedMapFieldBase;
-  friend class ::PROTOBUF_NAMESPACE_ID::MapIterator;
-  friend class internal::DynamicMapField;
-
-  union KeyValue {
-    KeyValue() {}
-    internal::ExplicitlyConstructed<std::string> string_value_;
-    int64 int64_value_;
-    int32 int32_value_;
-    uint64 uint64_value_;
-    uint32 uint32_value_;
-    bool bool_value_;
-  } val_;
-
-  void SetType(FieldDescriptor::CppType type) {
-    if (type_ == type) return;
-    if (type_ == FieldDescriptor::CPPTYPE_STRING) {
-      val_.string_value_.Destruct();
-    }
-    type_ = type;
-    if (type_ == FieldDescriptor::CPPTYPE_STRING) {
-      val_.string_value_.DefaultConstruct();
-    }
-  }
-
-  // type_ is 0 or a valid FieldDescriptor::CppType.
-  int type_;
-};
-
 // MapValueRef points to a map value.
 // MapValueRef points to a map value.
 class PROTOBUF_EXPORT MapValueRef {
 class PROTOBUF_EXPORT MapValueRef {
  public:
  public:

+ 0 - 30
src/google/protobuf/map_test_util.inc

@@ -1,33 +1,3 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// https://developers.google.com/protocol-buffers/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
 // Protocol Buffers - Google's data interchange format
 // Protocol Buffers - Google's data interchange format
 // Copyright 2008 Google Inc.  All rights reserved.
 // Copyright 2008 Google Inc.  All rights reserved.
 // https://developers.google.com/protocol-buffers/
 // https://developers.google.com/protocol-buffers/

+ 0 - 30
src/google/protobuf/test_messages_proto3.proto

@@ -1,33 +1,3 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// https://developers.google.com/protocol-buffers/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
 // Protocol Buffers - Google's data interchange format
 // Protocol Buffers - Google's data interchange format
 // Copyright 2008 Google Inc.  All rights reserved.
 // Copyright 2008 Google Inc.  All rights reserved.
 // https://developers.google.com/protocol-buffers/
 // https://developers.google.com/protocol-buffers/

+ 21 - 15
src/google/protobuf/unittest_proto3_optional.proto

@@ -71,21 +71,27 @@ class MockObjectWriter : public ObjectWriter {
  public:
  public:
   MockObjectWriter() {}
   MockObjectWriter() {}
 
 
-  MOCK_METHOD1(StartObject, ObjectWriter*(StringPiece));
-  MOCK_METHOD0(EndObject, ObjectWriter*());
-  MOCK_METHOD1(StartList, ObjectWriter*(StringPiece));
-  MOCK_METHOD0(EndList, ObjectWriter*());
-  MOCK_METHOD2(RenderBool, ObjectWriter*(StringPiece, bool));
-  MOCK_METHOD2(RenderInt32, ObjectWriter*(StringPiece, int32));
-  MOCK_METHOD2(RenderUint32, ObjectWriter*(StringPiece, uint32));
-  MOCK_METHOD2(RenderInt64, ObjectWriter*(StringPiece, int64));
-  MOCK_METHOD2(RenderUint64, ObjectWriter*(StringPiece, uint64));
-  MOCK_METHOD2(RenderDouble, ObjectWriter*(StringPiece, double));
-  MOCK_METHOD2(RenderFloat, ObjectWriter*(StringPiece, float));
-  MOCK_METHOD2(RenderString,
-               ObjectWriter*(StringPiece, StringPiece));
-  MOCK_METHOD2(RenderBytes, ObjectWriter*(StringPiece, StringPiece));
-  MOCK_METHOD1(RenderNull, ObjectWriter*(StringPiece));
+  MOCK_METHOD(ObjectWriter*, StartObject, (StringPiece), (override));
+  MOCK_METHOD(ObjectWriter*, EndObject, (), (override));
+  MOCK_METHOD(ObjectWriter*, StartList, (StringPiece), (override));
+  MOCK_METHOD(ObjectWriter*, EndList, (), (override));
+  MOCK_METHOD(ObjectWriter*, RenderBool, (StringPiece, bool), (override));
+  MOCK_METHOD(ObjectWriter*, RenderInt32, (StringPiece, int32),
+              (override));
+  MOCK_METHOD(ObjectWriter*, RenderUint32, (StringPiece, uint32),
+              (override));
+  MOCK_METHOD(ObjectWriter*, RenderInt64, (StringPiece, int64),
+              (override));
+  MOCK_METHOD(ObjectWriter*, RenderUint64, (StringPiece, uint64),
+              (override));
+  MOCK_METHOD(ObjectWriter*, RenderDouble, (StringPiece, double),
+              (override));
+  MOCK_METHOD(ObjectWriter*, RenderFloat, (StringPiece, float),
+              (override));
+  MOCK_METHOD(ObjectWriter*, RenderString,
+              (StringPiece, StringPiece), (override));
+  MOCK_METHOD(ObjectWriter*, RenderBytes, (StringPiece, StringPiece));
+  MOCK_METHOD(ObjectWriter*, RenderNull, (StringPiece), (override));
 };
 };
 
 
 class ExpectingObjectWriter : public ObjectWriter {
 class ExpectingObjectWriter : public ObjectWriter {

+ 12 - 8
src/google/protobuf/util/internal/mock_error_listener.h

@@ -46,14 +46,18 @@ class MockErrorListener : public ErrorListener {
   MockErrorListener() {}
   MockErrorListener() {}
   virtual ~MockErrorListener() {}
   virtual ~MockErrorListener() {}
 
 
-  MOCK_METHOD3(InvalidName,
-               void(const LocationTrackerInterface& loc,
-                    StringPiece unknown_name, StringPiece message));
-  MOCK_METHOD3(InvalidValue,
-               void(const LocationTrackerInterface& loc,
-                    StringPiece type_name, StringPiece value));
-  MOCK_METHOD2(MissingField, void(const LocationTrackerInterface& loc,
-                                  StringPiece missing_name));
+  MOCK_METHOD(void, InvalidName,
+              (const LocationTrackerInterface& loc,
+               StringPiece unknown_name, StringPiece message),
+              (override));
+  MOCK_METHOD(void, InvalidValue,
+              (const LocationTrackerInterface& loc, StringPiece type_name,
+               StringPiece value),
+              (override));
+  MOCK_METHOD(void, MissingField,
+              (const LocationTrackerInterface& loc,
+               StringPiece missing_name),
+              (override));
 };
 };
 
 
 }  // namespace converter
 }  // namespace converter