Browse Source

Merge branch 'master' into integrate

Adam Cozzette 7 years ago
parent
commit
b78c218af5
47 changed files with 1381 additions and 293 deletions
  1. 9 3
      csharp/src/AddressBook/Addressbook.cs
  2. 6 2
      csharp/src/Google.Protobuf.Conformance/Conformance.cs
  3. 21 7
      csharp/src/Google.Protobuf.Test/TestProtos/MapUnittestProto3.cs
  4. 9 3
      csharp/src/Google.Protobuf.Test/TestProtos/TestMessagesProto3.cs
  5. 63 21
      csharp/src/Google.Protobuf.Test/TestProtos/UnittestCustomOptionsProto3.cs
  6. 3 1
      csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportProto3.cs
  7. 3 1
      csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportPublicProto3.cs
  8. 39 13
      csharp/src/Google.Protobuf.Test/TestProtos/UnittestIssues.cs
  9. 117 39
      csharp/src/Google.Protobuf.Test/TestProtos/UnittestProto3.cs
  10. 12 4
      csharp/src/Google.Protobuf.Test/TestProtos/UnittestWellKnownTypes.cs
  11. BIN
      csharp/src/Google.Protobuf.Test/testprotos.pb
  12. 19 1
      csharp/src/Google.Protobuf/CodedInputStream.cs
  13. 9 0
      csharp/src/Google.Protobuf/CodedOutputStream.cs
  14. 4 0
      csharp/src/Google.Protobuf/Collections/RepeatedField.cs
  15. 30 3
      csharp/src/Google.Protobuf/FieldCodec.cs
  16. 57 19
      csharp/src/Google.Protobuf/Reflection/Descriptor.cs
  17. 28 1
      csharp/src/Google.Protobuf/UnknownField.cs
  18. 41 9
      csharp/src/Google.Protobuf/UnknownFieldSet.cs
  19. 3 1
      csharp/src/Google.Protobuf/WellKnownTypes/Any.cs
  20. 9 3
      csharp/src/Google.Protobuf/WellKnownTypes/Api.cs
  21. 3 1
      csharp/src/Google.Protobuf/WellKnownTypes/Duration.cs
  22. 3 1
      csharp/src/Google.Protobuf/WellKnownTypes/Empty.cs
  23. 3 1
      csharp/src/Google.Protobuf/WellKnownTypes/FieldMask.cs
  24. 3 1
      csharp/src/Google.Protobuf/WellKnownTypes/SourceContext.cs
  25. 9 3
      csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs
  26. 3 1
      csharp/src/Google.Protobuf/WellKnownTypes/Timestamp.cs
  27. 15 5
      csharp/src/Google.Protobuf/WellKnownTypes/Type.cs
  28. 27 9
      csharp/src/Google.Protobuf/WellKnownTypes/Wrappers.cs
  29. 1 0
      docs/third_party.md
  30. 13 0
      examples/Makefile
  31. 21 1
      examples/README.md
  32. 70 0
      examples/add_person.dart
  33. 47 0
      examples/list_people.dart
  34. 5 0
      examples/pubspec.yaml
  35. 6 26
      objectivec/DevTools/full_mac_build.sh
  36. 5 0
      objectivec/GPBDescriptor.m
  37. 3 3
      objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj
  38. 3 3
      objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj
  39. 45 0
      objectivec/Tests/GPBMessageTests.m
  40. 86 34
      objectivec/Tests/unittest_objc.proto
  41. 1 0
      src/Makefile.am
  42. 3 1
      src/google/protobuf/compiler/csharp/csharp_message.cc
  43. 68 19
      src/google/protobuf/compiler/csharp/csharp_message_field.cc
  44. 179 0
      src/google/protobuf/compiler/objectivec/method_dump.sh
  45. 79 53
      src/google/protobuf/compiler/objectivec/objectivec_helpers.cc
  46. 197 0
      src/google/protobuf/compiler/objectivec/objectivec_nsobject_methods.h
  47. 1 0
      src/google/protobuf/implicit_weak_message.cc

+ 9 - 3
csharp/src/AddressBook/Addressbook.cs

@@ -260,7 +260,9 @@ namespace Google.Protobuf.Examples.AddressBook {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 10: {
             Name = input.ReadString();
@@ -440,7 +442,9 @@ namespace Google.Protobuf.Examples.AddressBook {
           while ((tag = input.ReadTag()) != 0) {
             switch(tag) {
               default:
-                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+                if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+                  return;
+                }
                 break;
               case 10: {
                 Number = input.ReadString();
@@ -573,7 +577,9 @@ namespace Google.Protobuf.Examples.AddressBook {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 10: {
             people_.AddEntriesFrom(input, _repeated_people_codec);

+ 6 - 2
csharp/src/Google.Protobuf.Conformance/Conformance.cs

@@ -343,7 +343,9 @@ namespace Conformance {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 10: {
             ProtobufPayload = input.ReadBytes();
@@ -683,7 +685,9 @@ namespace Conformance {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 10: {
             ParseError = input.ReadString();

+ 21 - 7
csharp/src/Google.Protobuf.Test/TestProtos/MapUnittestProto3.cs

@@ -541,7 +541,9 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 10: {
             mapInt32Int32_.AddEntriesFrom(input, _map_mapInt32Int32_codec);
@@ -737,7 +739,9 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 10: {
             if (testMap_ == null) {
@@ -861,7 +865,9 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 10: {
             mapInt32Message_.AddEntriesFrom(input, _map_mapInt32Message_codec);
@@ -1001,7 +1007,9 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 10: {
             map1_.AddEntriesFrom(input, _map_map1_codec);
@@ -1350,7 +1358,9 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 10: {
             mapInt32Int32_.AddEntriesFrom(input, _map_mapInt32Int32_codec);
@@ -1531,7 +1541,9 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 10: {
             type_.AddEntriesFrom(input, _map_type_codec);
@@ -1666,7 +1678,9 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 10: {
             entry_.AddEntriesFrom(input, _map_entry_codec);

+ 9 - 3
csharp/src/Google.Protobuf.Test/TestProtos/TestMessagesProto3.cs

@@ -2867,7 +2867,9 @@ namespace ProtobufTestMessages.Proto3 {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 8: {
             OptionalInt32 = input.ReadInt32();
@@ -3582,7 +3584,9 @@ namespace ProtobufTestMessages.Proto3 {
           while ((tag = input.ReadTag()) != 0) {
             switch(tag) {
               default:
-                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+                if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+                  return;
+                }
                 break;
               case 8: {
                 A = input.ReadInt32();
@@ -3723,7 +3727,9 @@ namespace ProtobufTestMessages.Proto3 {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 8: {
             C = input.ReadInt32();

+ 63 - 21
csharp/src/Google.Protobuf.Test/TestProtos/UnittestCustomOptionsProto3.cs

@@ -352,7 +352,9 @@ namespace UnitTest.Issues.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 10: {
             Field1 = input.ReadString();
@@ -478,7 +480,9 @@ namespace UnitTest.Issues.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
         }
       }
@@ -579,7 +583,9 @@ namespace UnitTest.Issues.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
         }
       }
@@ -680,7 +686,9 @@ namespace UnitTest.Issues.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
         }
       }
@@ -781,7 +789,9 @@ namespace UnitTest.Issues.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
         }
       }
@@ -882,7 +892,9 @@ namespace UnitTest.Issues.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
         }
       }
@@ -996,7 +1008,9 @@ namespace UnitTest.Issues.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
         }
       }
@@ -1097,7 +1111,9 @@ namespace UnitTest.Issues.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
         }
       }
@@ -1198,7 +1214,9 @@ namespace UnitTest.Issues.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
         }
       }
@@ -1299,7 +1317,9 @@ namespace UnitTest.Issues.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
         }
       }
@@ -1400,7 +1420,9 @@ namespace UnitTest.Issues.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
         }
       }
@@ -1501,7 +1523,9 @@ namespace UnitTest.Issues.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
         }
       }
@@ -1690,7 +1714,9 @@ namespace UnitTest.Issues.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 8: {
             Foo = input.ReadInt32();
@@ -1902,7 +1928,9 @@ namespace UnitTest.Issues.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 10: {
             if (bar_ == null) {
@@ -2051,7 +2079,9 @@ namespace UnitTest.Issues.TestProtos {
           while ((tag = input.ReadTag()) != 0) {
             switch(tag) {
               default:
-                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+                if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+                  return;
+                }
                 break;
               case 8: {
                 Waldo = input.ReadInt32();
@@ -2185,7 +2215,9 @@ namespace UnitTest.Issues.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 8: {
             Qux = input.ReadInt32();
@@ -2293,7 +2325,9 @@ namespace UnitTest.Issues.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
         }
       }
@@ -2475,7 +2509,9 @@ namespace UnitTest.Issues.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 8: {
             I = input.ReadInt32();
@@ -2615,7 +2651,9 @@ namespace UnitTest.Issues.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 8: {
             Fieldname = input.ReadInt32();
@@ -2723,7 +2761,9 @@ namespace UnitTest.Issues.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
         }
       }
@@ -2855,7 +2895,9 @@ namespace UnitTest.Issues.TestProtos {
           while ((tag = input.ReadTag()) != 0) {
             switch(tag) {
               default:
-                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+                if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+                  return;
+                }
                 break;
               case 8: {
                 NestedField = input.ReadInt32();

+ 3 - 1
csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportProto3.cs

@@ -167,7 +167,9 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 8: {
             D = input.ReadInt32();

+ 3 - 1
csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportPublicProto3.cs

@@ -155,7 +155,9 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 8: {
             E = input.ReadInt32();

+ 39 - 13
csharp/src/Google.Protobuf.Test/TestProtos/UnittestIssues.cs

@@ -181,7 +181,9 @@ namespace UnitTest.Issues.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
         }
       }
@@ -284,7 +286,9 @@ namespace UnitTest.Issues.TestProtos {
           while ((tag = input.ReadTag()) != 0) {
             switch(tag) {
               default:
-                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+                if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+                  return;
+                }
                 break;
             }
           }
@@ -387,7 +391,9 @@ namespace UnitTest.Issues.TestProtos {
               while ((tag = input.ReadTag()) != 0) {
                 switch(tag) {
                   default:
-                    _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+                    if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+                      return;
+                    }
                     break;
                 }
               }
@@ -554,7 +560,9 @@ namespace UnitTest.Issues.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 8: {
             Value = (global::UnitTest.Issues.TestProtos.NegativeEnum) input.ReadEnum();
@@ -669,7 +677,9 @@ namespace UnitTest.Issues.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
         }
       }
@@ -899,7 +909,9 @@ namespace UnitTest.Issues.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 8: {
             PrimitiveValue = input.ReadInt32();
@@ -1056,7 +1068,9 @@ namespace UnitTest.Issues.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 8: {
             Item = input.ReadInt32();
@@ -1209,7 +1223,9 @@ namespace UnitTest.Issues.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 8: {
             Types_ = input.ReadInt32();
@@ -1323,7 +1339,9 @@ namespace UnitTest.Issues.TestProtos {
           while ((tag = input.ReadTag()) != 0) {
             switch(tag) {
               default:
-                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+                if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+                  return;
+                }
                 break;
             }
           }
@@ -1647,7 +1665,9 @@ namespace UnitTest.Issues.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 10: {
             PlainString = input.ReadString();
@@ -1847,7 +1867,9 @@ namespace UnitTest.Issues.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 10: {
             Name = input.ReadString();
@@ -2047,7 +2069,9 @@ namespace UnitTest.Issues.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 10: {
             Text = input.ReadString();
@@ -2211,7 +2235,9 @@ namespace UnitTest.Issues.TestProtos {
           while ((tag = input.ReadTag()) != 0) {
             switch(tag) {
               default:
-                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+                if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+                  return;
+                }
                 break;
               case 8: {
                 X = input.ReadInt32();

+ 117 - 39
csharp/src/Google.Protobuf.Test/TestProtos/UnittestProto3.cs

@@ -1387,7 +1387,9 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 8: {
             SingleInt32 = input.ReadInt32();
@@ -1755,7 +1757,9 @@ namespace Google.Protobuf.TestProtos {
           while ((tag = input.ReadTag()) != 0) {
             switch(tag) {
               default:
-                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+                if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+                  return;
+                }
                 break;
               case 8: {
                 Bb = input.ReadInt32();
@@ -1938,7 +1942,9 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 10: {
             if (child_ == null) {
@@ -2082,7 +2088,9 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 8: {
             DeprecatedInt32 = input.ReadInt32();
@@ -2215,7 +2223,9 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 8: {
             C = input.ReadInt32();
@@ -2320,7 +2330,9 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
         }
       }
@@ -2451,7 +2463,9 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 10: {
             if (foreignNested_ == null) {
@@ -2614,7 +2628,9 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 8: {
             A = input.ReadInt32();
@@ -2774,7 +2790,9 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 10: {
             if (a_ == null) {
@@ -2916,7 +2934,9 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 10: {
             if (bb_ == null) {
@@ -3075,7 +3095,9 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 10: {
             if (a_ == null) {
@@ -3211,7 +3233,9 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 8: {
             Value = (global::Google.Protobuf.TestProtos.TestEnumWithDupValue) input.ReadEnum();
@@ -3483,7 +3507,9 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 8: {
             PrimitiveField = input.ReadInt32();
@@ -3724,7 +3750,9 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 8: {
             MyInt = input.ReadInt64();
@@ -3899,7 +3927,9 @@ namespace Google.Protobuf.TestProtos {
           while ((tag = input.ReadTag()) != 0) {
             switch(tag) {
               default:
-                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+                if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+                  return;
+                }
                 break;
               case 8: {
                 Bb = input.ReadInt32();
@@ -4037,7 +4067,9 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 8: {
             SparseEnum = (global::Google.Protobuf.TestProtos.TestSparseEnum) input.ReadEnum();
@@ -4169,7 +4201,9 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 10: {
             Data = input.ReadString();
@@ -4290,7 +4324,9 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 10: {
             data_.AddEntriesFrom(input, _repeated_data_codec);
@@ -4419,7 +4455,9 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 10: {
             Data = input.ReadBytes();
@@ -4548,7 +4586,9 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 10: {
             Data = input.ReadBytes();
@@ -4680,7 +4720,9 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 8: {
             Data = input.ReadInt32();
@@ -4809,7 +4851,9 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 8: {
             Data = input.ReadUInt32();
@@ -4938,7 +4982,9 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 8: {
             Data = input.ReadInt64();
@@ -5067,7 +5113,9 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 8: {
             Data = input.ReadUInt64();
@@ -5196,7 +5244,9 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 8: {
             Data = input.ReadBool();
@@ -5413,7 +5463,9 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 8: {
             FooInt = input.ReadInt32();
@@ -5755,7 +5807,9 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 722:
           case 720: {
@@ -6154,7 +6208,9 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 722:
           case 720: {
@@ -6435,7 +6491,9 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 98:
           case 101: {
@@ -6593,7 +6651,9 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 10: {
             A = input.ReadString();
@@ -6701,7 +6761,9 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
         }
       }
@@ -6802,7 +6864,9 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
         }
       }
@@ -6903,7 +6967,9 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
         }
       }
@@ -7004,7 +7070,9 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
         }
       }
@@ -7105,7 +7173,9 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
         }
       }
@@ -7206,7 +7276,9 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
         }
       }
@@ -7307,7 +7379,9 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
         }
       }
@@ -7438,7 +7512,9 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 10: {
             Text = input.ReadString();
@@ -7585,7 +7661,9 @@ namespace Google.Protobuf.TestProtos {
           while ((tag = input.ReadTag()) != 0) {
             switch(tag) {
               default:
-                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+                if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+                  return;
+                }
                 break;
               case 10: {
                 NestedText = input.ReadString();

+ 12 - 4
csharp/src/Google.Protobuf.Test/TestProtos/UnittestWellKnownTypes.cs

@@ -788,7 +788,9 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 10: {
             if (anyField_ == null) {
@@ -1316,7 +1318,9 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 10: {
             anyField_.AddEntriesFrom(input, _repeated_anyField_codec);
@@ -2027,7 +2031,9 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 10: {
             global::Google.Protobuf.WellKnownTypes.Any subBuilder = new global::Google.Protobuf.WellKnownTypes.Any();
@@ -2538,7 +2544,9 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 10: {
             anyField_.AddEntriesFrom(input, _map_anyField_codec);

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


+ 19 - 1
csharp/src/Google.Protobuf/CodedInputStream.cs

@@ -373,7 +373,7 @@ namespace Google.Protobuf
                 if (IsAtEnd)
                 {
                     lastTag = 0;
-                    return 0; // This is the only case in which we return 0.
+                    return 0;
                 }
 
                 lastTag = ReadRawVarint32();
@@ -383,6 +383,10 @@ namespace Google.Protobuf
                 // If we actually read a tag with a field of 0, that's not a valid tag.
                 throw InvalidProtocolBufferException.InvalidTag();
             }
+            if (ReachedLimit)
+            {
+                return 0;
+            }
             return lastTag;
         }
 
@@ -591,6 +595,20 @@ namespace Google.Protobuf
             PopLimit(oldLimit);
         }
 
+        /// <summary>
+        /// Reads an embedded group field from the stream.
+        /// </summary>
+        public void ReadGroup(IMessage builder)
+        {
+            if (recursionDepth >= recursionLimit)
+            {
+                throw InvalidProtocolBufferException.RecursionLimitExceeded();
+            }
+            ++recursionDepth;
+            builder.MergeFrom(this);
+            --recursionDepth;
+        }
+
         /// <summary>
         /// Reads a bytes field value from the stream.
         /// </summary>   

+ 9 - 0
csharp/src/Google.Protobuf/CodedOutputStream.cs

@@ -303,6 +303,15 @@ namespace Google.Protobuf
             value.WriteTo(this);
         }
 
+        /// <summary>
+        /// Writes a group, without a tag, to the stream.
+        /// </summary>
+        /// <param name="value">The value to write</param>
+        public void WriteGroup(IMessage value)
+        {
+            value.WriteTo(this);
+        }
+
         /// <summary>
         /// Write a byte string, without a tag, to the stream.
         /// The data is length-prefixed.

+ 4 - 0
csharp/src/Google.Protobuf/Collections/RepeatedField.cs

@@ -208,6 +208,10 @@ namespace Google.Protobuf.Collections
                 {
                     output.WriteTag(tag);
                     writer(output, array[i]);
+                    if (codec.EndTag != 0)
+                    {
+                        output.WriteTag(codec.EndTag);
+                    }
                 }
             }
         }

+ 30 - 3
csharp/src/Google.Protobuf/FieldCodec.cs

@@ -225,6 +225,19 @@ namespace Google.Protobuf
                 (output, value) => output.WriteMessage(value), message => CodedOutputStream.ComputeMessageSize(message), tag);
         }
 
+        /// <summary>
+        /// Retrieves a codec suitable for a group field with the given tag.
+        /// </summary>
+        /// <param name="startTag">The start group tag.</param>
+        /// <param name="endTag">The end group tag.</param>
+        /// <param name="parser">A parser to use for the group message type.</param>
+        /// <returns>A codec for given tag</returns>
+        public static FieldCodec<T> ForGroup<T>(uint startTag, uint endTag, MessageParser<T> parser) where T : IMessage<T>
+        {
+            return new FieldCodec<T>(input => { T message = parser.CreateTemplate(); input.ReadGroup(message); return message; },
+                (output, value) => output.WriteGroup(value), message => CodedOutputStream.ComputeGroupSize(message), startTag, endTag);
+        }
+
         /// <summary>
         /// Creates a codec for a wrapper type of a class - which must be string or ByteString.
         /// </summary>
@@ -235,7 +248,7 @@ namespace Google.Protobuf
                 input => WrapperCodecs.Read<T>(input, nestedCodec),
                 (output, value) => WrapperCodecs.Write<T>(output, value, nestedCodec),
                 value => WrapperCodecs.CalculateSize<T>(value, nestedCodec),
-                tag,
+                tag, 0,
                 null); // Default value for the wrapper
         }
 
@@ -250,7 +263,7 @@ namespace Google.Protobuf
                 input => WrapperCodecs.Read<T>(input, nestedCodec),
                 (output, value) => WrapperCodecs.Write<T>(output, value.Value, nestedCodec),
                 value => value == null ? 0 : WrapperCodecs.CalculateSize<T>(value.Value, nestedCodec),
-                tag,
+                tag, 0,
                 null); // Default value for the wrapper
         }
 
@@ -399,6 +412,14 @@ namespace Google.Protobuf
         /// </value>
         internal uint Tag { get; }
 
+        /// <summary>
+        /// Gets the end tag of the codec or 0 if there is no end tag
+        /// </summary>
+        /// <value>
+        /// The end tag of the codec.
+        /// </value>
+        internal uint EndTag { get; }
+
         /// <summary>
         /// Default value for this codec. Usually the same for every instance of the same type, but
         /// for string/ByteString wrapper fields the codec's default value is null, whereas for
@@ -424,7 +445,8 @@ namespace Google.Protobuf
             Func<CodedInputStream, T> reader,
             Action<CodedOutputStream, T> writer,
             Func<T, int> sizeCalculator,
-            uint tag) : this(reader, writer, sizeCalculator, tag, DefaultDefault)
+            uint tag,
+            uint endTag = 0) : this(reader, writer, sizeCalculator, tag, endTag, DefaultDefault)
         {
         }
 
@@ -433,6 +455,7 @@ namespace Google.Protobuf
             Action<CodedOutputStream, T> writer,
             Func<T, int> sizeCalculator,
             uint tag,
+            uint endTag,
             T defaultValue)
         {
             ValueReader = reader;
@@ -455,6 +478,10 @@ namespace Google.Protobuf
             {
                 output.WriteTag(Tag);
                 ValueWriter(output, value);
+                if (EndTag != 0)
+                {
+                    output.WriteTag(EndTag);
+                }
             }
         }
 

+ 57 - 19
csharp/src/Google.Protobuf/Reflection/Descriptor.cs

@@ -302,7 +302,9 @@ namespace Google.Protobuf.Reflection {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 10: {
             file_.AddEntriesFrom(input, _repeated_file_codec);
@@ -733,7 +735,9 @@ namespace Google.Protobuf.Reflection {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 10: {
             Name = input.ReadString();
@@ -1098,7 +1102,9 @@ namespace Google.Protobuf.Reflection {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 10: {
             Name = input.ReadString();
@@ -1357,7 +1363,9 @@ namespace Google.Protobuf.Reflection {
           while ((tag = input.ReadTag()) != 0) {
             switch(tag) {
               default:
-                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+                if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+                  return;
+                }
                 break;
               case 8: {
                 Start = input.ReadInt32();
@@ -1560,7 +1568,9 @@ namespace Google.Protobuf.Reflection {
           while ((tag = input.ReadTag()) != 0) {
             switch(tag) {
               default:
-                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+                if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+                  return;
+                }
                 break;
               case 8: {
                 Start = input.ReadInt32();
@@ -1693,7 +1703,9 @@ namespace Google.Protobuf.Reflection {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 7994: {
             uninterpretedOption_.AddEntriesFrom(input, _repeated_uninterpretedOption_codec);
@@ -2200,7 +2212,9 @@ namespace Google.Protobuf.Reflection {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 10: {
             Name = input.ReadString();
@@ -2487,7 +2501,9 @@ namespace Google.Protobuf.Reflection {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 10: {
             Name = input.ReadString();
@@ -2732,7 +2748,9 @@ namespace Google.Protobuf.Reflection {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 10: {
             Name = input.ReadString();
@@ -2948,7 +2966,9 @@ namespace Google.Protobuf.Reflection {
           while ((tag = input.ReadTag()) != 0) {
             switch(tag) {
               default:
-                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+                if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+                  return;
+                }
                 break;
               case 8: {
                 Start = input.ReadInt32();
@@ -3177,7 +3197,9 @@ namespace Google.Protobuf.Reflection {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 10: {
             Name = input.ReadString();
@@ -3385,7 +3407,9 @@ namespace Google.Protobuf.Reflection {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 10: {
             Name = input.ReadString();
@@ -3735,7 +3759,9 @@ namespace Google.Protobuf.Reflection {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 10: {
             Name = input.ReadString();
@@ -6923,7 +6949,9 @@ namespace Google.Protobuf.Reflection {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 18: {
             name_.AddEntriesFrom(input, _repeated_name_codec);
@@ -7136,7 +7164,9 @@ namespace Google.Protobuf.Reflection {
           while ((tag = input.ReadTag()) != 0) {
             switch(tag) {
               default:
-                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+                if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+                  return;
+                }
                 break;
               case 10: {
                 NamePart_ = input.ReadString();
@@ -7315,7 +7345,9 @@ namespace Google.Protobuf.Reflection {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 10: {
             location_.AddEntriesFrom(input, _repeated_location_codec);
@@ -7623,7 +7655,9 @@ namespace Google.Protobuf.Reflection {
           while ((tag = input.ReadTag()) != 0) {
             switch(tag) {
               default:
-                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+                if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+                  return;
+                }
                 break;
               case 10:
               case 8: {
@@ -7776,7 +7810,9 @@ namespace Google.Protobuf.Reflection {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 10: {
             annotation_.AddEntriesFrom(input, _repeated_annotation_codec);
@@ -8027,7 +8063,9 @@ namespace Google.Protobuf.Reflection {
           while ((tag = input.ReadTag()) != 0) {
             switch(tag) {
               default:
-                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+                if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+                  return;
+                }
                 break;
               case 10:
               case 8: {

+ 28 - 1
csharp/src/Google.Protobuf/UnknownField.cs

@@ -55,6 +55,7 @@ namespace Google.Protobuf
         private List<uint> fixed32List;
         private List<ulong> fixed64List;
         private List<ByteString> lengthDelimitedList;
+        private List<UnknownFieldSet> groupList;
 
         /// <summary>
         /// Creates a new UnknownField.
@@ -77,7 +78,8 @@ namespace Google.Protobuf
                    && Lists.Equals(varintList, otherField.varintList)
                    && Lists.Equals(fixed32List, otherField.fixed32List)
                    && Lists.Equals(fixed64List, otherField.fixed64List)
-                   && Lists.Equals(lengthDelimitedList, otherField.lengthDelimitedList);
+                   && Lists.Equals(lengthDelimitedList, otherField.lengthDelimitedList)
+                   && Lists.Equals(groupList, otherField.groupList);
         }
 
         /// <summary>
@@ -90,6 +92,7 @@ namespace Google.Protobuf
             hash = hash * 47 + Lists.GetHashCode(fixed32List);
             hash = hash * 47 + Lists.GetHashCode(fixed64List);
             hash = hash * 47 + Lists.GetHashCode(lengthDelimitedList);
+            hash = hash * 47 + Lists.GetHashCode(groupList);
             return hash;
         }
 
@@ -133,6 +136,15 @@ namespace Google.Protobuf
                     output.WriteBytes(value);
                 }
             }
+            if (groupList != null)
+            {
+                foreach (UnknownFieldSet value in groupList)
+                {
+                    output.WriteTag(fieldNumber, WireFormat.WireType.StartGroup);
+                    value.WriteTo(output);
+                    output.WriteTag(fieldNumber, WireFormat.WireType.EndGroup);
+                }
+            }
         }
 
         /// <summary>
@@ -168,6 +180,14 @@ namespace Google.Protobuf
                     result += CodedOutputStream.ComputeBytesSize(value);
                 }
             }
+            if (groupList != null)
+            {
+                result += CodedOutputStream.ComputeTagSize(fieldNumber) * 2 * groupList.Count;
+                foreach (UnknownFieldSet value in groupList)
+                {
+                    result += value.CalculateSize();
+                }
+            }
             return result;
         }
 
@@ -182,6 +202,7 @@ namespace Google.Protobuf
             fixed32List = AddAll(fixed32List, other.fixed32List);
             fixed64List = AddAll(fixed64List, other.fixed64List);
             lengthDelimitedList = AddAll(lengthDelimitedList, other.lengthDelimitedList);
+            groupList = AddAll(groupList, other.groupList);
             return this;
         }
 
@@ -245,6 +266,12 @@ namespace Google.Protobuf
             return this;
         }
 
+        internal UnknownField AddGroup(UnknownFieldSet value) 
+        {
+            groupList = Add(groupList, value);
+            return this;
+        }
+
         /// <summary>
         /// Adds <paramref name="value"/> to the <paramref name="list"/>, creating
         /// a new list if <paramref name="list"/> is null. The list is returned - either

+ 41 - 9
csharp/src/Google.Protobuf/UnknownFieldSet.cs

@@ -183,7 +183,7 @@ namespace Google.Protobuf
         /// </summary>
         /// <param name="input">The coded input stream containing the field</param>
         /// <returns>false if the tag is an "end group" tag, true otherwise</returns>
-        private void MergeFieldFrom(CodedInputStream input)
+        private bool MergeFieldFrom(CodedInputStream input)
         {
             uint tag = input.LastTag;
             int number = WireFormat.GetTagFieldNumber(tag);
@@ -193,34 +193,40 @@ namespace Google.Protobuf
                     {
                         ulong uint64 = input.ReadUInt64();
                         GetOrAddField(number).AddVarint(uint64);
-                        return;
+                        return true;
                     }
                 case WireFormat.WireType.Fixed32:
                     {
                         uint uint32 = input.ReadFixed32();
                         GetOrAddField(number).AddFixed32(uint32);
-                        return;
+                        return true;
                     }
                 case WireFormat.WireType.Fixed64:
                     {
                         ulong uint64 = input.ReadFixed64();
                         GetOrAddField(number).AddFixed64(uint64);
-                        return;
+                        return true;
                     }
                 case WireFormat.WireType.LengthDelimited:
                     {
                         ByteString bytes = input.ReadBytes();
                         GetOrAddField(number).AddLengthDelimited(bytes);
-                        return;
+                        return true;
                     }
                 case WireFormat.WireType.StartGroup:
                     {
-                        input.SkipGroup(tag);
-                        return;
+                        uint endTag = WireFormat.MakeTag(number, WireFormat.WireType.EndGroup);
+                        UnknownFieldSet set = new UnknownFieldSet();
+                        while (input.ReadTag() != endTag)
+                        {
+                            set.MergeFieldFrom(input);
+                        }
+                        GetOrAddField(number).AddGroup(set);
+                        return true;
                     }
                 case WireFormat.WireType.EndGroup:
                     {
-                        throw new InvalidProtocolBufferException("Merge an unknown field of end-group tag, indicating that the corresponding start-group was missing.");
+                        return false;
                     }
                 default:
                     throw new InvalidOperationException("Wire Type is invalid.");
@@ -248,8 +254,34 @@ namespace Google.Protobuf
             {
                 unknownFields = new UnknownFieldSet();
             }
-            unknownFields.MergeFieldFrom(input);
+            if (!unknownFields.MergeFieldFrom(input))
+            {
+                throw new InvalidProtocolBufferException("Merge an unknown field of end-group tag, indicating that the corresponding start-group was missing."); // match the old code-gen
+            }
             return unknownFields;
+        }
+
+        /// <summary>
+        /// Create a new UnknownFieldSet if unknownFields is null.
+        /// Parse a single field from <paramref name="input"/> and merge it
+        /// into unknownFields. If <paramref name="input"/> is configured to discard unknown fields,
+        /// <paramref name="unknownFields"/> will be returned as-is and the field will be skipped.
+        /// </summary>
+        /// <param name="unknownFields">The UnknownFieldSet which need to be merged</param>
+        /// <param name="input">The coded input stream containing the field</param>
+        /// <returns>The merged UnknownFieldSet</returns>
+        public static bool MergeFieldFrom(ref UnknownFieldSet unknownFields, CodedInputStream input)
+        {
+            if (input.DiscardUnknownFields)
+            {
+                input.SkipLastField();
+                return true;
+            }
+            if (unknownFields == null)
+            {
+                unknownFields = new UnknownFieldSet();
+            }
+            return unknownFields.MergeFieldFrom(input);
         }
 
         /// <summary>

+ 3 - 1
csharp/src/Google.Protobuf/WellKnownTypes/Any.cs

@@ -292,7 +292,9 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 10: {
             TypeUrl = input.ReadString();

+ 9 - 3
csharp/src/Google.Protobuf/WellKnownTypes/Api.cs

@@ -345,7 +345,9 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 10: {
             Name = input.ReadString();
@@ -661,7 +663,9 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 10: {
             Name = input.ReadString();
@@ -925,7 +929,9 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 10: {
             Name = input.ReadString();

+ 3 - 1
csharp/src/Google.Protobuf/WellKnownTypes/Duration.cs

@@ -254,7 +254,9 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 8: {
             Seconds = input.ReadInt64();

+ 3 - 1
csharp/src/Google.Protobuf/WellKnownTypes/Empty.cs

@@ -143,7 +143,9 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
         }
       }

+ 3 - 1
csharp/src/Google.Protobuf/WellKnownTypes/FieldMask.cs

@@ -352,7 +352,9 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 10: {
             paths_.AddEntriesFrom(input, _repeated_paths_codec);

+ 3 - 1
csharp/src/Google.Protobuf/WellKnownTypes/SourceContext.cs

@@ -165,7 +165,9 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 10: {
             FileName = input.ReadString();

+ 9 - 3
csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs

@@ -189,7 +189,9 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 10: {
             fields_.AddEntriesFrom(input, _map_fields_codec);
@@ -513,7 +515,9 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 8: {
             kind_ = input.ReadEnum();
@@ -673,7 +677,9 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 10: {
             values_.AddEntriesFrom(input, _repeated_values_codec);

+ 3 - 1
csharp/src/Google.Protobuf/WellKnownTypes/Timestamp.cs

@@ -273,7 +273,9 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 8: {
             Seconds = input.ReadInt64();

+ 15 - 5
csharp/src/Google.Protobuf/WellKnownTypes/Type.cs

@@ -328,7 +328,9 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 10: {
             Name = input.ReadString();
@@ -723,7 +725,9 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 8: {
             Kind = (global::Google.Protobuf.WellKnownTypes.Field.Types.Kind) input.ReadEnum();
@@ -1100,7 +1104,9 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 10: {
             Name = input.ReadString();
@@ -1300,7 +1306,9 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 10: {
             Name = input.ReadString();
@@ -1480,7 +1488,9 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 10: {
             Name = input.ReadString();

+ 27 - 9
csharp/src/Google.Protobuf/WellKnownTypes/Wrappers.cs

@@ -177,7 +177,9 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 9: {
             Value = input.ReadDouble();
@@ -314,7 +316,9 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 13: {
             Value = input.ReadFloat();
@@ -451,7 +455,9 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 8: {
             Value = input.ReadInt64();
@@ -588,7 +594,9 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 8: {
             Value = input.ReadUInt64();
@@ -725,7 +733,9 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 8: {
             Value = input.ReadInt32();
@@ -862,7 +872,9 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 8: {
             Value = input.ReadUInt32();
@@ -999,7 +1011,9 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 8: {
             Value = input.ReadBool();
@@ -1136,7 +1150,9 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 10: {
             Value = input.ReadString();
@@ -1273,7 +1289,9 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {
+              return;
+            }
             break;
           case 10: {
             Value = input.ReadBytes();

+ 1 - 0
docs/third_party.md

@@ -170,3 +170,4 @@ There are miscellaneous other things you may find useful as a Protocol Buffers d
 * [Make protoc plugins in NodeJS](https://github.com/konsumer/node-protoc-plugin)
 * [ProfaneDB - A Protocol Buffers database](https://profanedb.gitlab.io)
 * [Protocol Buffer property-based testing utility and example message generator (Python / Hypothesis)](https://github.com/CurataEng/hypothesis-protobuf)
+* [Protolock - CLI utility to prevent backward-incompatible changes to .proto files](https://github.com/nilslice/protolock) 

+ 13 - 0
examples/Makefile

@@ -5,6 +5,7 @@
 all: cpp java python
 
 cpp:    add_person_cpp    list_people_cpp
+dart:   add_person_dart   list_people_dart
 go:     add_person_go     list_people_go
 gotest: add_person_gotest list_people_gotest
 java:   add_person_java   list_people_java
@@ -16,6 +17,8 @@ clean:
 	rm -f protoc_middleman addressbook.pb.cc addressbook.pb.h addressbook_pb2.py com/example/tutorial/AddressBookProtos.java
 	rm -f *.pyc
 	rm -f protoc_middleman_go tutorial/*.pb.go add_person_go list_people_go
+	rm -f protoc_middleman_dart dart_tutorial/*.pb*.dart
+	rmdir dart_tutorial 2>/dev/null || true
 	rmdir tutorial 2>/dev/null || true
 	rmdir com/example/tutorial 2>/dev/null || true
 	rmdir com/example 2>/dev/null || true
@@ -30,6 +33,12 @@ protoc_middleman_go: addressbook.proto
 	protoc $$PROTO_PATH --go_out=tutorial addressbook.proto
 	@touch protoc_middleman_go
 
+protoc_middleman_dart: addressbook.proto
+	mkdir -p dart_tutorial # make directory for the dart package
+	protoc -I ../src/:. --dart_out=dart_tutorial addressbook.proto ../src/google/protobuf/timestamp.proto
+	pub get
+	@touch protoc_middleman_dart
+
 add_person_cpp: add_person.cc protoc_middleman
 	pkg-config --cflags protobuf  # fails if protobuf is not installed
 	c++ add_person.cc addressbook.pb.cc -o add_person_cpp `pkg-config --cflags --libs protobuf`
@@ -38,6 +47,10 @@ list_people_cpp: list_people.cc protoc_middleman
 	pkg-config --cflags protobuf  # fails if protobuf is not installed
 	c++ list_people.cc addressbook.pb.cc -o list_people_cpp `pkg-config --cflags --libs protobuf`
 
+add_person_dart: add_person.dart protoc_middleman_dart
+
+list_people_dart: list_people.dart protoc_middleman_dart
+
 add_person_go: add_person.go protoc_middleman_go
 	go build -o add_person_go add_person.go
 

+ 21 - 1
examples/README.md

@@ -119,6 +119,26 @@ is created if it does not exist.  To view the data, run:
 
     ./list_people_go addressbook.data
 
-Observe that the C++, Python, and Java examples in this directory run in a
+Observe that the C++, Python, Java, and Dart examples in this directory run in a
 similar way and can view/modify files created by the Go example and vice
 versa.
+
+### Dart
+
+First, follow the instructions in [../README.md](../README.md) to install the Protocol Buffer Compiler (protoc).
+
+Then, install the Dart Protocol Buffer plugin as described [here](https://github.com/dart-lang/dart-protoc-plugin#how-to-build-and-use).
+Note, the executable `bin/protoc-gen-dart` must be in your `PATH` for `protoc` to find it.
+
+Build the Dart samples in this directory with `make dart`.
+
+To run the examples:
+
+```sh
+$ dart add_person.dart addessbook.data
+$ dart list_people.dart addressbook.data
+```
+
+The two programs take a protocol buffer encoded file as their parameter.
+The first can be used to add a person to the file. The file is created
+if it does not exist. The second displays the data in the file.

+ 70 - 0
examples/add_person.dart

@@ -0,0 +1,70 @@
+import 'dart:io';
+
+import 'dart_tutorial/addressbook.pb.dart';
+
+// This function fills in a Person message based on user input.
+Person promtForAddress() {
+  Person person = Person();
+
+  print('Enter person ID: ');
+  String input = stdin.readLineSync();
+  person.id = int.parse(input);
+
+  print('Enter name');
+  person.name = stdin.readLineSync();
+
+  print('Enter email address (blank for none) : ');
+  String email = stdin.readLineSync();
+  if (email.isNotEmpty) {
+    person.email = email;
+  }
+
+  while (true) {
+    print('Enter a phone number (or leave blank to finish): ');
+    String number = stdin.readLineSync();
+    if (number.isEmpty) break;
+
+    Person_PhoneNumber phoneNumber = Person_PhoneNumber();
+
+    phoneNumber.number = number;
+    print('Is this a mobile, home, or work phone? ');
+
+    String type = stdin.readLineSync();
+    switch (type) {
+      case 'mobile':
+        phoneNumber.type = Person_PhoneType.MOBILE;
+        break;
+      case 'home':
+        phoneNumber.type = Person_PhoneType.HOME;
+        break;
+      case 'work':
+        phoneNumber.type = Person_PhoneType.WORK;
+        break;
+      default:
+        print('Unknown phone type.  Using default.');
+    }
+    person.phones.add(phoneNumber);
+  }
+
+  return person;
+}
+
+// Reads the entire address book from a file, adds one person based
+// on user input, then writes it back out to the same file.
+main(List<String> arguments) {
+  if (arguments.length != 1) {
+    print('Usage: add_person ADDRESS_BOOK_FILE');
+    exit(-1);
+  }
+
+  File file = File(arguments.first);
+  AddressBook addressBook;
+  if (!file.existsSync()) {
+    print('File not found. Creating new file.');
+    addressBook = AddressBook();
+  } else {
+    addressBook = AddressBook.fromBuffer(file.readAsBytesSync());
+  }
+  addressBook.people.add(promtForAddress());
+  file.writeAsBytes(addressBook.writeToBuffer());
+}

+ 47 - 0
examples/list_people.dart

@@ -0,0 +1,47 @@
+import 'dart:io';
+
+import 'dart_tutorial/addressbook.pb.dart';
+import 'dart_tutorial/addressbook.pbenum.dart';
+
+// Iterates though all people in the AddressBook and prints info about them.
+void printAddressBook(AddressBook addressBook) {
+  for (Person person in addressBook.people) {
+    print('Person ID: ${person.id}');
+    print('  Name: ${person.name}');
+    if (person.hasEmail()) {
+      print('  E-mail address:${person.email}');
+    }
+
+    for (Person_PhoneNumber phoneNumber in person.phones) {
+      switch (phoneNumber.type) {
+        case Person_PhoneType.MOBILE:
+          print('   Mobile phone #: ');
+          break;
+        case Person_PhoneType.HOME:
+          print('   Home phone #: ');
+          break;
+        case Person_PhoneType.WORK:
+          print('   Work phone #: ');
+          break;
+        default:
+          print('   Unknown phone #: ');
+          break;
+      }
+      print(phoneNumber.number);
+    }
+  }
+}
+
+// Reads the entire address book from a file and prints all
+// the information inside.
+main(List<String> arguments) {
+  if (arguments.length != 1) {
+    print('Usage: list_person ADDRESS_BOOK_FILE');
+    exit(-1);
+  }
+
+  // Read the existing address book.
+  File file = new File(arguments.first);
+  AddressBook addressBook = new AddressBook.fromBuffer(file.readAsBytesSync());
+  printAddressBook(addressBook);
+}

+ 5 - 0
examples/pubspec.yaml

@@ -0,0 +1,5 @@
+name: addressbook
+description: dartlang.org example code.
+
+dependencies:
+  protobuf:

+ 6 - 26
objectivec/DevTools/full_mac_build.sh

@@ -239,27 +239,11 @@ if [[ "${DO_XCODE_IOS_TESTS}" == "yes" ]] ; then
   # just pick a mix of OS Versions and 32/64 bit.
   # NOTE: Different Xcode have different simulated hardware/os support.
   case "${XCODE_VERSION}" in
-    6.* )
-      echo "ERROR: Xcode 6.3/6.4 no longer supported for building, please use 8.0 or higher." 1>&2
-      exit 10
-      ;;
-    7.* )
-      echo "ERROR: Xcode 7.x no longer supported for building, please use 8.0 or higher." 1>&2
+    [6-8].* )
+      echo "ERROR: The unittests include Swift code that is now Swift 4.0." 1>&2
+      echo "ERROR: Xcode 9.0 or higher is required to build the test suite, but the library works with Xcode 7.x." 1>&2
       exit 11
       ;;
-    8.0* )
-      # The 8.* device seem to hang and never start under Xcode 8.
-      XCODEBUILD_TEST_BASE_IOS+=(
-          -destination "platform=iOS Simulator,name=iPhone 4s,OS=9.0" # 32bit
-          -destination "platform=iOS Simulator,name=iPhone 7,OS=10.0" # 64bit
-      )
-      ;;
-    8.[1-3]* )
-      XCODEBUILD_TEST_BASE_IOS+=(
-          -destination "platform=iOS Simulator,name=iPhone 4s,OS=8.1" # 32bit
-          -destination "platform=iOS Simulator,name=iPhone 7,OS=latest" # 64bit
-      )
-      ;;
     9.[0-2]* )
       XCODEBUILD_TEST_BASE_IOS+=(
           -destination "platform=iOS Simulator,name=iPhone 4s,OS=8.1" # 32bit
@@ -317,13 +301,9 @@ if [[ "${DO_XCODE_OSX_TESTS}" == "yes" ]] ; then
     XCODEBUILD_TEST_BASE_OSX+=( -quiet )
   fi
   case "${XCODE_VERSION}" in
-    6.* )
-      echo "ERROR: Xcode 6.3/6.4 no longer supported for building, please use 8.0 or higher." 1>&2
-      exit 10
-      ;;
-    7.* )
-      echo "ERROR: The unittests include Swift code that is now Swift 3.0." 1>&2
-      echo "ERROR: Xcode 8.0 or higher is required to build the test suite, but the library works with Xcode 7.x." 1>&2
+    [6-8].* )
+      echo "ERROR: The unittests include Swift code that is now Swift 4.0." 1>&2
+      echo "ERROR: Xcode 9.0 or higher is required to build the test suite, but the library works with Xcode 7.x." 1>&2
       exit 11
       ;;
   esac

+ 5 - 0
objectivec/GPBDescriptor.m

@@ -819,6 +819,7 @@ uint32_t GPBFieldAlternateTag(GPBFieldDescriptor *self) {
       return;
     }
     uint32_t *offsets = malloc(valueCount_ * sizeof(uint32_t));
+    if (!offsets) return;
     const char *scan = valueNames_;
     for (uint32_t i = 0; i < valueCount_; ++i) {
       offsets[i] = (uint32_t)(scan - valueNames_);
@@ -851,6 +852,7 @@ uint32_t GPBFieldAlternateTag(GPBFieldDescriptor *self) {
   nameAsCStr += prefixLen;
 
   if (nameOffsets_ == NULL) [self calcValueNameOffsets];
+  if (nameOffsets_ == NULL) return NO;
 
   // Find it.
   for (uint32_t i = 0; i < valueCount_; ++i) {
@@ -867,6 +869,7 @@ uint32_t GPBFieldAlternateTag(GPBFieldDescriptor *self) {
 
 - (BOOL)getValue:(int32_t *)outValue forEnumTextFormatName:(NSString *)textFormatName {
     if (nameOffsets_ == NULL) [self calcValueNameOffsets];
+    if (nameOffsets_ == NULL) return NO;
 
     for (uint32_t i = 0; i < valueCount_; ++i) {
         int32_t value = values_[i];
@@ -905,6 +908,7 @@ uint32_t GPBFieldAlternateTag(GPBFieldDescriptor *self) {
 
 - (NSString *)getEnumNameForIndex:(uint32_t)index {
   if (nameOffsets_ == NULL) [self calcValueNameOffsets];
+  if (nameOffsets_ == NULL) return nil;
 
   if (index >= valueCount_) {
     return nil;
@@ -916,6 +920,7 @@ uint32_t GPBFieldAlternateTag(GPBFieldDescriptor *self) {
 
 - (NSString *)getEnumTextFormatNameForIndex:(uint32_t)index {
   if (nameOffsets_ == NULL) [self calcValueNameOffsets];
+  if (nameOffsets_ == NULL) return nil;
 
   if (index >= valueCount_) {
     return nil;

+ 3 - 3
objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj

@@ -640,7 +640,7 @@
 				LastUpgradeCheck = 0930;
 				TargetAttributes = {
 					8BBEA4A5147C727100C4ADB7 = {
-						LastSwiftMigration = 0800;
+						LastSwiftMigration = 0940;
 						TestTargetID = 8B9A5EA41831993600A9D33B;
 					};
 					F45BBC141B0CE3C6002D064D = {
@@ -852,7 +852,7 @@
 				PRODUCT_NAME = UnitTests;
 				SWIFT_OBJC_BRIDGING_HEADER = "Tests/UnitTests-Bridging-Header.h";
 				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
-				SWIFT_VERSION = 3.0;
+				SWIFT_VERSION = 4.0;
 				WARNING_CFLAGS = (
 					"$(inherited)",
 					"-Wno-documentation-unknown-command",
@@ -878,7 +878,7 @@
 				PRODUCT_BUNDLE_IDENTIFIER = "com.yourcompany.${PRODUCT_NAME:identifier}";
 				PRODUCT_NAME = UnitTests;
 				SWIFT_OBJC_BRIDGING_HEADER = "Tests/UnitTests-Bridging-Header.h";
-				SWIFT_VERSION = 3.0;
+				SWIFT_VERSION = 4.0;
 				WARNING_CFLAGS = (
 					"$(inherited)",
 					"-Wno-documentation-unknown-command",

+ 3 - 3
objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj

@@ -647,7 +647,7 @@
 				LastUpgradeCheck = 0930;
 				TargetAttributes = {
 					8BBEA4A5147C727100C4ADB7 = {
-						LastSwiftMigration = 0800;
+						LastSwiftMigration = 0940;
 						TestTargetID = 8B9A5EA41831993600A9D33B;
 					};
 					F45BBC0E1B0CDB50002D064D = {
@@ -866,7 +866,7 @@
 				PRODUCT_NAME = UnitTests;
 				SWIFT_OBJC_BRIDGING_HEADER = "Tests/UnitTests-Bridging-Header.h";
 				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
-				SWIFT_VERSION = 3.0;
+				SWIFT_VERSION = 4.0;
 				TARGETED_DEVICE_FAMILY = "1,2";
 				WARNING_CFLAGS = (
 					"$(inherited)",
@@ -900,7 +900,7 @@
 				OTHER_LDFLAGS = "-ObjC";
 				PRODUCT_NAME = UnitTests;
 				SWIFT_OBJC_BRIDGING_HEADER = "Tests/UnitTests-Bridging-Header.h";
-				SWIFT_VERSION = 3.0;
+				SWIFT_VERSION = 4.0;
 				TARGETED_DEVICE_FAMILY = "1,2";
 				WARNING_CFLAGS = (
 					"$(inherited)",

+ 45 - 0
objectivec/Tests/GPBMessageTests.m

@@ -1980,6 +1980,51 @@
                  EnumTestMsg_MyEnum_NegTwo);
 }
 
+- (void)testReservedWordNaming {
+  // objectivec_helpers.cc has some special handing to make sure that
+  // some "reserved" objc names get renamed in a way so they
+  // don't conflict.
+  //
+  // This "test" confirms that the expected names are generated,
+  // otherwise the test itself will fail to compile.
+  self_Class *msg = [self_Class message];
+
+  // Some ObjC/C/C++ keywords.
+  msg.className_p = msg.hasClassName_p;
+  msg.cmd = msg.hasCmd;
+  msg.nullable_p = msg.hasNullable_p;
+  msg.typeof_p = msg.hasTypeof_p;
+  msg.instancetype_p = msg.hasInstancetype_p;
+  msg.nil_p = msg.hasNil_p;
+  msg.instancetype_p = msg.hasInstancetype_p;
+  msg.public_p = msg.hasPublic_p;
+
+  // Some that would override NSObject methods
+  msg.camltype = msg.hasCamltype;
+  msg.isNsdictionary = msg.hasIsNsdictionary;
+  msg.dealloc_p = msg.hasDealloc_p;
+  msg.zone_p = msg.hasZone_p;
+  msg.accessibilityLabel_p = msg.hasAccessibilityLabel_p;
+
+  // Some that we shouldn't need to handle.
+  msg.atomic = msg.hasAtomic;
+  msg.nonatomic = msg.hasNonatomic;
+  msg.strong = msg.hasStrong;
+  msg.nullResettable = msg.hasNullResettable;
+
+  // Some that would override GPBMessage methods
+  msg.clear_p = msg.hasClear_p;
+  msg.data_p = msg.hasData_p;
+
+  // Some MacTypes
+  msg.fixed = msg.hasFixed;
+  msg.style = msg.hasStyle;
+
+  // Some C Identifiers
+  msg.generic = msg.hasGeneric;
+  msg.block = msg.hasBlock;
+}
+
 - (void)testOneBasedEnumHolder {
   // Test case for https://github.com/protocolbuffers/protobuf/issues/1453
   // Message with no explicit defaults, but a non zero default for an enum.

+ 86 - 34
objectivec/Tests/unittest_objc.proto

@@ -103,37 +103,89 @@ message self {
   }
 
   // Singular
-  optional   bool id                =  1;
-  optional   bool _cmd              =  2;
-  optional   bool in                =  3;
-  optional   bool out               =  4;
-  optional   bool inout             =  5;
-  optional   bool bycopy            =  6;
-  optional   bool byref             =  7;
-  optional   bool oneway            =  8;
-  optional   bool dealloc           =  9;
-  optional   bool zone              = 10;
-  optional   bool isProxy           = 11;
-  optional   bool copy              = 12;
-  optional   bool readonly          = 13;
-  optional   bool default           = 14;
-  optional   bool assign            = 15;
-  optional   bool getter            = 16;
-  optional   bool setter            = 17;
-  optional   bool weak              = 18;
-  optional   bool public            = 19;
-  optional   bool case              = 20;
-
-  optional   autorelease SubEnum    = 25;
-
- optional group New = 50 {
-   optional string copy = 51;
- }
-  optional group MutableCopy = 60 {
-    optional int32 extensionRegistry = 61;
+  // Objective C Keywords
+  optional bool id                =  1;
+  optional bool _cmd              =  2;
+  // super is used as submessage above
+  optional bool in                =  4;
+  optional bool out               =  5;
+  optional bool inout             =  6;
+  optional bool bycopy            =  7;
+  optional bool byref             =  8;
+  optional bool oneway            =  9;
+  optional bool self              =  10;
+  optional bool instancetype      =  11;
+  optional bool nullable          =  12;
+  optional bool nonnull           =  13;
+  optional bool nil               =  14;
+  // Nil and nil can't be in the same message
+  optional bool YES               =  16;
+  optional bool NO                =  17;
+  optional bool weak              =  18;
+
+  // Some C/C++ Keywords
+  optional bool case              = 30;
+  optional bool if                = 31;
+  optional bool and_eq            = 32;
+  optional bool public            = 33;
+  optional bool private           = 34;
+  optional bool typename          = 35;
+  optional bool static_cast       = 36;
+  optional bool typeof            = 37;
+  optional bool restrict          = 38;
+  optional bool NULL              = 39;
+
+  // Some NSObject Methods
+  optional bool dealloc           = 110;
+  optional bool isProxy           = 111;
+  optional bool copy              = 112;
+  optional bool description       = 113;
+  optional bool zone              = 114;
+  optional bool className         = 115;
+  optional bool __retain_OA       = 116;
+  optional bool CAMLType          = 117;
+  optional bool isNSDictionary__  = 118;
+  optional bool accessibilityLabel = 119;
+
+  // Some Objc "keywords" that we shouldn't
+  // have to worry about because they
+  // can only appear in specialized areas.
+  optional bool assign            = 200;
+  optional bool getter            = 201;
+  optional bool setter            = 202;
+  optional bool atomic            = 203;
+  optional bool nonatomic         = 204;
+  optional bool strong            = 205;
+  optional bool null_resettable   = 206;
+  optional bool readonly          = 207;
+
+  // Some GPBMessage methods
+  optional bool clear             = 300;
+  optional bool data              = 301;
+  optional bool descriptor        = 302;
+  optional bool delimitedData     = 303;
+
+  // Some MacTypes
+  optional bool Fixed             = 400;
+  optional bool Point             = 401;
+  optional bool FixedPoint        = 402;
+  optional bool Style             = 403;
+
+  // C/C++ reserved identifiers
+  optional bool _Generic          = 500;
+  optional bool __block           = 501;
+
+  // Try a keyword as a type
+  optional autorelease SubEnum    = 1000;
+
+  optional group New = 2000 {
+   optional string copy = 1;
+  }
+  optional group MutableCopy = 2001 {
+    optional int32 extensionRegistry = 1;
   }
 
-  extensions 90 to 94;
+  extensions 3000 to 3999;
 
 }
 
@@ -177,11 +229,11 @@ enum Time {
 }
 
 extend self {
-  repeated    int32 debugDescription    =  90 [packed = true];
-  repeated    int64 finalize            =  91 [packed = true];
-  repeated   uint32 hash                =  92 [packed = true];
-  repeated   uint64 classForCoder       =  93 [packed = true];
-  repeated   sint32 byref               =  94 [packed = true];
+  repeated    int32 debugDescription    =  3000 [packed = true];
+  repeated    int64 finalize            =  3001 [packed = true];
+  repeated   uint32 hash                =  3002 [packed = true];
+  repeated   uint64 classForCoder       =  3003 [packed = true];
+  repeated   sint32 byref               =  3004 [packed = true];
 }
 
 // Test handing of fields that start with init* since Xcode 5's ARC support

+ 1 - 0
src/Makefile.am

@@ -424,6 +424,7 @@ libprotoc_la_SOURCES =                                         \
   google/protobuf/compiler/objectivec/objectivec_message.h     \
   google/protobuf/compiler/objectivec/objectivec_message_field.cc \
   google/protobuf/compiler/objectivec/objectivec_message_field.h \
+  google/protobuf/compiler/objectivec/objectivec_nsobject_methods.h  \
   google/protobuf/compiler/objectivec/objectivec_oneof.cc      \
   google/protobuf/compiler/objectivec/objectivec_oneof.h       \
   google/protobuf/compiler/objectivec/objectivec_primitive_field.cc \

+ 3 - 1
src/google/protobuf/compiler/csharp/csharp_message.cc

@@ -539,7 +539,9 @@ void MessageGenerator::GenerateMergingMethods(io::Printer* printer) {
   } else {
     printer->Print(
       "default:\n"
-      "  _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);\n"
+      "  if (!pb::UnknownFieldSet.MergeFieldFrom(ref _unknownFields, input)) {\n"
+      "    return;\n"
+      "  }\n"
       "  break;\n");
   }
   for (int i = 0; i < fields_by_number().size(); i++) {

+ 68 - 19
src/google/protobuf/compiler/csharp/csharp_message_field.cc

@@ -37,6 +37,8 @@
 #include <google/protobuf/io/printer.h>
 #include <google/protobuf/io/zero_copy_stream.h>
 #include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/wire_format_lite.h>
 
 #include <google/protobuf/compiler/csharp/csharp_doc_comment.h>
 #include <google/protobuf/compiler/csharp/csharp_helpers.h>
@@ -56,6 +58,21 @@ MessageFieldGenerator::MessageFieldGenerator(const FieldDescriptor* descriptor,
     variables_["has_property_check"] = name() + "_ != null";
     variables_["has_not_property_check"] = name() + "_ == null";
   }
+
+  if (descriptor_->type() == FieldDescriptor::Type::TYPE_GROUP) {
+    int tag_size = internal::WireFormat::TagSize(descriptor_->number(), descriptor_->type()) / 2;
+    uint tag = internal::WireFormatLite::MakeTag(
+        descriptor_->number(),
+        internal::WireFormatLite::WIRETYPE_END_GROUP);
+    uint8 tag_array[5];
+    io::CodedOutputStream::WriteTagToArray(tag, tag_array);
+    string tag_bytes = SimpleItoa(tag_array[0]);
+    for (int i = 1; i < tag_size; i++) {
+        tag_bytes += ", " + SimpleItoa(tag_array[i]);
+    }
+    variables_["end_tag"] = SimpleItoa(tag);
+    variables_["end_tag_bytes"] = tag_bytes;
+  }
 }
 
 MessageFieldGenerator::~MessageFieldGenerator() {
@@ -114,25 +131,47 @@ void MessageFieldGenerator::GenerateParsingCode(io::Printer* printer) {
     variables_,
     "if ($has_not_property_check$) {\n"
     "  $property_name$ = new $type_name$();\n"
-    "}\n"
-    "input.ReadMessage($property_name$);\n");
+    "}\n");
+  if (descriptor_->type() == FieldDescriptor::Type::TYPE_MESSAGE) {
+    printer->Print(variables_, "input.ReadMessage($property_name$);\n");
+  } else {
+    printer->Print(variables_, "input.ReadGroup($property_name$);\n");
+  }
 }
 
 void MessageFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
-  printer->Print(
-    variables_,
-    "if ($has_property_check$) {\n"
-    "  output.WriteRawTag($tag_bytes$);\n"
-    "  output.WriteMessage($property_name$);\n"
-    "}\n");
+  if (descriptor_->type() == FieldDescriptor::Type::TYPE_MESSAGE) {
+    printer->Print(
+      variables_,
+      "if ($has_property_check$) {\n"
+      "  output.WriteRawTag($tag_bytes$);\n"
+      "  output.WriteMessage($property_name$);\n"
+      "}\n");
+  } else {
+    printer->Print(
+      variables_,
+      "if ($has_property_check$) {\n"
+      "  output.WriteRawTag($tag_bytes$);\n"
+      "  output.WriteGroup($property_name$);\n"
+      "  output.WriteRawTag($end_tag_bytes$);\n"
+      "}\n");
+  }
 }
 
 void MessageFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
-  printer->Print(
-    variables_,
-    "if ($has_property_check$) {\n"
-    "  size += $tag_size$ + pb::CodedOutputStream.ComputeMessageSize($property_name$);\n"
-    "}\n");
+  if (descriptor_->type() == FieldDescriptor::Type::TYPE_MESSAGE) {
+    printer->Print(
+      variables_,
+      "if ($has_property_check$) {\n"
+      "  size += $tag_size$ + pb::CodedOutputStream.ComputeMessageSize($property_name$);\n"
+      "}\n");
+  } else {
+    printer->Print(
+      variables_,
+      "if ($has_property_check$) {\n"
+      "  size += $tag_size$ + $tag_size$ + pb::CodedOutputStream.ComputeGroupSize($property_name$);\n"
+      "}\n");
+  }
 }
 
 void MessageFieldGenerator::WriteHash(io::Printer* printer) {
@@ -160,9 +199,15 @@ void MessageFieldGenerator::GenerateFreezingCode(io::Printer* printer) {
 }
 
 void MessageFieldGenerator::GenerateCodecCode(io::Printer* printer) {
-  printer->Print(
-    variables_,
-    "pb::FieldCodec.ForMessage($tag$, $type_name$.Parser)");
+  if (descriptor_->type() == FieldDescriptor::Type::TYPE_MESSAGE) {
+    printer->Print(
+      variables_,
+      "pb::FieldCodec.ForMessage($tag$, $type_name$.Parser)");
+  } else {
+    printer->Print(
+      variables_,
+      "pb::FieldCodec.ForGroup($tag$, $end_tag$, $type_name$.Parser)");
+  }
 }
 
 MessageOneofFieldGenerator::MessageOneofFieldGenerator(
@@ -228,9 +273,13 @@ void MessageOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) {
     "$type_name$ subBuilder = new $type_name$();\n"
     "if ($has_property_check$) {\n"
     "  subBuilder.MergeFrom($property_name$);\n"
-    "}\n"
-    "input.ReadMessage(subBuilder);\n"
-    "$property_name$ = subBuilder;\n");
+    "}\n");
+  if (descriptor_->type() == FieldDescriptor::Type::TYPE_MESSAGE) {
+    printer->Print("input.ReadMessage(subBuilder);\n");
+  } else {
+    printer->Print("input.ReadGroup(subBuilder);\n");
+  }
+  printer->Print(variables_, "$property_name$ = subBuilder;\n");
 }
 
 void MessageOneofFieldGenerator::WriteToString(io::Printer* printer) {

+ 179 - 0
src/google/protobuf/compiler/objectivec/method_dump.sh

@@ -0,0 +1,179 @@
+#!/bin/bash
+
+# Updates objectivec_nsobject_methods.h by generating a list of all of the properties
+# and methods on NSObject that Protobufs should not overload from iOS and macOS combined.
+#
+# The rules:
+#   - No property should ever be overloaded.
+#   - Do not overload any methods that have 0 args such as "autorelease".
+#   - Do not overload any methods that start with "set[A-Z]" and have 1 arg such as
+#     "setValuesForKeysWithDictionary:". Note that these will end up in the list as just
+#     the "proto field" name, so "setValuesForKeysWithDictionary:" will become
+#     "valuesForKeysWithDictionary".
+
+set -eu
+
+trim() {
+    local var="$*"
+    # remove leading whitespace characters
+    var="${var#"${var%%[![:space:]]*}"}"
+    # remove trailing whitespace characters
+    var="${var%"${var##*[![:space:]]}"}"
+    echo -n "$var"
+}
+
+objc_code=$(cat <<'END_CODE'
+#import <Foundation/Foundation.h>
+#import <objc/runtime.h>
+
+int main(int argc, const char * argv[]) {
+  @autoreleasepool {
+    Class cls = [NSObject class];
+
+    // List out the protocols on NSObject just so we are aware if they change.
+    unsigned int protocolCount;
+    __unsafe_unretained Protocol **protocols =
+        class_copyProtocolList(cls, &protocolCount);
+    for (unsigned int i = 0; i < protocolCount; i++) {
+      printf("// Protocol: %s\n", protocol_getName(protocols[i]));
+    }
+    free(protocols);
+
+    // Grab all the properties.
+    unsigned int propCount;
+    objc_property_t *props = class_copyPropertyList(cls, &propCount);
+    NSMutableSet *reservedNames = [[NSMutableSet alloc] init];
+    for (unsigned int i = 0; i < propCount; ++i) {
+      NSString *propertyName = [NSString stringWithUTF8String:property_getName(props[i])];
+      [reservedNames addObject:propertyName];
+    }
+    free(props);
+
+    // Note that methods have 2 defaults args (_cmd and SEL) so a method "0 arg method"
+    // actually has 2.
+    unsigned int methodCount;
+    Method *methods = class_copyMethodList(cls, &methodCount);
+    for (unsigned int i = 0; i < methodCount; ++i) {
+      int argCount = method_getNumberOfArguments(methods[i]);
+      NSString *methodName =
+          [NSString stringWithUTF8String:sel_getName(method_getName(methods[i]))];
+      if (argCount == 2) {
+        [reservedNames addObject:methodName];
+      }
+      if (argCount == 3 && [methodName hasPrefix:@"set"] && methodName.length > 4) {
+        NSString *firstLetter = [methodName substringWithRange:NSMakeRange(3,1)];
+        NSString *lowerFirstLetter = [firstLetter lowercaseString];
+        if ([lowerFirstLetter isEqual:firstLetter]) {
+          // Make sure the next letter is a capital letter so we do not take things like
+          // settingSomething:
+          continue;
+        }
+        // -5 because 3 for set, 1 for the firstLetter and 1 for the colon on the end.
+        NSString *restOfString =
+            [methodName substringWithRange:NSMakeRange(4, methodName.length - 5)];
+        methodName = [lowerFirstLetter stringByAppendingString:restOfString];
+        [reservedNames addObject:methodName];
+      }
+    }
+    free(methods);
+
+    SEL sortSelector = @selector(caseInsensitiveCompare:);
+    NSArray *array = [reservedNames.allObjects sortedArrayUsingSelector:sortSelector];
+    for (NSString *item in array) {
+      // Some items with _ in them get returned in quotes, so do not add more.
+      if ([item hasPrefix:@"\""]) {
+        printf("\t%s,\n", item.UTF8String);
+      } else {
+        printf("\t\"%s\",\n", item.UTF8String);
+      }
+    }
+  }
+  return 0;
+}
+END_CODE
+)
+
+file_header=$(cat <<'END_HEADER'
+// NSObject methods
+// Autogenerated by method_dump.sh. Do not edit by hand.
+// Date: %DATE%
+// macOS: %MACOS%
+// iOS: %IOS%
+
+const char* const kNSObjectMethodsList[] = {
+END_HEADER
+)
+
+file_footer=$(cat <<'END_FOOTER'
+};
+END_FOOTER
+)
+
+# Check to make sure we are updating the correct file.
+if [[ ! -e "objectivec_nsobject_methods.h" ]]; then
+  echo "error: Must be run in the src/google/protobuf/compiler/objectivec directory"
+  exit 1
+fi
+
+temp_dir=$(mktemp -d)
+
+echo "$objc_code" >> "$temp_dir"/method_dump.m
+
+# Compile up iphonesimulator and macos version of cmd line app.
+iphone_simulator_sdk=$(xcrun --sdk iphonesimulator --show-sdk-path)
+clang -isysroot "$iphone_simulator_sdk" -o "$temp_dir"/method_dump_ios \
+    -framework Foundation -framework UIKit "$temp_dir"/method_dump.m
+macos_sdk=$(xcrun --sdk macosx --show-sdk-path)
+clang -isysroot "$macos_sdk" -o "$temp_dir"/method_dump_macos -framework Foundation \
+    -framework Cocoa "$temp_dir"/method_dump.m
+
+# Create a device of the latest phone and iphonesimulator SDK and run our iOS cmd line.
+device_type=$(xcrun simctl list devicetypes | grep \.iPhone- | tail -1 | sed 's/.*(\(.*\))/\1/')
+# runtimes come with a space at the end (for Xcode 10) so let's trim all of our input to
+# be safe.
+device_type=$(trim "$device_type")
+runtime=$(xcrun simctl list runtimes | grep \.iOS- | tail -1 | \
+    sed 's/.*\(com\.apple.\CoreSimulator\.SimRuntime\.iOS.*\)/\1/')
+runtime=$(trim "$runtime")
+uuid=$(uuidgen)
+device_name="method_dump_device_$uuid"
+device=$(xcrun simctl create "$device_name" "$device_type" "$runtime")
+xcrun simctl spawn "$device" "$temp_dir"/method_dump_ios > "$temp_dir"/methods_unsorted_ios.txt
+xcrun simctl delete "$device"
+
+# Run the Mac version
+"$temp_dir"/method_dump_macos >> "$temp_dir"/methods_unsorted_macos.txt
+
+# Generate sorted output
+echo "$file_header" | sed -e "s|%DATE%|$(date)|" -e "s|%MACOS%|$(basename $macos_sdk)|" \
+    -e "s|%IOS%|$(basename $iphone_simulator_sdk)|" > "$temp_dir"/methods_sorted.txt
+sort -u "$temp_dir"/methods_unsorted_ios.txt \
+    "$temp_dir"/methods_unsorted_macos.txt >> "$temp_dir"/methods_sorted.txt
+echo $"$file_footer" >> "$temp_dir"/methods_sorted.txt
+
+# Check for differences. Turn off error checking because we expect diff to fail when
+# there are no differences.
+set +e
+diff_out=$(diff -I "^//.*$" "$temp_dir"/methods_sorted.txt objectivec_nsobject_methods.h)
+removed_methods=$(echo "$diff_out" | grep '^>.*$')
+set -e
+if [[ -n "$removed_methods" ]]; then
+  echo "error: Methods removed from NSObject"
+  echo "It appears that some methods may have been removed from NSObject."
+  echo "This could mean that there may be some backwards compatibility issues."
+  echo "You could potentially build apps that may not work on earlier systems than:"
+  echo "$iphone_simulator_sdk"
+  echo "$macos_sdk"
+  echo "If they declare protobuf types that use any of the following as names:"
+  echo "$removed_methods"
+  echo ""
+  echo "New Version: $temp_dir/methods_sorted.txt"
+  echo "Old Version: objectivec_nsobject_methods.h"
+  exit 1
+fi
+if [[ -n "$diff_out" ]]; then
+  echo "Added Methods:"
+  echo "$(echo "$diff_out" | grep '^<.*$' | sed -e 's/^< "\(.*\)",$/  \1/')"
+fi;
+cp "$temp_dir"/methods_sorted.txt objectivec_nsobject_methods.h
+rm -rf "$temp_dir"

+ 79 - 53
src/google/protobuf/compiler/objectivec/objectivec_helpers.cc

@@ -43,6 +43,7 @@
 
 #include <google/protobuf/stubs/hash.h>
 #include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
+#include <google/protobuf/compiler/objectivec/objectivec_nsobject_methods.h>
 #include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/io/coded_stream.h>
 #include <google/protobuf/io/printer.h>
@@ -170,65 +171,90 @@ string UnderscoresToCamelCase(const string& input, bool first_capitalized) {
 }
 
 const char* const kReservedWordList[] = {
-    // Objective C "keywords" that aren't in C
-    // From
-    // http://stackoverflow.com/questions/1873630/reserved-keywords-in-objective-c
-    "id", "_cmd", "super", "in", "out", "inout", "bycopy", "byref", "oneway",
-    "self",
-
-    // C/C++ keywords (Incl C++ 0x11)
-    // From http://en.cppreference.com/w/cpp/keywords
-    "and", "and_eq", "alignas", "alignof", "asm", "auto", "bitand", "bitor",
-    "bool", "break", "case", "catch", "char", "char16_t", "char32_t", "class",
-    "compl", "const", "constexpr", "const_cast", "continue", "decltype",
-    "default", "delete", "double", "dynamic_cast", "else", "enum", "explicit",
-    "export", "extern ", "false", "float", "for", "friend", "goto", "if",
-    "inline", "int", "long", "mutable", "namespace", "new", "noexcept", "not",
-    "not_eq", "nullptr", "operator", "or", "or_eq", "private", "protected",
-    "public", "register", "reinterpret_cast", "return", "short", "signed",
-    "sizeof", "static", "static_assert", "static_cast", "struct", "switch",
-    "template", "this", "thread_local", "throw", "true", "try", "typedef",
-    "typeid", "typename", "union", "unsigned", "using", "virtual", "void",
-    "volatile", "wchar_t", "while", "xor", "xor_eq",
-
-    // C99 keywords
-    // From
-    // http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Fkeyw.htm
-    "restrict",
-
-    // Objective-C Runtime typedefs
-    // From <obc/runtime.h>
-    "Category", "Ivar", "Method", "Protocol",
-
-    // NSObject Methods
-    // new is covered by C++ keywords.
-    "description", "debugDescription", "finalize", "hash", "dealloc", "init",
-    "class", "superclass", "retain", "release", "autorelease", "retainCount",
-    "zone", "isProxy", "copy", "mutableCopy", "classForCoder",
-
-    // GPBMessage Methods
-    // Only need to add instance methods that may conflict with
-    // method declared in protos. The main cases are methods
-    // that take no arguments, or setFoo:/hasFoo: type methods.
-    "clear", "data", "delimitedData", "descriptor", "extensionRegistry",
-    "extensionsCurrentlySet", "initialized", "isInitialized", "serializedSize",
-    "sortedExtensionsInUse", "unknownFields",
-
-    // MacTypes.h names
-    "Fixed", "Fract", "Size", "LogicalAddress", "PhysicalAddress", "ByteCount",
-    "ByteOffset", "Duration", "AbsoluteTime", "OptionBits", "ItemCount",
-    "PBVersion", "ScriptCode", "LangCode", "RegionCode", "OSType",
-    "ProcessSerialNumber", "Point", "Rect", "FixedPoint", "FixedRect", "Style",
-    "StyleParameter", "StyleField", "TimeScale", "TimeBase", "TimeRecord",
+  // Note NSObject Methods:
+  // These are brought in from objectivec_nsobject_methods.h that is generated
+  // using method_dump.sh. See kNSObjectMethods below.
+
+  // Objective C "keywords" that aren't in C
+  // From
+  // http://stackoverflow.com/questions/1873630/reserved-keywords-in-objective-c
+  // with some others added on.
+  "id", "_cmd", "super", "in", "out", "inout", "bycopy", "byref", "oneway",
+  "self", "instancetype", "nullable", "nonnull", "nil", "Nil",
+  "YES", "NO", "weak",
+
+  // C/C++ keywords (Incl C++ 0x11)
+  // From http://en.cppreference.com/w/cpp/keywords
+  "and", "and_eq", "alignas", "alignof", "asm", "auto", "bitand", "bitor",
+  "bool", "break", "case", "catch", "char", "char16_t", "char32_t", "class",
+  "compl", "const", "constexpr", "const_cast", "continue", "decltype",
+  "default", "delete", "double", "dynamic_cast", "else", "enum", "explicit",
+  "export", "extern ", "false", "float", "for", "friend", "goto", "if",
+  "inline", "int", "long", "mutable", "namespace", "new", "noexcept", "not",
+  "not_eq", "nullptr", "operator", "or", "or_eq", "private", "protected",
+  "public", "register", "reinterpret_cast", "return", "short", "signed",
+  "sizeof", "static", "static_assert", "static_cast", "struct", "switch",
+  "template", "this", "thread_local", "throw", "true", "try", "typedef",
+  "typeid", "typename", "union", "unsigned", "using", "virtual", "void",
+  "volatile", "wchar_t", "while", "xor", "xor_eq",
+
+  // C99 keywords
+  // From
+  // http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Fkeyw.htm
+  "restrict",
+
+  // GCC/Clang extension
+  "typeof",
+
+  // Not a keyword, but will break you
+  "NULL",
+
+  // Objective-C Runtime typedefs
+  // From <obc/runtime.h>
+  "Category", "Ivar", "Method", "Protocol",
+
+  // GPBMessage Methods
+  // Only need to add instance methods that may conflict with
+  // method declared in protos. The main cases are methods
+  // that take no arguments, or setFoo:/hasFoo: type methods.
+  "clear", "data", "delimitedData", "descriptor", "extensionRegistry",
+  "extensionsCurrentlySet", "initialized", "isInitialized", "serializedSize",
+  "sortedExtensionsInUse", "unknownFields",
+
+  // MacTypes.h names
+  "Fixed", "Fract", "Size", "LogicalAddress", "PhysicalAddress", "ByteCount",
+  "ByteOffset", "Duration", "AbsoluteTime", "OptionBits", "ItemCount",
+  "PBVersion", "ScriptCode", "LangCode", "RegionCode", "OSType",
+  "ProcessSerialNumber", "Point", "Rect", "FixedPoint", "FixedRect", "Style",
+  "StyleParameter", "StyleField", "TimeScale", "TimeBase", "TimeRecord",
 };
 
-std::unordered_set<string> kReservedWords =
-    MakeWordsMap(kReservedWordList, GOOGLE_ARRAYSIZE(kReservedWordList));
+// returns true is input starts with __ or _[A-Z] which are reserved identifiers
+// in C/ C++. All calls should go through UnderscoresToCamelCase before getting here
+// but this verifies and allows for future expansion if we decide to redefine what a
+// reserved C identifier is (for example the GNU list
+// https://www.gnu.org/software/libc/manual/html_node/Reserved-Names.html )
+bool IsReservedCIdentifier(const string& input) {
+  if (input.length() > 2) {
+    if (input.at(0) == '_') {
+      if (isupper(input.at(1)) || input.at(1) == '_') {
+        return true;
+      }
+    }
+  }
+  return false;
+}
 
 string SanitizeNameForObjC(const string& input,
                            const string& extension,
                            string* out_suffix_added) {
-  if (kReservedWords.count(input) > 0) {
+  static const std::unordered_set<string> kReservedWords =
+      MakeWordsMap(kReservedWordList, GOOGLE_ARRAYSIZE(kReservedWordList));
+  static const std::unordered_set<string> kNSObjectMethods =
+      MakeWordsMap(kNSObjectMethodsList, GOOGLE_ARRAYSIZE(kNSObjectMethodsList));
+  if (IsReservedCIdentifier(input) ||
+      (kReservedWords.count(input) > 0) ||
+      (kNSObjectMethods.count(input) > 0)) {
     if (out_suffix_added) *out_suffix_added = extension;
     return input + extension;
   }

+ 197 - 0
src/google/protobuf/compiler/objectivec/objectivec_nsobject_methods.h

@@ -0,0 +1,197 @@
+// NSObject methods
+// Autogenerated by method_dump.sh. Do not edit by hand.
+// Date: Thu Nov  1 14:12:16 PDT 2018
+// macOS: MacOSX10.14.sdk
+// iOS: iPhoneSimulator12.1.sdk
+
+const char* const kNSObjectMethodsList[] = {
+	"CAMLType",
+	"CA_copyRenderValue",
+	"CA_prepareRenderValue",
+	"NS_copyCGImage",
+	"NS_tiledLayerVisibleRect",
+	"___tryRetain_OA",
+	"__autorelease_OA",
+	"__dealloc_zombie",
+	"__release_OA",
+	"__retain_OA",
+	"_accessibilityFinalize",
+	"_accessibilityIsTableViewDescendant",
+	"_accessibilityUIElementSpecifier",
+	"_accessibilityUseConvenienceAPI",
+	"_allowsDirectEncoding",
+	"_asScriptTerminologyNameArray",
+	"_asScriptTerminologyNameString",
+	"_bindingAdaptor",
+	"_cfTypeID",
+	"_copyDescription",
+	"_destroyObserverList",
+	"_didEndKeyValueObserving",
+	"_implicitObservationInfo",
+	"_internalAccessibilityAttributedHint",
+	"_internalAccessibilityAttributedLabel",
+	"_internalAccessibilityAttributedValue",
+	"_isAXConnector",
+	"_isAccessibilityContainerSectionCandidate",
+	"_isAccessibilityContentNavigatorSectionCandidate",
+	"_isAccessibilityContentSectionCandidate",
+	"_isAccessibilityTopLevelNavigatorSectionCandidate",
+	"_isDeallocating",
+	"_isKVOA",
+	"_isToManyChangeInformation",
+	"_ivarDescription",
+	"_localClassNameForClass",
+	"_methodDescription",
+	"_observerStorage",
+	"_overrideUseFastBlockObservers",
+	"_propertyDescription",
+	"_releaseBindingAdaptor",
+	"_scriptingCount",
+	"_scriptingCountNonrecursively",
+	"_scriptingDebugDescription",
+	"_scriptingExists",
+	"_scriptingShouldCheckObjectIndexes",
+	"_shortMethodDescription",
+	"_shouldSearchChildrenForSection",
+	"_traitStorageList",
+	"_tryRetain",
+	"_ui_descriptionBuilder",
+	"_uikit_variesByTraitCollections",
+	"_web_description",
+	"_webkit_invokeOnMainThread",
+	"_willBeginKeyValueObserving",
+	"accessibilityActivate",
+	"accessibilityActivationPoint",
+	"accessibilityAllowsOverriddenAttributesWhenIgnored",
+	"accessibilityAssistiveTechnologyFocusedIdentifiers",
+	"accessibilityAttributedHint",
+	"accessibilityAttributedLabel",
+	"accessibilityAttributedValue",
+	"accessibilityContainer",
+	"accessibilityContainerType",
+	"accessibilityCustomActions",
+	"accessibilityCustomRotors",
+	"accessibilityDecrement",
+	"accessibilityDragSourceDescriptors",
+	"accessibilityDropPointDescriptors",
+	"accessibilityElementCount",
+	"accessibilityElementDidBecomeFocused",
+	"accessibilityElementDidLoseFocus",
+	"accessibilityElementIsFocused",
+	"accessibilityElements",
+	"accessibilityElementsHidden",
+	"accessibilityFrame",
+	"accessibilityHeaderElements",
+	"accessibilityHint",
+	"accessibilityIdentification",
+	"accessibilityIdentifier",
+	"accessibilityIncrement",
+	"accessibilityLabel",
+	"accessibilityLanguage",
+	"accessibilityLocalizedStringKey",
+	"accessibilityNavigationStyle",
+	"accessibilityOverriddenAttributes",
+	"accessibilityParameterizedAttributeNames",
+	"accessibilityPath",
+	"accessibilityPerformEscape",
+	"accessibilityPerformMagicTap",
+	"accessibilityPresenterProcessIdentifier",
+	"accessibilityShouldUseUniqueId",
+	"accessibilitySupportsNotifications",
+	"accessibilitySupportsOverriddenAttributes",
+	"accessibilityTemporaryChildren",
+	"accessibilityTraits",
+	"accessibilityValue",
+	"accessibilityViewIsModal",
+	"accessibilityVisibleArea",
+	"allPropertyKeys",
+	"allowsWeakReference",
+	"attributeKeys",
+	"autoContentAccessingProxy",
+	"autorelease",
+	"awakeFromNib",
+	"boolValueSafe",
+	"bs_encoded",
+	"bs_isPlistableType",
+	"bs_secureEncoded",
+	"cl_json_serializeKey",
+	"class",
+	"classCode",
+	"classDescription",
+	"classForArchiver",
+	"classForCoder",
+	"classForKeyedArchiver",
+	"classForPortCoder",
+	"className",
+	"clearProperties",
+	"copy",
+	"dealloc",
+	"debugDescription",
+	"defaultAccessibilityTraits",
+	"description",
+	"doubleValueSafe",
+	"entityName",
+	"exposedBindings",
+	"finalize",
+	"finishObserving",
+	"flushKeyBindings",
+	"hash",
+	"init",
+	"int64ValueSafe",
+	"isAccessibilityElement",
+	"isAccessibilityElementByDefault",
+	"isElementAccessibilityExposedToInterfaceBuilder",
+	"isFault",
+	"isNSArray__",
+	"isNSCFConstantString__",
+	"isNSData__",
+	"isNSDate__",
+	"isNSDictionary__",
+	"isNSNumber__",
+	"isNSObject__",
+	"isNSOrderedSet__",
+	"isNSSet__",
+	"isNSString__",
+	"isNSTimeZone__",
+	"isNSValue__",
+	"isProxy",
+	"mutableCopy",
+	"nilValueForKey",
+	"objectSpecifier",
+	"observationInfo",
+	"pep_onDetachedThread",
+	"pep_onMainThread",
+	"pep_onMainThreadIfNecessary",
+	"prepareForInterfaceBuilder",
+	"release",
+	"releaseOnMainThread",
+	"retain",
+	"retainCount",
+	"retainWeakReference",
+	"scriptingProperties",
+	"self",
+	"shouldGroupAccessibilityChildren",
+	"storedAccessibilityActivationPoint",
+	"storedAccessibilityContainerType",
+	"storedAccessibilityElementsHidden",
+	"storedAccessibilityFrame",
+	"storedAccessibilityNavigationStyle",
+	"storedAccessibilityTraits",
+	"storedAccessibilityViewIsModal",
+	"storedIsAccessibilityElement",
+	"storedShouldGroupAccessibilityChildren",
+	"stringValueSafe",
+	"superclass",
+	"toManyRelationshipKeys",
+	"toOneRelationshipKeys",
+	"traitStorageList",
+	"un_safeBoolValue",
+	"userInterfaceItemIdentifier",
+	"utf8ValueSafe",
+	"valuesForKeysWithDictionary",
+	"zone",
+// Protocol: CAAnimatableValue
+// Protocol: CARenderValue
+// Protocol: NSObject
+// Protocol: ROCKRemoteInvocationInterface
+};

+ 1 - 0
src/google/protobuf/implicit_weak_message.cc

@@ -34,6 +34,7 @@
 #include <google/protobuf/io/zero_copy_stream_impl_lite.h>
 #include <google/protobuf/stubs/once.h>
 #include <google/protobuf/wire_format_lite.h>
+#include <google/protobuf/wire_format_lite_inl.h>
 
 #include <google/protobuf/port_def.inc>