Procházet zdrojové kódy

Merge remote-tracking branch 'upstream/master'

Tres Seaver před 11 roky
rodič
revize
0eb74768d0
91 změnil soubory, kde provedl 7714 přidání a 1239 odebrání
  1. 23 15
      java/src/main/java/com/google/protobuf/GeneratedMessageLite.java
  2. 1 1
      java/src/main/java/com/google/protobuf/MapEntry.java
  3. 1 1
      java/src/main/java/com/google/protobuf/MapField.java
  4. 14 0
      java/src/test/java/com/google/protobuf/MapForProto2Test.java
  5. 5 0
      java/src/test/java/com/google/protobuf/map_for_proto2_lite_test.proto
  6. 5 0
      java/src/test/java/com/google/protobuf/map_for_proto2_test.proto
  7. 0 2
      python/google/protobuf/internal/generator_test.py
  8. 2 4
      python/google/protobuf/internal/test_bad_identifiers.proto
  9. 18 18
      python/google/protobuf/text_format.py
  10. 22 0
      src/Makefile.am
  11. 1 1
      src/google/protobuf/arena.cc
  12. 39 2
      src/google/protobuf/arena_unittest.cc
  13. 10 0
      src/google/protobuf/arenastring.cc
  14. 2 0
      src/google/protobuf/arenastring.h
  15. 3 3
      src/google/protobuf/compiler/command_line_interface.cc
  16. 3 3
      src/google/protobuf/compiler/command_line_interface_unittest.cc
  17. 2 2
      src/google/protobuf/compiler/cpp/cpp_enum.cc
  18. 17 3
      src/google/protobuf/compiler/cpp/cpp_field.cc
  19. 1 1
      src/google/protobuf/compiler/cpp/cpp_field.h
  20. 22 5
      src/google/protobuf/compiler/cpp/cpp_file.cc
  21. 4 4
      src/google/protobuf/compiler/cpp/cpp_file.h
  22. 2 2
      src/google/protobuf/compiler/cpp/cpp_generator.cc
  23. 19 0
      src/google/protobuf/compiler/cpp/cpp_helpers.cc
  24. 9 1
      src/google/protobuf/compiler/cpp/cpp_helpers.h
  25. 255 0
      src/google/protobuf/compiler/cpp/cpp_map_field.cc
  26. 75 0
      src/google/protobuf/compiler/cpp/cpp_map_field.h
  27. 120 28
      src/google/protobuf/compiler/cpp/cpp_message.cc
  28. 3 3
      src/google/protobuf/compiler/cpp/cpp_message.h
  29. 9 5
      src/google/protobuf/compiler/cpp/cpp_message_field.cc
  30. 1 1
      src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc
  31. 8 1
      src/google/protobuf/compiler/cpp/cpp_string_field.cc
  32. 8 8
      src/google/protobuf/compiler/cpp/cpp_unittest.cc
  33. 3 3
      src/google/protobuf/compiler/importer.cc
  34. 3 3
      src/google/protobuf/compiler/importer_unittest.cc
  35. 1 1
      src/google/protobuf/compiler/java/java_context.h
  36. 1 1
      src/google/protobuf/compiler/java/java_field.cc
  37. 1 1
      src/google/protobuf/compiler/java/java_field.h
  38. 7 7
      src/google/protobuf/compiler/java/java_file.cc
  39. 4 4
      src/google/protobuf/compiler/java/java_file.h
  40. 2 2
      src/google/protobuf/compiler/java/java_generator.cc
  41. 102 57
      src/google/protobuf/compiler/java/java_message.cc
  42. 1 1
      src/google/protobuf/compiler/java/java_plugin_unittest.cc
  43. 2 2
      src/google/protobuf/compiler/java/java_shared_code_generator.cc
  44. 1 1
      src/google/protobuf/compiler/java/java_shared_code_generator.h
  45. 3 3
      src/google/protobuf/compiler/mock_code_generator.cc
  46. 3 3
      src/google/protobuf/compiler/parser_unittest.cc
  47. 61 133
      src/google/protobuf/compiler/plugin.pb.cc
  48. 50 215
      src/google/protobuf/compiler/plugin.pb.h
  49. 7 42
      src/google/protobuf/compiler/python/python_generator.cc
  50. 1 1
      src/google/protobuf/compiler/python/python_plugin_unittest.cc
  51. 7 6
      src/google/protobuf/descriptor.cc
  52. 2 2
      src/google/protobuf/descriptor.h
  53. 148 261
      src/google/protobuf/descriptor.pb.cc
  54. 10 329
      src/google/protobuf/descriptor.pb.h
  55. 5 0
      src/google/protobuf/descriptor.proto
  56. 42 0
      src/google/protobuf/descriptor_unittest.cc
  57. 1 1
      src/google/protobuf/drop_unknown_fields_test.cc
  58. 25 4
      src/google/protobuf/dynamic_message.cc
  59. 1 1
      src/google/protobuf/dynamic_message.h
  60. 1 1
      src/google/protobuf/extension_set_unittest.cc
  61. 152 33
      src/google/protobuf/generated_message_reflection.cc
  62. 26 0
      src/google/protobuf/generated_message_reflection.h
  63. 1 0
      src/google/protobuf/generated_message_util.cc
  64. 282 0
      src/google/protobuf/map.h
  65. 449 0
      src/google/protobuf/map_entry.h
  66. 113 0
      src/google/protobuf/map_field.cc
  67. 220 0
      src/google/protobuf/map_field.h
  68. 269 0
      src/google/protobuf/map_field_inl.h
  69. 470 0
      src/google/protobuf/map_field_test.cc
  70. 39 0
      src/google/protobuf/map_lite_unittest.proto
  71. 68 0
      src/google/protobuf/map_proto2_unittest.proto
  72. 2143 0
      src/google/protobuf/map_test.cc
  73. 1479 0
      src/google/protobuf/map_test_util.cc
  74. 149 0
      src/google/protobuf/map_test_util.h
  75. 486 0
      src/google/protobuf/map_type_handler.h
  76. 77 0
      src/google/protobuf/map_unittest.proto
  77. 5 1
      src/google/protobuf/message.cc
  78. 1 1
      src/google/protobuf/preserve_unknown_enum_test.cc
  79. 1 1
      src/google/protobuf/proto3_arena_unittest.cc
  80. 68 0
      src/google/protobuf/reflection_internal.h
  81. 6 1
      src/google/protobuf/repeated_field.h
  82. 1 1
      src/google/protobuf/repeated_field_reflection.h
  83. 1 1
      src/google/protobuf/repeated_field_reflection_unittest.cc
  84. 2 0
      src/google/protobuf/stubs/common.h
  85. 1 1
      src/google/protobuf/text_format.h
  86. 1 0
      src/google/protobuf/unittest.proto
  87. 1 0
      src/google/protobuf/unittest_arena.proto
  88. 1 0
      src/google/protobuf/unittest_import.proto
  89. 1 0
      src/google/protobuf/unittest_mset.proto
  90. 1 0
      src/google/protobuf/unittest_no_arena.proto
  91. 1 0
      src/google/protobuf/unittest_proto3_arena.proto

+ 23 - 15
java/src/main/java/com/google/protobuf/GeneratedMessageLite.java

@@ -81,22 +81,18 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite
     return unknownFields.mergeFieldFrom(tag, input);
     return unknownFields.mergeFieldFrom(tag, input);
   }
   }
 
 
-  /**
-   * Used by parsing constructors in generated classes.
-   */
-  protected void makeExtensionsImmutable() {
-    // Noop for messages without extensions.
-  }
-
   @SuppressWarnings("unchecked")
   @SuppressWarnings("unchecked")
   public abstract static class Builder<MessageType extends GeneratedMessageLite,
   public abstract static class Builder<MessageType extends GeneratedMessageLite,
                                        BuilderType extends Builder>
                                        BuilderType extends Builder>
       extends AbstractMessageLite.Builder<BuilderType> {
       extends AbstractMessageLite.Builder<BuilderType> {
 
 
+    private final MessageType defaultInstance;
     private UnknownFieldSetLite unknownFields =
     private UnknownFieldSetLite unknownFields =
         UnknownFieldSetLite.getDefaultInstance();
         UnknownFieldSetLite.getDefaultInstance();
 
 
-    protected Builder() {}
+    protected Builder(MessageType defaultInstance) {
+      this.defaultInstance = defaultInstance;
+    }
 
 
     //@Override (Java 1.6 override semantics, but we must support 1.5)
     //@Override (Java 1.6 override semantics, but we must support 1.5)
     public BuilderType clear() {
     public BuilderType clear() {
@@ -111,15 +107,25 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite
       builder.mergeFrom(buildPartial());
       builder.mergeFrom(buildPartial());
       return builder;
       return builder;
     }
     }
-    
+
     /** All subclasses implement this. */
     /** All subclasses implement this. */
     public abstract MessageType buildPartial();
     public abstract MessageType buildPartial();
 
 
+    //@Override (Java 1.6 override semantics, but we must support 1.5)
+    public final MessageType build() {
+      MessageType result = buildPartial();
+      if (!result.isInitialized()) {
+        throw newUninitializedMessageException(result);
+      }
+      return result;
+    }
+
     /** All subclasses implement this. */
     /** All subclasses implement this. */
     public abstract BuilderType mergeFrom(MessageType message);
     public abstract BuilderType mergeFrom(MessageType message);
-
-    // Defined here for return type covariance.
-    public abstract MessageType getDefaultInstanceForType();
+    
+    public MessageType getDefaultInstanceForType() {
+      return defaultInstance;
+    }
 
 
     /**
     /**
      * Called by subclasses to parse an unknown field.
      * Called by subclasses to parse an unknown field.
@@ -288,8 +294,8 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite
     /**
     /**
      * Used by parsing constructors in generated classes.
      * Used by parsing constructors in generated classes.
      */
      */
-    @Override
-    protected void makeExtensionsImmutable() {
+    protected static void makeExtensionsImmutable(
+        FieldSet<ExtensionDescriptor> extensions) {
       extensions.makeImmutable();
       extensions.makeImmutable();
     }
     }
 
 
@@ -361,7 +367,9 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite
         BuilderType extends ExtendableBuilder<MessageType, BuilderType>>
         BuilderType extends ExtendableBuilder<MessageType, BuilderType>>
       extends Builder<MessageType, BuilderType>
       extends Builder<MessageType, BuilderType>
       implements ExtendableMessageOrBuilder<MessageType> {
       implements ExtendableMessageOrBuilder<MessageType> {
-    protected ExtendableBuilder() {}
+    protected ExtendableBuilder(MessageType defaultInstance) {
+      super(defaultInstance);
+    }
 
 
     private FieldSet<ExtensionDescriptor> extensions = FieldSet.emptySet();
     private FieldSet<ExtensionDescriptor> extensions = FieldSet.emptySet();
     private boolean extensionsIsMutable;
     private boolean extensionsIsMutable;

+ 1 - 1
java/src/main/java/com/google/protobuf/MapEntry.java

@@ -282,7 +282,7 @@ public final class MapEntry<K, V> extends AbstractMessage {
     @Override
     @Override
     public MapEntry<K, V> buildPartial() {
     public MapEntry<K, V> buildPartial() {
       if (dataBuilder != null) {
       if (dataBuilder != null) {
-        data = dataBuilder.build();
+        data = dataBuilder.buildPartial();
         dataBuilder = null;
         dataBuilder = null;
       }
       }
       return new MapEntry<K, V>(metadata, data);
       return new MapEntry<K, V>(metadata, data);

+ 1 - 1
java/src/main/java/com/google/protobuf/MapField.java

@@ -91,7 +91,7 @@ public class MapField<K, V> {
     }
     }
     
     
     public Message convertKeyAndValueToMessage(K key, V value) {
     public Message convertKeyAndValueToMessage(K key, V value) {
-      return defaultEntry.newBuilderForType().setKey(key).setValue(value).build();
+      return defaultEntry.newBuilderForType().setKey(key).setValue(value).buildPartial();
     }
     }
     
     
     public void convertMessageToKeyAndValue(Message message, Map<K, V> map) {
     public void convertMessageToKeyAndValue(Message message, Map<K, V> map) {

+ 14 - 0
java/src/test/java/com/google/protobuf/MapForProto2Test.java

@@ -33,6 +33,7 @@ package com.google.protobuf;
 import com.google.protobuf.Descriptors.FieldDescriptor;
 import com.google.protobuf.Descriptors.FieldDescriptor;
 import map_test.MapForProto2TestProto.TestMap;
 import map_test.MapForProto2TestProto.TestMap;
 import map_test.MapForProto2TestProto.TestMap.MessageValue;
 import map_test.MapForProto2TestProto.TestMap.MessageValue;
+import map_test.MapForProto2TestProto.TestMap.MessageWithRequiredFields;
 import map_test.MapForProto2TestProto.TestUnknownEnumValue;
 import map_test.MapForProto2TestProto.TestUnknownEnumValue;
 
 
 import junit.framework.TestCase;
 import junit.framework.TestCase;
@@ -485,4 +486,17 @@ public class MapForProto2Test extends TestCase {
     assertEquals(54321, messageWithUnknownEnums.getInt32ToInt32Field().get(2).intValue());
     assertEquals(54321, messageWithUnknownEnums.getInt32ToInt32Field().get(2).intValue());
   }
   }
 
 
+
+  public void testRequiredMessage() throws Exception {
+    TestMap.Builder builder = TestMap.newBuilder();
+    builder.getMutableRequiredMessageMap().put(0,
+        MessageWithRequiredFields.newBuilder().buildPartial());
+    TestMap message = builder.buildPartial();
+    assertFalse(message.isInitialized());
+
+    builder.getMutableRequiredMessageMap().put(0,
+        MessageWithRequiredFields.newBuilder().setValue(1).build());
+    message = builder.build();
+    assertTrue(message.isInitialized());
+  }
 }
 }

+ 5 - 0
java/src/test/java/com/google/protobuf/map_for_proto2_lite_test.proto

@@ -51,6 +51,11 @@ message TestMap {
   map<int32, EnumValue>     int32_to_enum_field = 4;
   map<int32, EnumValue>     int32_to_enum_field = 4;
   map<int32, MessageValue>  int32_to_message_field = 5;
   map<int32, MessageValue>  int32_to_message_field = 5;
   map<string, int32>        string_to_int32_field = 6;
   map<string, int32>        string_to_int32_field = 6;
+
+  message MessageWithRequiredFields {
+    required int32 value = 1;
+  }
+  map<int32, MessageWithRequiredFields> required_message_map = 11;
 }
 }
 
 
 message TestUnknownEnumValue {
 message TestUnknownEnumValue {

+ 5 - 0
java/src/test/java/com/google/protobuf/map_for_proto2_test.proto

@@ -53,6 +53,11 @@ message TestMap {
   map<int32, EnumValue>     int32_to_enum_field = 4;
   map<int32, EnumValue>     int32_to_enum_field = 4;
   map<int32, MessageValue>  int32_to_message_field = 5;
   map<int32, MessageValue>  int32_to_message_field = 5;
   map<string, int32>        string_to_int32_field = 6;
   map<string, int32>        string_to_int32_field = 6;
+
+  message MessageWithRequiredFields {
+    required int32 value = 1;
+  }
+  map<int32, MessageWithRequiredFields> required_message_map = 11;
 }
 }
 
 
 message TestUnknownEnumValue {
 message TestUnknownEnumValue {

+ 0 - 2
python/google/protobuf/internal/generator_test.py

@@ -281,8 +281,6 @@ class GeneratorTest(basetest.TestCase):
                      "baz")
                      "baz")
     self.assertEqual(message.Extensions[test_bad_identifiers_pb2.service],
     self.assertEqual(message.Extensions[test_bad_identifiers_pb2.service],
                      "qux")
                      "qux")
-    self.assertEqual(message.Extensions[test_bad_identifiers_pb2.class_],
-                     "Foo")
 
 
   def testOneof(self):
   def testOneof(self):
     desc = unittest_pb2.TestAllTypes.DESCRIPTOR
     desc = unittest_pb2.TestAllTypes.DESCRIPTOR

+ 2 - 4
python/google/protobuf/internal/test_bad_identifiers.proto

@@ -40,15 +40,13 @@ message TestBadIdentifiers {
   extensions 100 to max;
   extensions 100 to max;
 }
 }
 
 
+// Make sure these reasonable extension names don't conflict with internal
+// variables.
 extend TestBadIdentifiers {
 extend TestBadIdentifiers {
-  // Make sure these reasonable extension names don't conflict with internal
-  // variables.
   optional string message = 100 [default="foo"];
   optional string message = 100 [default="foo"];
   optional string descriptor = 101 [default="bar"];
   optional string descriptor = 101 [default="bar"];
   optional string reflection = 102 [default="baz"];
   optional string reflection = 102 [default="baz"];
   optional string service = 103 [default="qux"];
   optional string service = 103 [default="qux"];
-  // And Python keywords.
-  optional string class = 104 [default="Foo"];
 }
 }
 
 
 message AnotherMessage {}
 message AnotherMessage {}

+ 18 - 18
python/google/protobuf/text_format.py

@@ -217,24 +217,6 @@ def PrintFieldValue(field, value, out, indent=0, as_utf8=False,
     out.write(str(value))
     out.write(str(value))
 
 
 
 
-def _ParseOrMerge(lines, message, allow_multiple_scalars):
-  """Converts an ASCII representation of a protocol message into a message.
-
-  Args:
-    lines: Lines of a message's ASCII representation.
-    message: A protocol buffer message to merge into.
-    allow_multiple_scalars: Determines if repeated values for a non-repeated
-      field are permitted, e.g., the string "foo: 1 foo: 2" for a
-      required/optional field named "foo".
-
-  Raises:
-    ParseError: On ASCII parsing problems.
-  """
-  tokenizer = _Tokenizer(lines)
-  while not tokenizer.AtEnd():
-    _MergeField(tokenizer, message, allow_multiple_scalars)
-
-
 def Parse(text, message):
 def Parse(text, message):
   """Parses an ASCII representation of a protocol message into a message.
   """Parses an ASCII representation of a protocol message into a message.
 
 
@@ -305,6 +287,24 @@ def MergeLines(lines, message):
   return message
   return message
 
 
 
 
+def _ParseOrMerge(lines, message, allow_multiple_scalars):
+  """Converts an ASCII representation of a protocol message into a message.
+
+  Args:
+    lines: Lines of a message's ASCII representation.
+    message: A protocol buffer message to merge into.
+    allow_multiple_scalars: Determines if repeated values for a non-repeated
+      field are permitted, e.g., the string "foo: 1 foo: 2" for a
+      required/optional field named "foo".
+
+  Raises:
+    ParseError: On ASCII parsing problems.
+  """
+  tokenizer = _Tokenizer(lines)
+  while not tokenizer.AtEnd():
+    _MergeField(tokenizer, message, allow_multiple_scalars)
+
+
 def _MergeField(tokenizer, message, allow_multiple_scalars):
 def _MergeField(tokenizer, message, allow_multiple_scalars):
   """Merges a single protocol message field into a message.
   """Merges a single protocol message field into a message.
 
 

+ 22 - 0
src/Makefile.am

@@ -40,6 +40,7 @@ MAINTAINERCLEANFILES =   \
 nobase_include_HEADERS =                                        \
 nobase_include_HEADERS =                                        \
   google/protobuf/stubs/atomic_sequence_num.h                   \
   google/protobuf/stubs/atomic_sequence_num.h                   \
   google/protobuf/stubs/atomicops.h                             \
   google/protobuf/stubs/atomicops.h                             \
+  google/protobuf/stubs/atomicops_internals_aix.h               \
   google/protobuf/stubs/atomicops_internals_arm64_gcc.h         \
   google/protobuf/stubs/atomicops_internals_arm64_gcc.h         \
   google/protobuf/stubs/atomicops_internals_arm_gcc.h           \
   google/protobuf/stubs/atomicops_internals_arm_gcc.h           \
   google/protobuf/stubs/atomicops_internals_arm_qnx.h           \
   google/protobuf/stubs/atomicops_internals_arm_qnx.h           \
@@ -71,6 +72,11 @@ nobase_include_HEADERS =                                        \
   google/protobuf/generated_enum_reflection.h                   \
   google/protobuf/generated_enum_reflection.h                   \
   google/protobuf/generated_message_reflection.h                \
   google/protobuf/generated_message_reflection.h                \
   google/protobuf/generated_message_util.h                      \
   google/protobuf/generated_message_util.h                      \
+  google/protobuf/map_entry.h                                   \
+  google/protobuf/map_field.h                                   \
+  google/protobuf/map_field_inl.h                               \
+  google/protobuf/map.h                                         \
+  google/protobuf/map_type_handler.h                            \
   google/protobuf/message.h                                     \
   google/protobuf/message.h                                     \
   google/protobuf/message_lite.h                                \
   google/protobuf/message_lite.h                                \
   google/protobuf/metadata.h                                    \
   google/protobuf/metadata.h                                    \
@@ -120,6 +126,7 @@ libprotobuf_lite_la_SOURCES =                                  \
   google/protobuf/arenastring.cc                               \
   google/protobuf/arenastring.cc                               \
   google/protobuf/extension_set.cc                             \
   google/protobuf/extension_set.cc                             \
   google/protobuf/generated_message_util.cc                    \
   google/protobuf/generated_message_util.cc                    \
+  google/protobuf/map_field.cc                                 \
   google/protobuf/message_lite.cc                              \
   google/protobuf/message_lite.cc                              \
   google/protobuf/repeated_field.cc                            \
   google/protobuf/repeated_field.cc                            \
   google/protobuf/wire_format_lite.cc                          \
   google/protobuf/wire_format_lite.cc                          \
@@ -182,6 +189,8 @@ libprotoc_la_SOURCES =                                         \
   google/protobuf/compiler/cpp/cpp_generator.cc                \
   google/protobuf/compiler/cpp/cpp_generator.cc                \
   google/protobuf/compiler/cpp/cpp_helpers.cc                  \
   google/protobuf/compiler/cpp/cpp_helpers.cc                  \
   google/protobuf/compiler/cpp/cpp_helpers.h                   \
   google/protobuf/compiler/cpp/cpp_helpers.h                   \
+  google/protobuf/compiler/cpp/cpp_map_field.cc                \
+  google/protobuf/compiler/cpp/cpp_map_field.h                 \
   google/protobuf/compiler/cpp/cpp_message.cc                  \
   google/protobuf/compiler/cpp/cpp_message.cc                  \
   google/protobuf/compiler/cpp/cpp_message.h                   \
   google/protobuf/compiler/cpp/cpp_message.h                   \
   google/protobuf/compiler/cpp/cpp_message_field.cc            \
   google/protobuf/compiler/cpp/cpp_message_field.cc            \
@@ -239,6 +248,9 @@ protoc_SOURCES = google/protobuf/compiler/main.cc
 # Tests ==============================================================
 # Tests ==============================================================
 
 
 protoc_inputs =                                                \
 protoc_inputs =                                                \
+  google/protobuf/map_lite_unittest.proto                      \
+  google/protobuf/map_proto2_unittest.proto                    \
+  google/protobuf/map_unittest.proto                           \
   google/protobuf/unittest.proto                               \
   google/protobuf/unittest.proto                               \
   google/protobuf/unittest_arena.proto                         \
   google/protobuf/unittest_arena.proto                         \
   google/protobuf/unittest_custom_options.proto                \
   google/protobuf/unittest_custom_options.proto                \
@@ -292,6 +304,12 @@ protoc_lite_outputs =                                          \
 
 
 protoc_outputs =                                               \
 protoc_outputs =                                               \
   $(protoc_lite_outputs)                                       \
   $(protoc_lite_outputs)                                       \
+  google/protobuf/map_lite_unittest.pb.cc                      \
+  google/protobuf/map_lite_unittest.pb.h                       \
+  google/protobuf/map_proto2_unittest.pb.cc                    \
+  google/protobuf/map_proto2_unittest.pb.h                     \
+  google/protobuf/map_unittest.pb.cc                           \
+  google/protobuf/map_unittest.pb.h                            \
   google/protobuf/unittest.pb.cc                               \
   google/protobuf/unittest.pb.cc                               \
   google/protobuf/unittest.pb.h                                \
   google/protobuf/unittest.pb.h                                \
   google/protobuf/unittest_arena.pb.cc                         \
   google/protobuf/unittest_arena.pb.cc                         \
@@ -351,6 +369,8 @@ endif
 $(protoc_outputs): unittest_proto_middleman
 $(protoc_outputs): unittest_proto_middleman
 
 
 COMMON_TEST_SOURCES =                                          \
 COMMON_TEST_SOURCES =                                          \
+  google/protobuf/map_test_util.cc                             \
+  google/protobuf/map_test_util.h                              \
   google/protobuf/test_util.cc                                 \
   google/protobuf/test_util.cc                                 \
   google/protobuf/test_util.h                                  \
   google/protobuf/test_util.h                                  \
   google/protobuf/testing/googletest.cc                        \
   google/protobuf/testing/googletest.cc                        \
@@ -385,6 +405,8 @@ protobuf_test_SOURCES =                                        \
   google/protobuf/dynamic_message_unittest.cc                  \
   google/protobuf/dynamic_message_unittest.cc                  \
   google/protobuf/extension_set_unittest.cc                    \
   google/protobuf/extension_set_unittest.cc                    \
   google/protobuf/generated_message_reflection_unittest.cc     \
   google/protobuf/generated_message_reflection_unittest.cc     \
+  google/protobuf/map_field_test.cc                            \
+  google/protobuf/map_test.cc                                  \
   google/protobuf/message_unittest.cc                          \
   google/protobuf/message_unittest.cc                          \
   google/protobuf/no_field_presence_test.cc                    \
   google/protobuf/no_field_presence_test.cc                    \
   google/protobuf/preserve_unknown_enum_test.cc                \
   google/protobuf/preserve_unknown_enum_test.cc                \

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

@@ -138,7 +138,7 @@ void* Arena::AllocateAligned(size_t n) {
     // for this thread.
     // for this thread.
     if (!owns_first_block_ && b->next == NULL) {
     if (!owns_first_block_ && b->next == NULL) {
       MutexLock l(&blocks_lock_);
       MutexLock l(&blocks_lock_);
-      if (b->owner == &b->owner) {
+      if (b->owner == &b->owner && b->avail() >= n) {
         b->owner = me;
         b->owner = me;
         SetThreadCacheBlock(b);
         SetThreadCacheBlock(b);
         return AllocFromBlock(b, n);
         return AllocFromBlock(b, n);

+ 39 - 2
src/google/protobuf/arena_unittest.cc

@@ -30,14 +30,26 @@
 
 
 #include <google/protobuf/arena.h>
 #include <google/protobuf/arena.h>
 
 
+#include <algorithm>
+#include <cstring>
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
 #include <string>
 #include <string>
 #include <vector>
 #include <vector>
 
 
+#include <google/protobuf/stubs/common.h>
 #include <google/protobuf/test_util.h>
 #include <google/protobuf/test_util.h>
+#include <google/protobuf/unittest.pb.h>
 #include <google/protobuf/unittest_arena.pb.h>
 #include <google/protobuf/unittest_arena.pb.h>
 #include <google/protobuf/unittest_no_arena.pb.h>
 #include <google/protobuf/unittest_no_arena.pb.h>
-#include <google/protobuf/unittest.pb.h>
-#include <google/protobuf/testing/googletest.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/extension_set.h>
+#include <google/protobuf/message.h>
+#include <google/protobuf/message_lite.h>
+#include <google/protobuf/repeated_field.h>
+#include <google/protobuf/unknown_field_set.h>
 #include <gtest/gtest.h>
 #include <gtest/gtest.h>
 
 
 
 
@@ -110,6 +122,31 @@ TEST(ArenaTest, BasicCreate) {
   EXPECT_EQ(2, notifier.GetCount());
   EXPECT_EQ(2, notifier.GetCount());
 }
 }
 
 
+TEST(ArenaTest, InitialBlockTooSmall) {
+  // Construct a small (64 byte) initial block of memory to be used by the
+  // arena allocator; then, allocate an object which will not fit in the
+  // initial block.
+  std::vector<char> arena_block(64);
+  ArenaOptions options;
+  options.initial_block = arena_block.data();
+  options.initial_block_size = arena_block.size();
+  Arena arena(options);
+
+  char* p = ::google::protobuf::Arena::CreateArray<char>(&arena, 96);
+  uintptr_t allocation = reinterpret_cast<uintptr_t>(p);
+
+  // Ensure that the arena allocator did not return memory pointing into the
+  // initial block of memory.
+  uintptr_t arena_start = reinterpret_cast<uintptr_t>(arena_block.data());
+  uintptr_t arena_end = arena_start + arena_block.size();
+  EXPECT_FALSE(allocation >= arena_start && allocation < arena_end);
+
+  // Write to the memory we allocated; this should (but is not guaranteed to)
+  // trigger a check for heap corruption if the object was allocated from the
+  // initially-provided block.
+  memset(p, '\0', 128);
+}
+
 TEST(ArenaTest, Parsing) {
 TEST(ArenaTest, Parsing) {
   TestAllTypes original;
   TestAllTypes original;
   TestUtil::SetAllFields(&original);
   TestUtil::SetAllFields(&original);

+ 10 - 0
src/google/protobuf/arenastring.cc

@@ -38,6 +38,16 @@ namespace protobuf {
 namespace internal {
 namespace internal {
 
 
 
 
+void ArenaStringPtr::AssignWithDefault(const ::std::string* default_value,
+                                       ArenaStringPtr value) {
+  const ::std::string* me = *UnsafeRawStringPointer();
+  const ::std::string* other = *value.UnsafeRawStringPointer();
+  // If the pointers are the same then do nothing.
+  if (me != other) {
+    SetNoArena(default_value, value.GetNoArena(default_value));
+  }
+}
+
 }  // namespace internal
 }  // namespace internal
 }  // namespace protobuf
 }  // namespace protobuf
 }  // namespace google
 }  // namespace google

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

@@ -214,6 +214,8 @@ struct ArenaStringPtr {
     }
     }
   }
   }
 
 
+  void AssignWithDefault(const ::std::string* default_value, ArenaStringPtr value);
+
   inline const ::std::string& GetNoArena(const ::std::string* default_value) const {
   inline const ::std::string& GetNoArena(const ::std::string* default_value) const {
     return *ptr_;
     return *ptr_;
   }
   }

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

@@ -300,7 +300,7 @@ class CommandLineInterface::MemoryOutputStream
   bool append_mode_;
   bool append_mode_;
 
 
   // StringOutputStream writing to data_.
   // StringOutputStream writing to data_.
-  scoped_ptr<io::StringOutputStream> inner_;
+  google::protobuf::scoped_ptr<io::StringOutputStream> inner_;
 };
 };
 
 
 // -------------------------------------------------------------------
 // -------------------------------------------------------------------
@@ -1321,7 +1321,7 @@ bool CommandLineInterface::GeneratePluginOutput(
 
 
   // Write the files.  We do this even if there was a generator error in order
   // Write the files.  We do this even if there was a generator error in order
   // to match the behavior of a compiled-in generator.
   // to match the behavior of a compiled-in generator.
-  scoped_ptr<io::ZeroCopyOutputStream> current_output;
+  google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> current_output;
   for (int i = 0; i < response.file_size(); i++) {
   for (int i = 0; i < response.file_size(); i++) {
     const CodeGeneratorResponse::File& output_file = response.file(i);
     const CodeGeneratorResponse::File& output_file = response.file(i);
 
 
@@ -1370,7 +1370,7 @@ bool CommandLineInterface::EncodeOrDecode(const DescriptorPool* pool) {
   }
   }
 
 
   DynamicMessageFactory dynamic_factory(pool);
   DynamicMessageFactory dynamic_factory(pool);
-  scoped_ptr<Message> message(dynamic_factory.GetPrototype(type)->New());
+  google::protobuf::scoped_ptr<Message> message(dynamic_factory.GetPrototype(type)->New());
 
 
   if (mode_ == MODE_ENCODE) {
   if (mode_ == MODE_ENCODE) {
     SetFdToTextMode(STDIN_FILENO);
     SetFdToTextMode(STDIN_FILENO);

+ 3 - 3
src/google/protobuf/compiler/command_line_interface_unittest.cc

@@ -261,7 +261,7 @@ void CommandLineInterfaceTest::SetUp() {
 
 
 void CommandLineInterfaceTest::TearDown() {
 void CommandLineInterfaceTest::TearDown() {
   // Delete the temp directory.
   // Delete the temp directory.
-  if (File::Exists(temp_directory_)) {
+  if (FileExists(temp_directory_)) {
     File::DeleteRecursively(temp_directory_, NULL, NULL);
     File::DeleteRecursively(temp_directory_, NULL, NULL);
   }
   }
 
 
@@ -312,7 +312,7 @@ void CommandLineInterfaceTest::Run(const string& command) {
     }
     }
   }
   }
 
 
-  scoped_array<const char*> argv(new const char* [args.size()]);
+  google::protobuf::scoped_array<const char * > argv(new const char* [args.size()]);
 
 
   for (int i = 0; i < args.size(); i++) {
   for (int i = 0; i < args.size(); i++) {
     args[i] = StringReplace(args[i], "$tmpdir", temp_directory_, true);
     args[i] = StringReplace(args[i], "$tmpdir", temp_directory_, true);
@@ -1550,7 +1550,7 @@ class EncodeDecodeTest : public testing::Test {
     SplitStringUsing(command, " ", &args);
     SplitStringUsing(command, " ", &args);
     args.push_back("--proto_path=" + TestSourceDir());
     args.push_back("--proto_path=" + TestSourceDir());
 
 
-    scoped_array<const char*> argv(new const char* [args.size()]);
+    google::protobuf::scoped_array<const char * > argv(new const char* [args.size()]);
     for (int i = 0; i < args.size(); i++) {
     for (int i = 0; i < args.size(); i++) {
       argv[i] = args[i].c_str();
       argv[i] = args[i].c_str();
     }
     }

+ 2 - 2
src/google/protobuf/compiler/cpp/cpp_enum.cc

@@ -106,8 +106,8 @@ void EnumGenerator::GenerateDefinition(io::Printer* printer) {
     // INT32_MIN and INT32_MAX
     // INT32_MIN and INT32_MAX
     if (descriptor_->value_count() > 0) printer->Print(",\n");
     if (descriptor_->value_count() > 0) printer->Print(",\n");
     printer->Print(vars,
     printer->Print(vars,
-        "$classname$_$prefix$INT_MIN_SENTINEL_DO_NOT_USE_ = INT32_MIN,\n"
-        "$classname$_$prefix$INT_MAX_SENTINEL_DO_NOT_USE_ = INT32_MAX");
+        "$classname$_$prefix$INT_MIN_SENTINEL_DO_NOT_USE_ = ::google::protobuf::kint32min,\n"
+        "$classname$_$prefix$INT_MAX_SENTINEL_DO_NOT_USE_ = ::google::protobuf::kint32max");
   }
   }
 
 
   printer->Outdent();
   printer->Outdent();

+ 17 - 3
src/google/protobuf/compiler/cpp/cpp_field.cc

@@ -42,6 +42,7 @@
 #include <google/protobuf/compiler/cpp/cpp_primitive_field.h>
 #include <google/protobuf/compiler/cpp/cpp_primitive_field.h>
 #include <google/protobuf/compiler/cpp/cpp_string_field.h>
 #include <google/protobuf/compiler/cpp/cpp_string_field.h>
 #include <google/protobuf/compiler/cpp/cpp_enum_field.h>
 #include <google/protobuf/compiler/cpp/cpp_enum_field.h>
+#include <google/protobuf/compiler/cpp/cpp_map_field.h>
 #include <google/protobuf/compiler/cpp/cpp_message_field.h>
 #include <google/protobuf/compiler/cpp/cpp_message_field.h>
 #include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/wire_format.h>
 #include <google/protobuf/wire_format.h>
@@ -65,6 +66,12 @@ void SetCommonFieldVariables(const FieldDescriptor* descriptor,
   (*variables)["classname"] = ClassName(FieldScope(descriptor), false);
   (*variables)["classname"] = ClassName(FieldScope(descriptor), false);
   (*variables)["declared_type"] = DeclaredTypeMethodName(descriptor->type());
   (*variables)["declared_type"] = DeclaredTypeMethodName(descriptor->type());
 
 
+  // non_null_ptr_to_name is usable only if has_$name$ is true.  It yields a
+  // pointer that will not be NULL.  Subclasses of FieldGenerator may set
+  // (*variables)["non_null_ptr_to_name"] differently.
+  (*variables)["non_null_ptr_to_name"] =
+      StrCat("&this->", FieldName(descriptor), "()");
+
   (*variables)["tag_size"] = SimpleItoa(
   (*variables)["tag_size"] = SimpleItoa(
     WireFormat::TagSize(descriptor->number(), descriptor->type()));
     WireFormat::TagSize(descriptor->number(), descriptor->type()));
   (*variables)["deprecation"] = descriptor->options().deprecated()
   (*variables)["deprecation"] = descriptor->options().deprecated()
@@ -89,8 +96,11 @@ void SetCommonFieldVariables(const FieldDescriptor* descriptor,
 
 
 void SetCommonOneofFieldVariables(const FieldDescriptor* descriptor,
 void SetCommonOneofFieldVariables(const FieldDescriptor* descriptor,
                                   map<string, string>* variables) {
                                   map<string, string>* variables) {
-  (*variables)["oneof_prefix"] = descriptor->containing_oneof()->name() + "_.";
+  const string prefix = descriptor->containing_oneof()->name() + "_.";
+  (*variables)["oneof_prefix"] = prefix;
   (*variables)["oneof_name"] = descriptor->containing_oneof()->name();
   (*variables)["oneof_name"] = descriptor->containing_oneof()->name();
+  (*variables)["non_null_ptr_to_name"] =
+      StrCat(prefix, (*variables)["name"], "_");
 }
 }
 
 
 FieldGenerator::~FieldGenerator() {}
 FieldGenerator::~FieldGenerator() {}
@@ -111,7 +121,7 @@ FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor,
                                      const Options& options)
                                      const Options& options)
     : descriptor_(descriptor),
     : descriptor_(descriptor),
       field_generators_(
       field_generators_(
-          new scoped_ptr<FieldGenerator>[descriptor->field_count()]) {
+          new google::protobuf::scoped_ptr<FieldGenerator>[descriptor->field_count()]) {
   // Construct all the FieldGenerators.
   // Construct all the FieldGenerators.
   for (int i = 0; i < descriptor->field_count(); i++) {
   for (int i = 0; i < descriptor->field_count(); i++) {
     field_generators_[i].reset(MakeGenerator(descriptor->field(i), options));
     field_generators_[i].reset(MakeGenerator(descriptor->field(i), options));
@@ -123,7 +133,11 @@ FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field,
   if (field->is_repeated()) {
   if (field->is_repeated()) {
     switch (field->cpp_type()) {
     switch (field->cpp_type()) {
       case FieldDescriptor::CPPTYPE_MESSAGE:
       case FieldDescriptor::CPPTYPE_MESSAGE:
-        return new RepeatedMessageFieldGenerator(field, options);
+        if (field->is_map()) {
+          return new MapFieldGenerator(field, options);
+        } else {
+          return new RepeatedMessageFieldGenerator(field, options);
+        }
       case FieldDescriptor::CPPTYPE_STRING:
       case FieldDescriptor::CPPTYPE_STRING:
         switch (field->options().ctype()) {
         switch (field->options().ctype()) {
           default:  // RepeatedStringFieldGenerator handles unknown ctypes.
           default:  // RepeatedStringFieldGenerator handles unknown ctypes.

+ 1 - 1
src/google/protobuf/compiler/cpp/cpp_field.h

@@ -182,7 +182,7 @@ class FieldGeneratorMap {
 
 
  private:
  private:
   const Descriptor* descriptor_;
   const Descriptor* descriptor_;
-  scoped_array<scoped_ptr<FieldGenerator> > field_generators_;
+  google::protobuf::scoped_array<google::protobuf::scoped_ptr<FieldGenerator> > field_generators_;
 
 
   static FieldGenerator* MakeGenerator(const FieldDescriptor* field,
   static FieldGenerator* MakeGenerator(const FieldDescriptor* field,
                                        const Options& options);
                                        const Options& options);

+ 22 - 5
src/google/protobuf/compiler/cpp/cpp_file.cc

@@ -59,13 +59,13 @@ namespace cpp {
 FileGenerator::FileGenerator(const FileDescriptor* file, const Options& options)
 FileGenerator::FileGenerator(const FileDescriptor* file, const Options& options)
     : file_(file),
     : file_(file),
       message_generators_(
       message_generators_(
-          new scoped_ptr<MessageGenerator>[file->message_type_count()]),
+          new google::protobuf::scoped_ptr<MessageGenerator>[file->message_type_count()]),
       enum_generators_(
       enum_generators_(
-          new scoped_ptr<EnumGenerator>[file->enum_type_count()]),
+          new google::protobuf::scoped_ptr<EnumGenerator>[file->enum_type_count()]),
       service_generators_(
       service_generators_(
-          new scoped_ptr<ServiceGenerator>[file->service_count()]),
+          new google::protobuf::scoped_ptr<ServiceGenerator>[file->service_count()]),
       extension_generators_(
       extension_generators_(
-          new scoped_ptr<ExtensionGenerator>[file->extension_count()]),
+          new google::protobuf::scoped_ptr<ExtensionGenerator>[file->extension_count()]),
       options_(options) {
       options_(options) {
 
 
   for (int i = 0; i < file->message_type_count(); i++) {
   for (int i = 0; i < file->message_type_count(); i++) {
@@ -105,7 +105,6 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
     "#define PROTOBUF_$filename_identifier$__INCLUDED\n"
     "#define PROTOBUF_$filename_identifier$__INCLUDED\n"
     "\n"
     "\n"
     "#include <string>\n"
     "#include <string>\n"
-    "#include <stdint.h>\n"  // INT32_MIN, INT32_MAX
     "\n",
     "\n",
     "filename", file_->name(),
     "filename", file_->name(),
     "filename_identifier", filename_identifier);
     "filename_identifier", filename_identifier);
@@ -151,6 +150,11 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
   printer->Print(
   printer->Print(
     "#include <google/protobuf/repeated_field.h>\n"
     "#include <google/protobuf/repeated_field.h>\n"
     "#include <google/protobuf/extension_set.h>\n");
     "#include <google/protobuf/extension_set.h>\n");
+  if (HasMapFields(file_)) {
+    printer->Print(
+      "#include <google/protobuf/map.h>\n"
+      "#include <google/protobuf/map_field_inl.h>\n");
+  }
 
 
   if (HasDescriptorMethods(file_) && HasEnumDefinitions(file_)) {
   if (HasDescriptorMethods(file_) && HasEnumDefinitions(file_)) {
     printer->Print(
     printer->Print(
@@ -396,6 +400,19 @@ void FileGenerator::GenerateSource(io::Printer* printer) {
 
 
   // Generate classes.
   // Generate classes.
   for (int i = 0; i < file_->message_type_count(); i++) {
   for (int i = 0; i < file_->message_type_count(); i++) {
+    if (i == 0 && HasGeneratedMethods(file_)) {
+      printer->Print(
+          "\n"
+          "namespace {\n"
+          "\n"
+          "static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD;\n"
+          "static void MergeFromFail(int line) {\n"
+          "  GOOGLE_CHECK(false) << __FILE__ << \":\" << line;\n"
+          "}\n"
+          "\n"
+          "}  // namespace\n"
+          "\n");
+    }
     printer->Print("\n");
     printer->Print("\n");
     printer->Print(kThickSeparator);
     printer->Print(kThickSeparator);
     printer->Print("\n");
     printer->Print("\n");

+ 4 - 4
src/google/protobuf/compiler/cpp/cpp_file.h

@@ -82,10 +82,10 @@ class FileGenerator {
 
 
   const FileDescriptor* file_;
   const FileDescriptor* file_;
 
 
-  scoped_array<scoped_ptr<MessageGenerator> > message_generators_;
-  scoped_array<scoped_ptr<EnumGenerator> > enum_generators_;
-  scoped_array<scoped_ptr<ServiceGenerator> > service_generators_;
-  scoped_array<scoped_ptr<ExtensionGenerator> > extension_generators_;
+  google::protobuf::scoped_array<google::protobuf::scoped_ptr<MessageGenerator> > message_generators_;
+  google::protobuf::scoped_array<google::protobuf::scoped_ptr<EnumGenerator> > enum_generators_;
+  google::protobuf::scoped_array<google::protobuf::scoped_ptr<ServiceGenerator> > service_generators_;
+  google::protobuf::scoped_array<google::protobuf::scoped_ptr<ExtensionGenerator> > extension_generators_;
 
 
   // E.g. if the package is foo.bar, package_parts_ is {"foo", "bar"}.
   // E.g. if the package is foo.bar, package_parts_ is {"foo", "bar"}.
   vector<string> package_parts_;
   vector<string> package_parts_;

+ 2 - 2
src/google/protobuf/compiler/cpp/cpp_generator.cc

@@ -105,7 +105,7 @@ bool CppGenerator::Generate(const FileDescriptor* file,
 
 
   // Generate header.
   // Generate header.
   {
   {
-    scoped_ptr<io::ZeroCopyOutputStream> output(
+    google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
         generator_context->Open(basename + ".h"));
         generator_context->Open(basename + ".h"));
     io::Printer printer(output.get(), '$');
     io::Printer printer(output.get(), '$');
     file_generator.GenerateHeader(&printer);
     file_generator.GenerateHeader(&printer);
@@ -113,7 +113,7 @@ bool CppGenerator::Generate(const FileDescriptor* file,
 
 
   // Generate cc file.
   // Generate cc file.
   {
   {
-    scoped_ptr<io::ZeroCopyOutputStream> output(
+    google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
         generator_context->Open(basename + ".cc"));
         generator_context->Open(basename + ".cc"));
     io::Printer printer(output.get(), '$');
     io::Printer printer(output.get(), '$');
     file_generator.GenerateSource(&printer);
     file_generator.GenerateSource(&printer);

+ 19 - 0
src/google/protobuf/compiler/cpp/cpp_helpers.cc

@@ -453,6 +453,25 @@ void PrintHandlingOptionalStaticInitializers(
 }
 }
 
 
 
 
+static bool HasMapFields(const Descriptor* descriptor) {
+  for (int i = 0; i < descriptor->field_count(); ++i) {
+    if (descriptor->field(i)->is_map()) {
+      return true;
+    }
+  }
+  for (int i = 0; i < descriptor->nested_type_count(); ++i) {
+    if (HasMapFields(descriptor->nested_type(i))) return true;
+  }
+  return false;
+}
+
+bool HasMapFields(const FileDescriptor* file) {
+  for (int i = 0; i < file->message_type_count(); ++i) {
+    if (HasMapFields(file->message_type(i))) return true;
+  }
+  return false;
+}
+
 static bool HasEnumDefinitions(const Descriptor* message_type) {
 static bool HasEnumDefinitions(const Descriptor* message_type) {
   if (message_type->enum_type_count() > 0) return true;
   if (message_type->enum_type_count() > 0) return true;
   for (int i = 0; i < message_type->nested_type_count(); ++i) {
   for (int i = 0; i < message_type->nested_type_count(); ++i) {

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

@@ -149,6 +149,10 @@ inline bool UseUnknownFieldSet(const FileDescriptor* file) {
 }
 }
 
 
 
 
+// Does the file have any map fields, necessitating the file to include
+// map_field_inl.h and map.h.
+bool HasMapFields(const FileDescriptor* file);
+
 // Does this file have any enum type definitions?
 // Does this file have any enum type definitions?
 bool HasEnumDefinitions(const FileDescriptor* file);
 bool HasEnumDefinitions(const FileDescriptor* file);
 
 
@@ -200,6 +204,10 @@ void PrintHandlingOptionalStaticInitializers(
     const char* without_static_init);
     const char* without_static_init);
 
 
 
 
+inline bool IsMapEntryMessage(const Descriptor* descriptor) {
+  return descriptor->options().map_entry();
+}
+
 // Returns true if the field's CPPTYPE is string or message.
 // Returns true if the field's CPPTYPE is string or message.
 bool IsStringOrMessage(const FieldDescriptor* field);
 bool IsStringOrMessage(const FieldDescriptor* field);
 
 
@@ -216,7 +224,7 @@ inline bool HasPreservingUnknownEnumSemantics(const FileDescriptor* file) {
 }
 }
 
 
 inline bool SupportsArenas(const FileDescriptor* file) {
 inline bool SupportsArenas(const FileDescriptor* file) {
-  return true;
+  return file->options().cc_enable_arenas();
 }
 }
 
 
 inline bool SupportsArenas(const Descriptor* desc) {
 inline bool SupportsArenas(const Descriptor* desc) {

+ 255 - 0
src/google/protobuf/compiler/cpp/cpp_map_field.cc

@@ -0,0 +1,255 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <google/protobuf/compiler/cpp/cpp_map_field.h>
+#include <google/protobuf/compiler/cpp/cpp_helpers.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+bool IsProto3Field(const FieldDescriptor* field_descriptor) {
+  const FileDescriptor* file_descriptor = field_descriptor->file();
+  return file_descriptor->syntax() == FileDescriptor::SYNTAX_PROTO3;
+}
+
+void SetMessageVariables(const FieldDescriptor* descriptor,
+                         map<string, string>* variables,
+                         const Options& options) {
+  SetCommonFieldVariables(descriptor, variables, options);
+  (*variables)["type"] = FieldMessageTypeName(descriptor);
+  (*variables)["stream_writer"] = (*variables)["declared_type"] +
+      (HasFastArraySerialization(descriptor->message_type()->file()) ?
+       "MaybeToArray" :
+       "");
+  (*variables)["full_name"] = descriptor->full_name();
+
+  const FieldDescriptor* key =
+      descriptor->message_type()->FindFieldByName("key");
+  const FieldDescriptor* val =
+      descriptor->message_type()->FindFieldByName("value");
+  (*variables)["key_cpp"] = PrimitiveTypeName(key->cpp_type());
+  switch (val->cpp_type()) {
+    case FieldDescriptor::CPPTYPE_MESSAGE:
+      (*variables)["val_cpp"] = FieldMessageTypeName(val);
+      (*variables)["wrapper"] = "EntryWrapper";
+      break;
+    case FieldDescriptor::CPPTYPE_ENUM:
+      (*variables)["val_cpp"] = ClassName(val->enum_type(), false);
+      (*variables)["wrapper"] = "EnumEntryWrapper";
+      break;
+    default:
+      (*variables)["val_cpp"] = PrimitiveTypeName(val->cpp_type());
+      (*variables)["wrapper"] = "EntryWrapper";
+  }
+  (*variables)["key_type"] =
+      "::google::protobuf::FieldDescriptor::TYPE_" +
+      ToUpper(DeclaredTypeMethodName(key->type()));
+  (*variables)["val_type"] =
+      "::google::protobuf::FieldDescriptor::TYPE_" +
+      ToUpper(DeclaredTypeMethodName(val->type()));
+  (*variables)["map_classname"] = ClassName(descriptor->message_type(), false);
+  (*variables)["number"] = Int32ToString(descriptor->number());
+
+  if (!IsProto3Field(descriptor) &&
+      val->type() == FieldDescriptor::TYPE_ENUM) {
+    const EnumValueDescriptor* default_value = val->default_value_enum();
+    (*variables)["default_enum_value"] = Int32ToString(default_value->number());
+  } else {
+    (*variables)["default_enum_value"] = "0";
+  }
+}
+
+MapFieldGenerator::
+MapFieldGenerator(const FieldDescriptor* descriptor,
+                              const Options& options)
+    : descriptor_(descriptor) {
+  SetMessageVariables(descriptor, &variables_, options);
+}
+
+MapFieldGenerator::~MapFieldGenerator() {}
+
+void MapFieldGenerator::
+GeneratePrivateMembers(io::Printer* printer) const {
+  printer->Print(variables_,
+      "typedef ::google::protobuf::internal::MapEntry<\n"
+      "    $key_cpp$, $val_cpp$,\n"
+      "    $key_type$,\n"
+      "    $val_type$, $default_enum_value$>\n"
+      "    $map_classname$;\n"
+      "::google::protobuf::internal::MapField< $key_cpp$, $val_cpp$,"
+      "$key_type$, $val_type$, $default_enum_value$ > $name$_;\n");
+}
+
+void MapFieldGenerator::
+GenerateAccessorDeclarations(io::Printer* printer) const {
+  printer->Print(variables_,
+      "inline const ::google::protobuf::Map< $key_cpp$, $val_cpp$ >&\n"
+      "    $name$() const$deprecation$;\n"
+      "inline ::google::protobuf::Map< $key_cpp$, $val_cpp$ >*\n"
+      "    mutable_$name$()$deprecation$;\n");
+}
+
+void MapFieldGenerator::
+GenerateInlineAccessorDefinitions(io::Printer* printer) const {
+  printer->Print(variables_,
+      "inline const ::google::protobuf::Map< $key_cpp$, $val_cpp$ >&\n"
+      "$classname$::$name$() const {\n"
+      "  // @@protoc_insertion_point(field_map:$full_name$)\n"
+      "  return $name$_.GetMap();\n"
+      "}\n"
+      "inline ::google::protobuf::Map< $key_cpp$, $val_cpp$ >*\n"
+      "$classname$::mutable_$name$() {\n"
+      "  // @@protoc_insertion_point(field_mutable_map:$full_name$)\n"
+      "  return $name$_.MutableMap();\n"
+      "}\n");
+}
+
+void MapFieldGenerator::
+GenerateClearingCode(io::Printer* printer) const {
+  printer->Print(variables_, "$name$_.Clear();\n");
+}
+
+void MapFieldGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+  printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n");
+}
+
+void MapFieldGenerator::
+GenerateSwappingCode(io::Printer* printer) const {
+  printer->Print(variables_, "$name$_.Swap(&other->$name$_);\n");
+}
+
+void MapFieldGenerator::
+GenerateConstructorCode(io::Printer* printer) const {
+  if (HasDescriptorMethods(descriptor_->file())) {
+    printer->Print(variables_,
+        "$name$_.SetAssignDescriptorCallback(\n"
+        "    protobuf_AssignDescriptorsOnce);\n"
+        "$name$_.SetEntryDescriptor(\n"
+        "    &$type$_descriptor_);\n");
+  }
+}
+
+void MapFieldGenerator::
+GenerateMergeFromCodedStream(io::Printer* printer) const {
+  const FieldDescriptor* value_field =
+      descriptor_->message_type()->FindFieldByName("value");
+  printer->Print(variables_,
+      "::google::protobuf::scoped_ptr<$map_classname$> entry($name$_.NewEntry());\n");
+
+  if (IsProto3Field(descriptor_) ||
+      value_field->type() != FieldDescriptor::TYPE_ENUM) {
+    printer->Print(variables_,
+        "DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(\n"
+        "    input, entry.get()));\n");
+    switch (value_field->cpp_type()) {
+      case FieldDescriptor::CPPTYPE_MESSAGE:
+        printer->Print(variables_,
+            "(*mutable_$name$())[entry->key()].Swap("
+            "entry->mutable_value());\n");
+        break;
+      case FieldDescriptor::CPPTYPE_ENUM:
+        printer->Print(variables_,
+            "(*mutable_$name$())[entry->key()] =\n"
+            "    static_cast<$val_cpp$>(*entry->mutable_value());\n");
+        break;
+      default:
+        printer->Print(variables_,
+            "(*mutable_$name$())[entry->key()] = *entry->mutable_value();\n");
+        break;
+    }
+  } else {
+    printer->Print(variables_,
+        "{\n"
+        "  ::std::string data;\n"
+        "  DO_(::google::protobuf::internal::WireFormatLite::ReadString(input, &data));\n"
+        "  DO_(entry->ParseFromString(data));\n"
+        "  if ($val_cpp$_IsValid(*entry->mutable_value())) {\n"
+        "    (*mutable_$name$())[entry->key()] =\n"
+        "        static_cast<$val_cpp$>(*entry->mutable_value());\n"
+        "  } else {\n"
+        "    mutable_unknown_fields()->AddLengthDelimited($number$, data);\n"
+        "  }\n"
+        "}\n");
+  }
+}
+
+void MapFieldGenerator::
+GenerateSerializeWithCachedSizes(io::Printer* printer) const {
+  printer->Print(variables_,
+      "{\n"
+      "  ::google::protobuf::scoped_ptr<$map_classname$> entry;\n"
+      "  for (::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_iterator\n"
+      "      it = $name$().begin(); it != $name$().end(); ++it) {\n"
+      "    entry.reset($name$_.New$wrapper$(it->first, it->second));\n"
+      "    ::google::protobuf::internal::WireFormatLite::Write$stream_writer$(\n"
+      "        $number$, *entry, output);\n"
+      "  }\n"
+      "}\n");
+}
+
+void MapFieldGenerator::
+GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
+  printer->Print(variables_,
+      "{\n"
+      "  ::google::protobuf::scoped_ptr<$map_classname$> entry;\n"
+      "  for (::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_iterator\n"
+      "      it = $name$().begin(); it != $name$().end(); ++it) {\n"
+      "    entry.reset($name$_.New$wrapper$(it->first, it->second));\n"
+      "    target = ::google::protobuf::internal::WireFormatLite::\n"
+      "        Write$declared_type$NoVirtualToArray(\n"
+      "            $number$, *entry, target);\n"
+      "  }\n"
+      "}\n");
+}
+
+void MapFieldGenerator::
+GenerateByteSize(io::Printer* printer) const {
+  printer->Print(variables_,
+      "total_size += $tag_size$ * this->$name$_size();\n"
+      "{\n"
+      "  ::google::protobuf::scoped_ptr<$map_classname$> entry;\n"
+      "  for (::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_iterator\n"
+      "      it = $name$().begin(); it != $name$().end(); ++it) {\n"
+      "    entry.reset($name$_.New$wrapper$(it->first, it->second));\n"
+      "    total_size += ::google::protobuf::internal::WireFormatLite::\n"
+      "        $declared_type$SizeNoVirtual(*entry);\n"
+      "  }\n"
+      "}\n");
+}
+
+}  // namespace cpp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google

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

@@ -0,0 +1,75 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_MAP_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_CPP_MAP_FIELD_H__
+
+#include <map>
+#include <string>
+
+#include <google/protobuf/compiler/cpp/cpp_message_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+class MapFieldGenerator : public FieldGenerator {
+ public:
+  explicit MapFieldGenerator(const FieldDescriptor* descriptor,
+                             const Options& options);
+  ~MapFieldGenerator();
+
+  // implements FieldGenerator ---------------------------------------
+  void GeneratePrivateMembers(io::Printer* printer) const;
+  void GenerateAccessorDeclarations(io::Printer* printer) const;
+  void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
+  void GenerateClearingCode(io::Printer* printer) const;
+  void GenerateMergingCode(io::Printer* printer) const;
+  void GenerateSwappingCode(io::Printer* printer) const;
+  void GenerateConstructorCode(io::Printer* printer) const;
+  void GenerateMergeFromCodedStream(io::Printer* printer) const;
+  void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
+  void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
+  void GenerateByteSize(io::Printer* printer) const;
+
+ private:
+  const FieldDescriptor* descriptor_;
+  map<string, string> variables_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapFieldGenerator);
+};
+
+}  // namespace cpp
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_CPP_MAP_FIELD_H__

+ 120 - 28
src/google/protobuf/compiler/cpp/cpp_message.cc

@@ -334,6 +334,31 @@ bool HasHasMethod(const FieldDescriptor* field) {
   return field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE;
   return field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE;
 }
 }
 
 
+// Collects map entry message type information.
+void CollectMapInfo(const Descriptor* descriptor,
+                    map<string, string>* variables) {
+  GOOGLE_CHECK(IsMapEntryMessage(descriptor));
+  const FieldDescriptor* key = descriptor->FindFieldByName("key");
+  const FieldDescriptor* val = descriptor->FindFieldByName("value");
+  (*variables)["key"] = PrimitiveTypeName(key->cpp_type());
+  switch (val->cpp_type()) {
+    case FieldDescriptor::CPPTYPE_MESSAGE:
+      (*variables)["val"] = FieldMessageTypeName(val);
+      break;
+    case FieldDescriptor::CPPTYPE_ENUM:
+      (*variables)["val"] = ClassName(val->enum_type(), false);
+      break;
+    default:
+      (*variables)["val"] = PrimitiveTypeName(val->cpp_type());
+  }
+  (*variables)["key_type"] =
+      "::google::protobuf::FieldDescriptor::TYPE_" +
+      ToUpper(DeclaredTypeMethodName(key->type()));
+  (*variables)["val_type"] =
+      "::google::protobuf::FieldDescriptor::TYPE_" +
+      ToUpper(DeclaredTypeMethodName(val->type()));
+}
+
 // Does the given field have a private (internal helper only) has_$name$()
 // Does the given field have a private (internal helper only) has_$name$()
 // method?
 // method?
 bool HasPrivateHasMethod(const FieldDescriptor* field) {
 bool HasPrivateHasMethod(const FieldDescriptor* field) {
@@ -353,11 +378,11 @@ MessageGenerator::MessageGenerator(const Descriptor* descriptor,
       classname_(ClassName(descriptor, false)),
       classname_(ClassName(descriptor, false)),
       options_(options),
       options_(options),
       field_generators_(descriptor, options),
       field_generators_(descriptor, options),
-      nested_generators_(new scoped_ptr<
+      nested_generators_(new google::protobuf::scoped_ptr<
           MessageGenerator>[descriptor->nested_type_count()]),
           MessageGenerator>[descriptor->nested_type_count()]),
       enum_generators_(
       enum_generators_(
-          new scoped_ptr<EnumGenerator>[descriptor->enum_type_count()]),
-      extension_generators_(new scoped_ptr<
+          new google::protobuf::scoped_ptr<EnumGenerator>[descriptor->enum_type_count()]),
+      extension_generators_(new google::protobuf::scoped_ptr<
           ExtensionGenerator>[descriptor->extension_count()]) {
           ExtensionGenerator>[descriptor->extension_count()]) {
 
 
   for (int i = 0; i < descriptor->nested_type_count(); i++) {
   for (int i = 0; i < descriptor->nested_type_count(); i++) {
@@ -391,6 +416,10 @@ GenerateForwardDeclaration(io::Printer* printer) {
                  "classname", classname_);
                  "classname", classname_);
 
 
   for (int i = 0; i < descriptor_->nested_type_count(); i++) {
   for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+    // map entry message doesn't need forward declaration. Since map entry
+    // message cannot be a top level class, we just need to avoid calling
+    // GenerateForwardDeclaration here.
+    if (IsMapEntryMessage(descriptor_->nested_type(i))) continue;
     nested_generators_[i]->GenerateForwardDeclaration(printer);
     nested_generators_[i]->GenerateForwardDeclaration(printer);
   }
   }
 }
 }
@@ -622,6 +651,10 @@ static bool CanClearByZeroing(const FieldDescriptor* field) {
 void MessageGenerator::
 void MessageGenerator::
 GenerateClassDefinition(io::Printer* printer) {
 GenerateClassDefinition(io::Printer* printer) {
   for (int i = 0; i < descriptor_->nested_type_count(); i++) {
   for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+    // map entry message doesn't need class definition. Since map entry message
+    // cannot be a top level class, we just need to avoid calling
+    // GenerateClassDefinition here.
+    if (IsMapEntryMessage(descriptor_->nested_type(i))) continue;
     nested_generators_[i]->GenerateClassDefinition(printer);
     nested_generators_[i]->GenerateClassDefinition(printer);
     printer->Print("\n");
     printer->Print("\n");
     printer->Print(kThinSeparator);
     printer->Print(kThinSeparator);
@@ -876,9 +909,11 @@ GenerateClassDefinition(io::Printer* printer) {
   // Import all nested message classes into this class's scope with typedefs.
   // Import all nested message classes into this class's scope with typedefs.
   for (int i = 0; i < descriptor_->nested_type_count(); i++) {
   for (int i = 0; i < descriptor_->nested_type_count(); i++) {
     const Descriptor* nested_type = descriptor_->nested_type(i);
     const Descriptor* nested_type = descriptor_->nested_type(i);
-    printer->Print("typedef $nested_full_name$ $nested_name$;\n",
-                   "nested_name", nested_type->name(),
-                   "nested_full_name", ClassName(nested_type, false));
+    if (!IsMapEntryMessage(nested_type)) {
+      printer->Print("typedef $nested_full_name$ $nested_name$;\n",
+                     "nested_name", nested_type->name(),
+                     "nested_full_name", ClassName(nested_type, false));
+    }
   }
   }
 
 
   if (descriptor_->nested_type_count() > 0) {
   if (descriptor_->nested_type_count() > 0) {
@@ -1124,6 +1159,10 @@ GenerateClassDefinition(io::Printer* printer) {
 void MessageGenerator::
 void MessageGenerator::
 GenerateInlineMethods(io::Printer* printer) {
 GenerateInlineMethods(io::Printer* printer) {
   for (int i = 0; i < descriptor_->nested_type_count(); i++) {
   for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+    // map entry message doesn't need inline methods. Since map entry message
+    // cannot be a top level class, we just need to avoid calling
+    // GenerateInlineMethods here.
+    if (IsMapEntryMessage(descriptor_->nested_type(i))) continue;
     nested_generators_[i]->GenerateInlineMethods(printer);
     nested_generators_[i]->GenerateInlineMethods(printer);
     printer->Print(kThinSeparator);
     printer->Print(kThinSeparator);
     printer->Print("\n");
     printer->Print("\n");
@@ -1151,11 +1190,17 @@ GenerateInlineMethods(io::Printer* printer) {
 
 
 void MessageGenerator::
 void MessageGenerator::
 GenerateDescriptorDeclarations(io::Printer* printer) {
 GenerateDescriptorDeclarations(io::Printer* printer) {
-  printer->Print(
-    "const ::google::protobuf::Descriptor* $name$_descriptor_ = NULL;\n"
-    "const ::google::protobuf::internal::GeneratedMessageReflection*\n"
-    "  $name$_reflection_ = NULL;\n",
-    "name", classname_);
+  if (!IsMapEntryMessage(descriptor_)) {
+    printer->Print(
+      "const ::google::protobuf::Descriptor* $name$_descriptor_ = NULL;\n"
+      "const ::google::protobuf::internal::GeneratedMessageReflection*\n"
+      "  $name$_reflection_ = NULL;\n",
+      "name", classname_);
+  } else {
+    printer->Print(
+      "const ::google::protobuf::Descriptor* $name$_descriptor_ = NULL;\n",
+      "name", classname_);
+  }
 
 
   // Generate oneof default instance for reflection usage.
   // Generate oneof default instance for reflection usage.
   if (descriptor_->oneof_decl_count() > 0) {
   if (descriptor_->oneof_decl_count() > 0) {
@@ -1206,13 +1251,20 @@ GenerateDescriptorInitializer(io::Printer* printer, int index) {
         "$parent$_descriptor_->nested_type($index$);\n");
         "$parent$_descriptor_->nested_type($index$);\n");
   }
   }
 
 
+  if (IsMapEntryMessage(descriptor_)) return;
+
   // Generate the offsets.
   // Generate the offsets.
   GenerateOffsets(printer);
   GenerateOffsets(printer);
 
 
+  const bool pass_pool_and_factory = false;
+  vars["fn"] = pass_pool_and_factory ?
+      "new ::google::protobuf::internal::GeneratedMessageReflection" :
+      "::google::protobuf::internal::GeneratedMessageReflection"
+      "::NewGeneratedMessageReflection";
   // Construct the reflection object.
   // Construct the reflection object.
   printer->Print(vars,
   printer->Print(vars,
     "$classname$_reflection_ =\n"
     "$classname$_reflection_ =\n"
-    "  new ::google::protobuf::internal::GeneratedMessageReflection(\n"
+    "  $fn$(\n"
     "    $classname$_descriptor_,\n"
     "    $classname$_descriptor_,\n"
     "    $classname$::default_instance_,\n"
     "    $classname$::default_instance_,\n"
     "    $classname$_offsets_,\n");
     "    $classname$_offsets_,\n");
@@ -1254,10 +1306,12 @@ GenerateDescriptorInitializer(io::Printer* printer, int index) {
       "$classname$, _oneof_case_[0]),\n");
       "$classname$, _oneof_case_[0]),\n");
   }
   }
 
 
-  printer->Print(
-    "    ::google::protobuf::DescriptorPool::generated_pool(),\n");
-  printer->Print(vars,
-    "    ::google::protobuf::MessageFactory::generated_factory(),\n");
+  if (pass_pool_and_factory) {
+    printer->Print(
+        "    ::google::protobuf::DescriptorPool::generated_pool(),\n");
+      printer->Print(vars,
+                     "    ::google::protobuf::MessageFactory::generated_factory(),\n");
+  }
 
 
   printer->Print(vars,
   printer->Print(vars,
     "    sizeof($classname$),\n");
     "    sizeof($classname$),\n");
@@ -1289,10 +1343,37 @@ GenerateDescriptorInitializer(io::Printer* printer, int index) {
 void MessageGenerator::
 void MessageGenerator::
 GenerateTypeRegistrations(io::Printer* printer) {
 GenerateTypeRegistrations(io::Printer* printer) {
   // Register this message type with the message factory.
   // Register this message type with the message factory.
-  printer->Print(
-    "::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(\n"
-    "  $classname$_descriptor_, &$classname$::default_instance());\n",
-    "classname", classname_);
+  if (!IsMapEntryMessage(descriptor_)) {
+    printer->Print(
+      "::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(\n"
+      "    $classname$_descriptor_, &$classname$::default_instance());\n",
+      "classname", classname_);
+  }
+  else {
+    map<string, string> vars;
+    CollectMapInfo(descriptor_, &vars);
+    vars["classname"] = classname_;
+
+    const FieldDescriptor* val = descriptor_->FindFieldByName("value");
+    if (descriptor_->file()->syntax() == FileDescriptor::SYNTAX_PROTO2 &&
+        val->type() == FieldDescriptor::TYPE_ENUM) {
+      const EnumValueDescriptor* default_value = val->default_value_enum();
+      vars["default_enum_value"] = Int32ToString(default_value->number());
+    } else {
+      vars["default_enum_value"] = "0";
+    }
+
+    printer->Print(vars,
+      "::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(\n"
+      "      $classname$_descriptor_,\n"
+      "      ::google::protobuf::internal::MapEntry<\n"
+      "          $key$,\n"
+      "          $val$,\n"
+      "          $key_type$,\n"
+      "          $val_type$,\n"
+      "          $default_enum_value$>::CreateDefaultInstance(\n"
+      "              $classname$_descriptor_));\n");
+  }
 
 
   // Handle nested types.
   // Handle nested types.
   for (int i = 0; i < descriptor_->nested_type_count(); i++) {
   for (int i = 0; i < descriptor_->nested_type_count(); i++) {
@@ -1309,6 +1390,8 @@ GenerateDefaultInstanceAllocator(io::Printer* printer) {
                      .GenerateDefaultInstanceAllocator(printer);
                      .GenerateDefaultInstanceAllocator(printer);
   }
   }
 
 
+  if (IsMapEntryMessage(descriptor_)) return;
+
   // Construct the default instance.  We can't call InitAsDefaultInstance() yet
   // Construct the default instance.  We can't call InitAsDefaultInstance() yet
   // because we need to make sure all default instances that this one might
   // because we need to make sure all default instances that this one might
   // depend on are constructed first.
   // depend on are constructed first.
@@ -1343,6 +1426,10 @@ GenerateDefaultInstanceInitializer(io::Printer* printer) {
 
 
   // Handle nested types.
   // Handle nested types.
   for (int i = 0; i < descriptor_->nested_type_count(); i++) {
   for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+    // map entry message doesn't need to initialize default instance manually.
+    // Since map entry message cannot be a top level class, we just need to
+    // avoid calling DefaultInstanceInitializer here.
+    if (IsMapEntryMessage(descriptor_->nested_type(i))) continue;
     nested_generators_[i]->GenerateDefaultInstanceInitializer(printer);
     nested_generators_[i]->GenerateDefaultInstanceInitializer(printer);
   }
   }
 }
 }
@@ -1372,6 +1459,7 @@ GenerateShutdownCode(io::Printer* printer) {
 
 
   // Handle nested types.
   // Handle nested types.
   for (int i = 0; i < descriptor_->nested_type_count(); i++) {
   for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+    if (IsMapEntryMessage(descriptor_->nested_type(i))) continue;
     nested_generators_[i]->GenerateShutdownCode(printer);
     nested_generators_[i]->GenerateShutdownCode(printer);
   }
   }
 }
 }
@@ -1383,6 +1471,10 @@ GenerateClassMethods(io::Printer* printer) {
   }
   }
 
 
   for (int i = 0; i < descriptor_->nested_type_count(); i++) {
   for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+    // map entry message doesn't need class methods. Since map entry message
+    // cannot be a top level class, we just need to avoid calling
+    // GenerateClassMethods here.
+    if (IsMapEntryMessage(descriptor_->nested_type(i))) continue;
     nested_generators_[i]->GenerateClassMethods(printer);
     nested_generators_[i]->GenerateClassMethods(printer);
     printer->Print("\n");
     printer->Print("\n");
     printer->Print(kThinSeparator);
     printer->Print(kThinSeparator);
@@ -2195,7 +2287,7 @@ GenerateMergeFrom(io::Printer* printer) {
     // base class as a parameter).
     // base class as a parameter).
     printer->Print(
     printer->Print(
       "void $classname$::MergeFrom(const ::google::protobuf::Message& from) {\n"
       "void $classname$::MergeFrom(const ::google::protobuf::Message& from) {\n"
-      "  GOOGLE_CHECK_NE(&from, this);\n",
+      "  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);\n",
       "classname", classname_);
       "classname", classname_);
     printer->Indent();
     printer->Indent();
 
 
@@ -2230,7 +2322,7 @@ GenerateMergeFrom(io::Printer* printer) {
   // Generate the class-specific MergeFrom, which avoids the GOOGLE_CHECK and cast.
   // Generate the class-specific MergeFrom, which avoids the GOOGLE_CHECK and cast.
   printer->Print(
   printer->Print(
     "void $classname$::MergeFrom(const $classname$& from) {\n"
     "void $classname$::MergeFrom(const $classname$& from) {\n"
-    "  GOOGLE_CHECK_NE(&from, this);\n",
+    "  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);\n",
     "classname", classname_);
     "classname", classname_);
   printer->Indent();
   printer->Indent();
 
 
@@ -2429,7 +2521,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) {
   printer->Print("for (;;) {\n");
   printer->Print("for (;;) {\n");
   printer->Indent();
   printer->Indent();
 
 
-  scoped_array<const FieldDescriptor*> ordered_fields(
+  google::protobuf::scoped_array<const FieldDescriptor * > ordered_fields(
       SortFieldsByNumber(descriptor_));
       SortFieldsByNumber(descriptor_));
   uint32 maxtag = descriptor_->field_count() == 0 ? 0 :
   uint32 maxtag = descriptor_->field_count() == 0 ? 0 :
       WireFormat::MakeTag(ordered_fields[descriptor_->field_count() - 1]);
       WireFormat::MakeTag(ordered_fields[descriptor_->field_count() - 1]);
@@ -2788,7 +2880,7 @@ GenerateSerializeWithCachedSizesToArray(io::Printer* printer) {
 
 
 void MessageGenerator::
 void MessageGenerator::
 GenerateSerializeWithCachedSizesBody(io::Printer* printer, bool to_array) {
 GenerateSerializeWithCachedSizesBody(io::Printer* printer, bool to_array) {
-  scoped_array<const FieldDescriptor*> ordered_fields(
+  google::protobuf::scoped_array<const FieldDescriptor * > ordered_fields(
       SortFieldsByNumber(descriptor_));
       SortFieldsByNumber(descriptor_));
 
 
   vector<const Descriptor::ExtensionRange*> sorted_extensions;
   vector<const Descriptor::ExtensionRange*> sorted_extensions;
@@ -3186,14 +3278,14 @@ GenerateIsInitialized(io::Printer* printer) {
           " return false;\n",
           " return false;\n",
           "name", FieldName(field));
           "name", FieldName(field));
       } else {
       } else {
-        if (field->options().weak()) {
+        if (field->options().weak() || !field->containing_oneof()) {
           // For weak fields, use the data member (::google::protobuf::Message*) instead
           // For weak fields, use the data member (::google::protobuf::Message*) instead
           // of the getter to avoid a link dependency on the weak message type
           // of the getter to avoid a link dependency on the weak message type
           // which is only forward declared.
           // which is only forward declared.
           printer->Print(
           printer->Print(
-            "if (has_$name$()) {\n"
-            "  if (!this->$name$_->IsInitialized()) return false;\n"
-            "}\n",
+              "if (has_$name$()) {\n"
+              "  if (!this->$name$_->IsInitialized()) return false;\n"
+              "}\n",
             "name", FieldName(field));
             "name", FieldName(field));
         } else {
         } else {
           printer->Print(
           printer->Print(

+ 3 - 3
src/google/protobuf/compiler/cpp/cpp_message.h

@@ -163,9 +163,9 @@ class MessageGenerator {
   Options options_;
   Options options_;
   FieldGeneratorMap field_generators_;
   FieldGeneratorMap field_generators_;
   vector< vector<string> > runs_of_fields_;  // that might be trivially cleared
   vector< vector<string> > runs_of_fields_;  // that might be trivially cleared
-  scoped_array<scoped_ptr<MessageGenerator> > nested_generators_;
-  scoped_array<scoped_ptr<EnumGenerator> > enum_generators_;
-  scoped_array<scoped_ptr<ExtensionGenerator> > extension_generators_;
+  google::protobuf::scoped_array<google::protobuf::scoped_ptr<MessageGenerator> > nested_generators_;
+  google::protobuf::scoped_array<google::protobuf::scoped_ptr<EnumGenerator> > enum_generators_;
+  google::protobuf::scoped_array<google::protobuf::scoped_ptr<ExtensionGenerator> > extension_generators_;
   int num_required_fields_;
   int num_required_fields_;
   bool uses_string_;
   bool uses_string_;
 
 

+ 9 - 5
src/google/protobuf/compiler/cpp/cpp_message_field.cc

@@ -49,6 +49,10 @@ void SetMessageVariables(const FieldDescriptor* descriptor,
                          const Options& options) {
                          const Options& options) {
   SetCommonFieldVariables(descriptor, variables, options);
   SetCommonFieldVariables(descriptor, variables, options);
   (*variables)["type"] = FieldMessageTypeName(descriptor);
   (*variables)["type"] = FieldMessageTypeName(descriptor);
+  if (descriptor->options().weak() || !descriptor->containing_oneof()) {
+    (*variables)["non_null_ptr_to_name"] =
+        StrCat("this->", (*variables)["name"], "_");
+  }
   (*variables)["stream_writer"] = (*variables)["declared_type"] +
   (*variables)["stream_writer"] = (*variables)["declared_type"] +
       (HasFastArraySerialization(descriptor->message_type()->file()) ?
       (HasFastArraySerialization(descriptor->message_type()->file()) ?
        "MaybeToArray" :
        "MaybeToArray" :
@@ -293,7 +297,7 @@ void MessageFieldGenerator::
 GenerateSerializeWithCachedSizes(io::Printer* printer) const {
 GenerateSerializeWithCachedSizes(io::Printer* printer) const {
   printer->Print(variables_,
   printer->Print(variables_,
     "::google::protobuf::internal::WireFormatLite::Write$stream_writer$(\n"
     "::google::protobuf::internal::WireFormatLite::Write$stream_writer$(\n"
-    "  $number$, this->$name$(), output);\n");
+    "  $number$, *$non_null_ptr_to_name$, output);\n");
 }
 }
 
 
 void MessageFieldGenerator::
 void MessageFieldGenerator::
@@ -301,7 +305,7 @@ GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
   printer->Print(variables_,
   printer->Print(variables_,
     "target = ::google::protobuf::internal::WireFormatLite::\n"
     "target = ::google::protobuf::internal::WireFormatLite::\n"
     "  Write$declared_type$NoVirtualToArray(\n"
     "  Write$declared_type$NoVirtualToArray(\n"
-    "    $number$, this->$name$(), target);\n");
+    "    $number$, *$non_null_ptr_to_name$, target);\n");
 }
 }
 
 
 void MessageFieldGenerator::
 void MessageFieldGenerator::
@@ -309,7 +313,7 @@ GenerateByteSize(io::Printer* printer) const {
   printer->Print(variables_,
   printer->Print(variables_,
     "total_size += $tag_size$ +\n"
     "total_size += $tag_size$ +\n"
     "  ::google::protobuf::internal::WireFormatLite::$declared_type$SizeNoVirtual(\n"
     "  ::google::protobuf::internal::WireFormatLite::$declared_type$SizeNoVirtual(\n"
-    "    this->$name$());\n");
+    "    *$non_null_ptr_to_name$);\n");
 }
 }
 
 
 // ===================================================================
 // ===================================================================
@@ -591,7 +595,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
 void RepeatedMessageFieldGenerator::
 void RepeatedMessageFieldGenerator::
 GenerateSerializeWithCachedSizes(io::Printer* printer) const {
 GenerateSerializeWithCachedSizes(io::Printer* printer) const {
   printer->Print(variables_,
   printer->Print(variables_,
-    "for (int i = 0; i < this->$name$_size(); i++) {\n"
+    "for (unsigned int i = 0, n = this->$name$_size(); i < n; i++) {\n"
     "  ::google::protobuf::internal::WireFormatLite::Write$stream_writer$(\n"
     "  ::google::protobuf::internal::WireFormatLite::Write$stream_writer$(\n"
     "    $number$, this->$name$(i), output);\n"
     "    $number$, this->$name$(i), output);\n"
     "}\n");
     "}\n");
@@ -600,7 +604,7 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) const {
 void RepeatedMessageFieldGenerator::
 void RepeatedMessageFieldGenerator::
 GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
 GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
   printer->Print(variables_,
   printer->Print(variables_,
-    "for (int i = 0; i < this->$name$_size(); i++) {\n"
+    "for (unsigned int i = 0, n = this->$name$_size(); i < n; i++) {\n"
     "  target = ::google::protobuf::internal::WireFormatLite::\n"
     "  target = ::google::protobuf::internal::WireFormatLite::\n"
     "    Write$declared_type$NoVirtualToArray(\n"
     "    Write$declared_type$NoVirtualToArray(\n"
     "      $number$, this->$name$(i), target);\n"
     "      $number$, this->$name$(i), target);\n"

+ 1 - 1
src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc

@@ -171,7 +171,7 @@ class TestGenerator : public CodeGenerator {
 
 
   void TryInsert(const string& filename, const string& insertion_point,
   void TryInsert(const string& filename, const string& insertion_point,
                  GeneratorContext* context) const {
                  GeneratorContext* context) const {
-    scoped_ptr<io::ZeroCopyOutputStream> output(
+    google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
         context->OpenForInsert(filename, insertion_point));
         context->OpenForInsert(filename, insertion_point));
     io::Printer printer(output.get(), '$');
     io::Printer printer(output.get(), '$');
     printer.Print("// inserted $name$\n", "name", insertion_point);
     printer.Print("// inserted $name$\n", "name", insertion_point);

+ 8 - 1
src/google/protobuf/compiler/cpp/cpp_string_field.cc

@@ -306,7 +306,14 @@ GenerateClearingCode(io::Printer* printer) const {
 
 
 void StringFieldGenerator::
 void StringFieldGenerator::
 GenerateMergingCode(io::Printer* printer) const {
 GenerateMergingCode(io::Printer* printer) const {
-  printer->Print(variables_, "set_$name$(from.$name$());\n");
+  if (SupportsArenas(descriptor_) || descriptor_->containing_oneof() != NULL) {
+    // TODO(gpike): improve this
+    printer->Print(variables_, "set_$name$(from.$name$());\n");
+  } else {
+    printer->Print(variables_,
+      "$set_hasbit$\n"
+      "$name$_.AssignWithDefault($default_variable$, from.$name$_);\n");
+  }
 }
 }
 
 
 void StringFieldGenerator::
 void StringFieldGenerator::

+ 8 - 8
src/google/protobuf/compiler/cpp/cpp_unittest.cc

@@ -251,7 +251,7 @@ TEST(GeneratedMessageTest, ReleaseString) {
 
 
   message.set_default_string("blah");
   message.set_default_string("blah");
   EXPECT_TRUE(message.has_default_string());
   EXPECT_TRUE(message.has_default_string());
-  scoped_ptr<string> str(message.release_default_string());
+  google::protobuf::scoped_ptr<string> str(message.release_default_string());
   EXPECT_FALSE(message.has_default_string());
   EXPECT_FALSE(message.has_default_string());
   ASSERT_TRUE(str != NULL);
   ASSERT_TRUE(str != NULL);
   EXPECT_EQ("blah", *str);
   EXPECT_EQ("blah", *str);
@@ -270,7 +270,7 @@ TEST(GeneratedMessageTest, ReleaseMessage) {
   EXPECT_FALSE(message.has_optional_nested_message());
   EXPECT_FALSE(message.has_optional_nested_message());
 
 
   message.mutable_optional_nested_message()->set_bb(1);
   message.mutable_optional_nested_message()->set_bb(1);
-  scoped_ptr<unittest::TestAllTypes::NestedMessage> nest(
+  google::protobuf::scoped_ptr<unittest::TestAllTypes::NestedMessage> nest(
       message.release_optional_nested_message());
       message.release_optional_nested_message());
   EXPECT_FALSE(message.has_optional_nested_message());
   EXPECT_FALSE(message.has_optional_nested_message());
   ASSERT_TRUE(nest != NULL);
   ASSERT_TRUE(nest != NULL);
@@ -534,7 +534,7 @@ TEST(GeneratedMessageTest, DynamicMessageCopyFrom) {
 
 
   // Construct a new version of the dynamic message via the factory.
   // Construct a new version of the dynamic message via the factory.
   DynamicMessageFactory factory;
   DynamicMessageFactory factory;
-  scoped_ptr<Message> message1;
+  google::protobuf::scoped_ptr<Message> message1;
   message1.reset(factory.GetPrototype(
   message1.reset(factory.GetPrototype(
                      unittest::TestAllTypes::descriptor())->New());
                      unittest::TestAllTypes::descriptor())->New());
 
 
@@ -581,9 +581,9 @@ TEST(GeneratedMessageTest, NonEmptyMergeFrom) {
 
 
 TEST(GeneratedMessageTest, MergeFromSelf) {
 TEST(GeneratedMessageTest, MergeFromSelf) {
   unittest::TestAllTypes message;
   unittest::TestAllTypes message;
-  EXPECT_DEATH(message.MergeFrom(message), "&from");
+  EXPECT_DEATH(message.MergeFrom(message), "Check failed:.*pb[.]cc");
   EXPECT_DEATH(message.MergeFrom(implicit_cast<const Message&>(message)),
   EXPECT_DEATH(message.MergeFrom(implicit_cast<const Message&>(message)),
-               "&from");
+               "Check failed:.*pb[.]cc");
 }
 }
 
 
 #endif  // PROTOBUF_HAS_DEATH_TEST
 #endif  // PROTOBUF_HAS_DEATH_TEST
@@ -1221,7 +1221,7 @@ class GeneratedServiceTest : public testing::Test {
   unittest::FooResponse foo_response_;
   unittest::FooResponse foo_response_;
   unittest::BarRequest bar_request_;
   unittest::BarRequest bar_request_;
   unittest::BarResponse bar_response_;
   unittest::BarResponse bar_response_;
-  scoped_ptr<Closure> done_;
+  google::protobuf::scoped_ptr<Closure> done_;
 };
 };
 
 
 TEST_F(GeneratedServiceTest, GetDescriptor) {
 TEST_F(GeneratedServiceTest, GetDescriptor) {
@@ -1519,7 +1519,7 @@ TEST_F(OneofTest, ReleaseString) {
 
 
   message.set_foo_string("blah");
   message.set_foo_string("blah");
   EXPECT_TRUE(message.has_foo_string());
   EXPECT_TRUE(message.has_foo_string());
-  scoped_ptr<string> str(message.release_foo_string());
+  google::protobuf::scoped_ptr<string> str(message.release_foo_string());
   EXPECT_FALSE(message.has_foo_string());
   EXPECT_FALSE(message.has_foo_string());
   ASSERT_TRUE(str != NULL);
   ASSERT_TRUE(str != NULL);
   EXPECT_EQ("blah", *str);
   EXPECT_EQ("blah", *str);
@@ -1573,7 +1573,7 @@ TEST_F(OneofTest, ReleaseMessage) {
 
 
   message.mutable_foo_message()->set_qux_int(1);
   message.mutable_foo_message()->set_qux_int(1);
   EXPECT_TRUE(message.has_foo_message());
   EXPECT_TRUE(message.has_foo_message());
-  scoped_ptr<unittest::TestOneof2_NestedMessage> mes(
+  google::protobuf::scoped_ptr<unittest::TestOneof2_NestedMessage> mes(
       message.release_foo_message());
       message.release_foo_message());
   EXPECT_FALSE(message.has_foo_message());
   EXPECT_FALSE(message.has_foo_message());
   ASSERT_TRUE(mes != NULL);
   ASSERT_TRUE(mes != NULL);

+ 3 - 3
src/google/protobuf/compiler/importer.cc

@@ -125,7 +125,7 @@ SourceTreeDescriptorDatabase::~SourceTreeDescriptorDatabase() {}
 
 
 bool SourceTreeDescriptorDatabase::FindFileByName(
 bool SourceTreeDescriptorDatabase::FindFileByName(
     const string& filename, FileDescriptorProto* output) {
     const string& filename, FileDescriptorProto* output) {
-  scoped_ptr<io::ZeroCopyInputStream> input(source_tree_->Open(filename));
+  google::protobuf::scoped_ptr<io::ZeroCopyInputStream> input(source_tree_->Open(filename));
   if (input == NULL) {
   if (input == NULL) {
     if (error_collector_ != NULL) {
     if (error_collector_ != NULL) {
       error_collector_->AddError(filename, -1, 0,
       error_collector_->AddError(filename, -1, 0,
@@ -403,7 +403,7 @@ DiskSourceTree::DiskFileToVirtualFile(
   // Verify that we can open the file.  Note that this also has the side-effect
   // Verify that we can open the file.  Note that this also has the side-effect
   // of verifying that we are not canonicalizing away any non-existent
   // of verifying that we are not canonicalizing away any non-existent
   // directories.
   // directories.
-  scoped_ptr<io::ZeroCopyInputStream> stream(OpenDiskFile(disk_file));
+  google::protobuf::scoped_ptr<io::ZeroCopyInputStream> stream(OpenDiskFile(disk_file));
   if (stream == NULL) {
   if (stream == NULL) {
     return CANNOT_OPEN;
     return CANNOT_OPEN;
   }
   }
@@ -413,7 +413,7 @@ DiskSourceTree::DiskFileToVirtualFile(
 
 
 bool DiskSourceTree::VirtualFileToDiskFile(const string& virtual_file,
 bool DiskSourceTree::VirtualFileToDiskFile(const string& virtual_file,
                                            string* disk_file) {
                                            string* disk_file) {
-  scoped_ptr<io::ZeroCopyInputStream> stream(
+  google::protobuf::scoped_ptr<io::ZeroCopyInputStream> stream(
       OpenVirtualFile(virtual_file, disk_file));
       OpenVirtualFile(virtual_file, disk_file));
   return stream != NULL;
   return stream != NULL;
 }
 }

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

@@ -242,7 +242,7 @@ class DiskSourceTreeTest : public testing::Test {
 
 
   virtual void TearDown() {
   virtual void TearDown() {
     for (int i = 0; i < dirnames_.size(); i++) {
     for (int i = 0; i < dirnames_.size(); i++) {
-      if (File::Exists(dirnames_[i])) {
+      if (FileExists(dirnames_[i])) {
         File::DeleteRecursively(dirnames_[i], NULL, NULL);
         File::DeleteRecursively(dirnames_[i], NULL, NULL);
       }
       }
     }
     }
@@ -258,7 +258,7 @@ class DiskSourceTreeTest : public testing::Test {
 
 
   void ExpectFileContents(const string& filename,
   void ExpectFileContents(const string& filename,
                           const char* expected_contents) {
                           const char* expected_contents) {
-    scoped_ptr<io::ZeroCopyInputStream> input(source_tree_.Open(filename));
+    google::protobuf::scoped_ptr<io::ZeroCopyInputStream> input(source_tree_.Open(filename));
 
 
     ASSERT_FALSE(input == NULL);
     ASSERT_FALSE(input == NULL);
 
 
@@ -275,7 +275,7 @@ class DiskSourceTreeTest : public testing::Test {
 
 
   void ExpectCannotOpenFile(const string& filename,
   void ExpectCannotOpenFile(const string& filename,
                             const string& error_message) {
                             const string& error_message) {
-    scoped_ptr<io::ZeroCopyInputStream> input(source_tree_.Open(filename));
+    google::protobuf::scoped_ptr<io::ZeroCopyInputStream> input(source_tree_.Open(filename));
     EXPECT_TRUE(input == NULL);
     EXPECT_TRUE(input == NULL);
     EXPECT_EQ(error_message, source_tree_.GetLastErrorMessage());
     EXPECT_EQ(error_message, source_tree_.GetLastErrorMessage());
   }
   }

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

@@ -84,7 +84,7 @@ class Context {
   void InitializeFieldGeneratorInfoForFields(
   void InitializeFieldGeneratorInfoForFields(
       const vector<const FieldDescriptor*>& fields);
       const vector<const FieldDescriptor*>& fields);
 
 
-  scoped_ptr<ClassNameResolver> name_resolver_;
+  google::protobuf::scoped_ptr<ClassNameResolver> name_resolver_;
   map<const FieldDescriptor*, FieldGeneratorInfo> field_generator_info_map_;
   map<const FieldDescriptor*, FieldGeneratorInfo> field_generator_info_map_;
   map<const OneofDescriptor*, OneofGeneratorInfo> oneof_generator_info_map_;
   map<const OneofDescriptor*, OneofGeneratorInfo> oneof_generator_info_map_;
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Context);
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Context);

+ 1 - 1
src/google/protobuf/compiler/java/java_field.cc

@@ -159,7 +159,7 @@ template <>
 FieldGeneratorMap<ImmutableFieldGenerator>::FieldGeneratorMap(
 FieldGeneratorMap<ImmutableFieldGenerator>::FieldGeneratorMap(
     const Descriptor* descriptor, Context* context)
     const Descriptor* descriptor, Context* context)
     : descriptor_(descriptor),
     : descriptor_(descriptor),
-      field_generators_(new scoped_ptr<
+      field_generators_(new google::protobuf::scoped_ptr<
           ImmutableFieldGenerator>[descriptor->field_count()]) {
           ImmutableFieldGenerator>[descriptor->field_count()]) {
 
 
   // Construct all the FieldGenerators and assign them bit indices for their
   // Construct all the FieldGenerators and assign them bit indices for their

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

@@ -108,7 +108,7 @@ class FieldGeneratorMap {
   const Descriptor* descriptor_;
   const Descriptor* descriptor_;
   Context* context_;
   Context* context_;
   ClassNameResolver* name_resolver_;
   ClassNameResolver* name_resolver_;
-  scoped_array<scoped_ptr<FieldGeneratorType> > field_generators_;
+  google::protobuf::scoped_array<google::protobuf::scoped_ptr<FieldGeneratorType> > field_generators_;
 
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorMap);
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorMap);
 };
 };

+ 7 - 7
src/google/protobuf/compiler/java/java_file.cc

@@ -121,7 +121,7 @@ void CollectExtensions(const FileDescriptorProto& file_proto,
            "descriptor.proto is not in the transitive dependencies. "
            "descriptor.proto is not in the transitive dependencies. "
            "This normally should not happen. Please report a bug.";
            "This normally should not happen. Please report a bug.";
     DynamicMessageFactory factory;
     DynamicMessageFactory factory;
-    scoped_ptr<Message> dynamic_file_proto(
+    google::protobuf::scoped_ptr<Message> dynamic_file_proto(
         factory.GetPrototype(file_proto_desc)->New());
         factory.GetPrototype(file_proto_desc)->New());
     GOOGLE_CHECK(dynamic_file_proto.get() != NULL);
     GOOGLE_CHECK(dynamic_file_proto.get() != NULL);
     GOOGLE_CHECK(dynamic_file_proto->ParseFromString(file_data));
     GOOGLE_CHECK(dynamic_file_proto->ParseFromString(file_data));
@@ -146,9 +146,9 @@ FileGenerator::FileGenerator(const FileDescriptor* file, bool immutable_api)
     : file_(file),
     : file_(file),
       java_package_(FileJavaPackage(file, immutable_api)),
       java_package_(FileJavaPackage(file, immutable_api)),
       message_generators_(
       message_generators_(
-          new scoped_ptr<MessageGenerator>[file->message_type_count()]),
+          new google::protobuf::scoped_ptr<MessageGenerator>[file->message_type_count()]),
       extension_generators_(
       extension_generators_(
-          new scoped_ptr<ExtensionGenerator>[file->extension_count()]),
+          new google::protobuf::scoped_ptr<ExtensionGenerator>[file->extension_count()]),
       context_(new Context(file)),
       context_(new Context(file)),
       name_resolver_(context_->GetNameResolver()),
       name_resolver_(context_->GetNameResolver()),
       immutable_api_(immutable_api) {
       immutable_api_(immutable_api) {
@@ -240,7 +240,7 @@ void FileGenerator::Generate(io::Printer* printer) {
     }
     }
     if (HasGenericServices(file_)) {
     if (HasGenericServices(file_)) {
       for (int i = 0; i < file_->service_count(); i++) {
       for (int i = 0; i < file_->service_count(); i++) {
-        scoped_ptr<ServiceGenerator> generator(
+        google::protobuf::scoped_ptr<ServiceGenerator> generator(
             generator_factory_->NewServiceGenerator(file_->service(i)));
             generator_factory_->NewServiceGenerator(file_->service(i)));
         generator->Generate(printer);
         generator->Generate(printer);
       }
       }
@@ -340,7 +340,7 @@ void FileGenerator::GenerateDescriptorInitializationCodeForImmutable(
       "com.google.protobuf.ExtensionRegistry registry =\n"
       "com.google.protobuf.ExtensionRegistry registry =\n"
       "    com.google.protobuf.ExtensionRegistry.newInstance();\n");
       "    com.google.protobuf.ExtensionRegistry.newInstance();\n");
     for (int i = 0; i < extensions.size(); i++) {
     for (int i = 0; i < extensions.size(); i++) {
-      scoped_ptr<ExtensionGenerator> generator(
+      google::protobuf::scoped_ptr<ExtensionGenerator> generator(
           generator_factory_->NewExtensionGenerator(extensions[i]));
           generator_factory_->NewExtensionGenerator(extensions[i]));
       generator->GenerateRegistrationCode(printer);
       generator->GenerateRegistrationCode(printer);
     }
     }
@@ -444,7 +444,7 @@ static void GenerateSibling(const string& package_dir,
   string filename = package_dir + descriptor->name() + name_suffix + ".java";
   string filename = package_dir + descriptor->name() + name_suffix + ".java";
   file_list->push_back(filename);
   file_list->push_back(filename);
 
 
-  scoped_ptr<io::ZeroCopyOutputStream> output(context->Open(filename));
+  google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(context->Open(filename));
   io::Printer printer(output.get(), '$');
   io::Printer printer(output.get(), '$');
 
 
   printer.Print(
   printer.Print(
@@ -492,7 +492,7 @@ void FileGenerator::GenerateSiblings(const string& package_dir,
     }
     }
     if (HasGenericServices(file_)) {
     if (HasGenericServices(file_)) {
       for (int i = 0; i < file_->service_count(); i++) {
       for (int i = 0; i < file_->service_count(); i++) {
-        scoped_ptr<ServiceGenerator> generator(
+        google::protobuf::scoped_ptr<ServiceGenerator> generator(
             generator_factory_->NewServiceGenerator(file_->service(i)));
             generator_factory_->NewServiceGenerator(file_->service(i)));
         GenerateSibling<ServiceGenerator>(package_dir, java_package_,
         GenerateSibling<ServiceGenerator>(package_dir, java_package_,
                                           file_->service(i),
                                           file_->service(i),

+ 4 - 4
src/google/protobuf/compiler/java/java_file.h

@@ -99,10 +99,10 @@ class FileGenerator {
   string java_package_;
   string java_package_;
   string classname_;
   string classname_;
 
 
-  scoped_array<scoped_ptr<MessageGenerator> > message_generators_;
-  scoped_array<scoped_ptr<ExtensionGenerator> > extension_generators_;
-  scoped_ptr<GeneratorFactory> generator_factory_;
-  scoped_ptr<Context> context_;
+  google::protobuf::scoped_array<google::protobuf::scoped_ptr<MessageGenerator> > message_generators_;
+  google::protobuf::scoped_array<google::protobuf::scoped_ptr<ExtensionGenerator> > extension_generators_;
+  google::protobuf::scoped_ptr<GeneratorFactory> generator_factory_;
+  google::protobuf::scoped_ptr<Context> context_;
   ClassNameResolver* name_resolver_;
   ClassNameResolver* name_resolver_;
   bool immutable_api_;
   bool immutable_api_;
 
 

+ 2 - 2
src/google/protobuf/compiler/java/java_generator.cc

@@ -130,7 +130,7 @@ bool JavaGenerator::Generate(const FileDescriptor* file,
     all_files.push_back(java_filename);
     all_files.push_back(java_filename);
 
 
     // Generate main java file.
     // Generate main java file.
-    scoped_ptr<io::ZeroCopyOutputStream> output(
+    google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
         context->Open(java_filename));
         context->Open(java_filename));
     io::Printer printer(output.get(), '$');
     io::Printer printer(output.get(), '$');
     file_generator->Generate(&printer);
     file_generator->Generate(&printer);
@@ -148,7 +148,7 @@ bool JavaGenerator::Generate(const FileDescriptor* file,
   if (!output_list_file.empty()) {
   if (!output_list_file.empty()) {
     // Generate output list.  This is just a simple text file placed in a
     // Generate output list.  This is just a simple text file placed in a
     // deterministic location which lists the .java files being generated.
     // deterministic location which lists the .java files being generated.
-    scoped_ptr<io::ZeroCopyOutputStream> srclist_raw_output(
+    google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> srclist_raw_output(
         context->Open(output_list_file));
         context->Open(output_list_file));
     io::Printer srclist_printer(srclist_raw_output.get(), '$');
     io::Printer srclist_printer(srclist_raw_output.get(), '$');
     for (int i = 0; i < all_files.size(); i++) {
     for (int i = 0; i < all_files.size(); i++) {

+ 102 - 57
src/google/protobuf/compiler/java/java_message.cc

@@ -70,6 +70,13 @@ bool GenerateHasBits(const Descriptor* descriptor) {
   return SupportFieldPresence(descriptor->file()) ||
   return SupportFieldPresence(descriptor->file()) ||
       HasRepeatedFields(descriptor);
       HasRepeatedFields(descriptor);
 }
 }
+
+string MapValueImmutableClassdName(const Descriptor* descriptor,
+                                   ClassNameResolver* name_resolver) {
+  const FieldDescriptor* value_field = descriptor->FindFieldByName("value");
+  GOOGLE_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, value_field->type());
+  return name_resolver->GetImmutableClassName(value_field->message_type());
+}
 }  // namespace
 }  // namespace
 
 
 // ===================================================================
 // ===================================================================
@@ -323,18 +330,7 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) {
   printer->Outdent();
   printer->Outdent();
   printer->Print(
   printer->Print(
     "}\n"
     "}\n"
-    "\n"
-    "private static final $classname$ defaultInstance;\n"
-    "public static $classname$ getDefaultInstance() {\n"
-    "  return defaultInstance;\n"
-    "}\n"
-    "\n"
-    "public $classname$ getDefaultInstanceForType() {\n"
-    "  return defaultInstance;\n"
-    "}\n"
-    "\n",
-    "classname", descriptor_->name(),
-    "lite", variables["lite"]);
+    "\n");
 
 
   if (HasDescriptorMethods(descriptor_)) {
   if (HasDescriptorMethods(descriptor_)) {
     printer->Print(
     printer->Print(
@@ -479,18 +475,25 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) {
   GenerateParseFromMethods(printer);
   GenerateParseFromMethods(printer);
   GenerateBuilder(printer);
   GenerateBuilder(printer);
 
 
-  // Carefully initialize the default instance in such a way that it doesn't
-  // conflict with other initialization.
   printer->Print(
   printer->Print(
-    "\n"
-    "static {\n"
-    "  defaultInstance = new $classname$();\n"
-    "}\n"
     "\n"
     "\n"
     "// @@protoc_insertion_point(class_scope:$full_name$)\n",
     "// @@protoc_insertion_point(class_scope:$full_name$)\n",
-    "classname", descriptor_->name(),
     "full_name", descriptor_->full_name());
     "full_name", descriptor_->full_name());
 
 
+  // Carefully initialize the default instance in such a way that it doesn't
+  // conflict with other initialization.
+  printer->Print("private static final $classname$ defaultInstance =\n"
+      "    new $classname$();\n"
+      "public static $classname$ getDefaultInstance() {\n"
+      "  return defaultInstance;\n"
+      "}\n"
+      "\n"
+      "public $classname$ getDefaultInstanceForType() {\n"
+      "  return defaultInstance;\n"
+      "}\n"
+      "\n",
+      "classname", descriptor_->name());
+
   // Extensions must be declared after the defaultInstance is initialized
   // Extensions must be declared after the defaultInstance is initialized
   // because the defaultInstance is used by the extension to lazily retrieve
   // because the defaultInstance is used by the extension to lazily retrieve
   // the outer class's FileDescriptor.
   // the outer class's FileDescriptor.
@@ -508,7 +511,7 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) {
 
 
 void ImmutableMessageGenerator::
 void ImmutableMessageGenerator::
 GenerateMessageSerializationMethods(io::Printer* printer) {
 GenerateMessageSerializationMethods(io::Printer* printer) {
-  scoped_array<const FieldDescriptor*> sorted_fields(
+  google::protobuf::scoped_array<const FieldDescriptor * > sorted_fields(
       SortFieldsByNumber(descriptor_));
       SortFieldsByNumber(descriptor_));
 
 
   vector<const Descriptor::ExtensionRange*> sorted_extensions;
   vector<const Descriptor::ExtensionRange*> sorted_extensions;
@@ -913,15 +916,15 @@ GenerateDescriptorMethods(io::Printer* printer) {
 
 
 void ImmutableMessageGenerator::
 void ImmutableMessageGenerator::
 GenerateCommonBuilderMethods(io::Printer* printer) {
 GenerateCommonBuilderMethods(io::Printer* printer) {
-  printer->Print(
-    "// Construct using $classname$.newBuilder()\n"
-    "private Builder() {\n"
-    "  maybeForceBuilderInitialization();\n"
-    "}\n"
-    "\n",
-    "classname", name_resolver_->GetImmutableClassName(descriptor_));
-
   if (HasDescriptorMethods(descriptor_)) {
   if (HasDescriptorMethods(descriptor_)) {
+    printer->Print(
+        "// Construct using $classname$.newBuilder()\n"
+        "private Builder() {\n"
+        "  maybeForceBuilderInitialization();\n"
+        "}\n"
+        "\n",
+        "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
     printer->Print(
     printer->Print(
       "private Builder(\n"
       "private Builder(\n"
       "    com.google.protobuf.GeneratedMessage.BuilderParent parent) {\n"
       "    com.google.protobuf.GeneratedMessage.BuilderParent parent) {\n"
@@ -929,6 +932,17 @@ GenerateCommonBuilderMethods(io::Printer* printer) {
       "  maybeForceBuilderInitialization();\n"
       "  maybeForceBuilderInitialization();\n"
       "}\n",
       "}\n",
       "classname", name_resolver_->GetImmutableClassName(descriptor_));
       "classname", name_resolver_->GetImmutableClassName(descriptor_));
+  } else {
+    // LITE runtime passes along the default instance to implement
+    // getDefaultInstanceForType() at the GneratedMessageLite level.
+    printer->Print(
+        "// Construct using $classname$.newBuilder()\n"
+        "private Builder() {\n"
+        "  super(defaultInstance);\n"
+        "  maybeForceBuilderInitialization();\n"
+        "}\n"
+        "\n",
+        "classname", name_resolver_->GetImmutableClassName(descriptor_));
   }
   }
 
 
 
 
@@ -994,25 +1008,33 @@ GenerateCommonBuilderMethods(io::Printer* printer) {
       "\n",
       "\n",
       "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()),
       "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()),
       "identifier", UniqueFileScopeIdentifier(descriptor_));
       "identifier", UniqueFileScopeIdentifier(descriptor_));
+
+    // LITE runtime implements this in GeneratedMessageLite.
+    printer->Print(
+      "public $classname$ getDefaultInstanceForType() {\n"
+      "  return $classname$.getDefaultInstance();\n"
+      "}\n"
+      "\n",
+      "classname", name_resolver_->GetImmutableClassName(descriptor_));
   }
   }
-  printer->Print(
-    "public $classname$ getDefaultInstanceForType() {\n"
-    "  return $classname$.getDefaultInstance();\n"
-    "}\n"
-    "\n",
-    "classname", name_resolver_->GetImmutableClassName(descriptor_));
 
 
   // -----------------------------------------------------------------
   // -----------------------------------------------------------------
 
 
+  if (HasDescriptorMethods(descriptor_)) {
+    // LITE implements build in GeneratedMessageLite to save methods.
+    printer->Print(
+      "public $classname$ build() {\n"
+      "  $classname$ result = buildPartial();\n"
+      "  if (!result.isInitialized()) {\n"
+      "    throw newUninitializedMessageException(result);\n"
+      "  }\n"
+      "  return result;\n"
+      "}\n"
+      "\n",
+      "classname", name_resolver_->GetImmutableClassName(descriptor_));
+  }
+
   printer->Print(
   printer->Print(
-    "public $classname$ build() {\n"
-    "  $classname$ result = buildPartial();\n"
-    "  if (!result.isInitialized()) {\n"
-    "    throw newUninitializedMessageException(result);\n"
-    "  }\n"
-    "  return result;\n"
-    "}\n"
-    "\n"
     "public $classname$ buildPartial() {\n"
     "public $classname$ buildPartial() {\n"
     "  $classname$ result = new $classname$(this);\n",
     "  $classname$ result = new $classname$(this);\n",
     "classname", name_resolver_->GetImmutableClassName(descriptor_));
     "classname", name_resolver_->GetImmutableClassName(descriptor_));
@@ -1255,17 +1277,31 @@ void ImmutableMessageGenerator::GenerateIsInitialized(
             "memoize", memoization ? "memoizedIsInitialized = 0;" : "");
             "memoize", memoization ? "memoizedIsInitialized = 0;" : "");
           break;
           break;
         case FieldDescriptor::LABEL_REPEATED:
         case FieldDescriptor::LABEL_REPEATED:
-          printer->Print(
-            "for (int i = 0; i < get$name$Count(); i++) {\n"
-            "  if (!get$name$(i).isInitialized()) {\n"
-            "    $memoize$\n"
-            "    return false;\n"
-            "  }\n"
-            "}\n",
-            "type", name_resolver_->GetImmutableClassName(
-                field->message_type()),
-            "name", info->capitalized_name,
-            "memoize", memoization ? "memoizedIsInitialized = 0;" : "");
+          if (IsMapEntry(field->message_type())) {
+            printer->Print(
+              "for ($type$ item : get$name$().values()) {\n"
+              "  if (!item.isInitialized()) {\n"
+              "    $memoize$\n"
+              "    return false;\n"
+              "  }\n"
+              "}\n",
+              "type", MapValueImmutableClassdName(field->message_type(),
+                                                  name_resolver_),
+              "name", info->capitalized_name,
+              "memoize", memoization ? "memoizedIsInitialized = 0;" : "");
+          } else {
+            printer->Print(
+              "for (int i = 0; i < get$name$Count(); i++) {\n"
+              "  if (!get$name$(i).isInitialized()) {\n"
+              "    $memoize$\n"
+              "    return false;\n"
+              "  }\n"
+              "}\n",
+              "type", name_resolver_->GetImmutableClassName(
+                  field->message_type()),
+              "name", info->capitalized_name,
+              "memoize", memoization ? "memoizedIsInitialized = 0;" : "");
+          }
           break;
           break;
       }
       }
     }
     }
@@ -1440,7 +1476,7 @@ GenerateExtensionRegistrationCode(io::Printer* printer) {
 // ===================================================================
 // ===================================================================
 void ImmutableMessageGenerator::
 void ImmutableMessageGenerator::
 GenerateParsingConstructor(io::Printer* printer) {
 GenerateParsingConstructor(io::Printer* printer) {
-  scoped_array<const FieldDescriptor*> sorted_fields(
+  google::protobuf::scoped_array<const FieldDescriptor * > sorted_fields(
       SortFieldsByNumber(descriptor_));
       SortFieldsByNumber(descriptor_));
 
 
   printer->Print(
   printer->Print(
@@ -1596,9 +1632,18 @@ GenerateParsingConstructor(io::Printer* printer) {
     printer->Print("this.unknownFields = unknownFields.build();\n");
     printer->Print("this.unknownFields = unknownFields.build();\n");
   }
   }
 
 
-  // Make extensions immutable.
-  printer->Print(
-      "makeExtensionsImmutable();\n");
+  if (!HasDescriptorMethods(descriptor_)) {
+    // LITE runtime uses a static method to reduce method count.
+    if (descriptor_->extension_range_count() > 0) {
+      // Make extensions immutable.
+      printer->Print(
+          "makeExtensionsImmutable(extensions);\n");
+    }
+  } else {
+    // Make extensions immutable.
+    printer->Print(
+        "makeExtensionsImmutable();\n");
+  }
 
 
   printer->Outdent();
   printer->Outdent();
   printer->Outdent();
   printer->Outdent();

+ 1 - 1
src/google/protobuf/compiler/java/java_plugin_unittest.cc

@@ -75,7 +75,7 @@ class TestGenerator : public CodeGenerator {
 
 
   void TryInsert(const string& filename, const string& insertion_point,
   void TryInsert(const string& filename, const string& insertion_point,
                  GeneratorContext* context) const {
                  GeneratorContext* context) const {
-    scoped_ptr<io::ZeroCopyOutputStream> output(
+    google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
         context->OpenForInsert(filename, insertion_point));
         context->OpenForInsert(filename, insertion_point));
     io::Printer printer(output.get(), '$');
     io::Printer printer(output.get(), '$');
     printer.Print("// inserted $name$\n", "name", insertion_point);
     printer.Print("// inserted $name$\n", "name", insertion_point);

+ 2 - 2
src/google/protobuf/compiler/java/java_shared_code_generator.cc

@@ -68,8 +68,8 @@ void SharedCodeGenerator::Generate(GeneratorContext* context,
     string classname = name_resolver_->GetDescriptorClassName(file_);
     string classname = name_resolver_->GetDescriptorClassName(file_);
     string filename = package_dir + classname + ".java";
     string filename = package_dir + classname + ".java";
     file_list->push_back(filename);
     file_list->push_back(filename);
-    scoped_ptr<io::ZeroCopyOutputStream> output(context->Open(filename));
-    scoped_ptr<io::Printer> printer(new io::Printer(output.get(), '$'));
+    google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(context->Open(filename));
+    google::protobuf::scoped_ptr<io::Printer> printer(new io::Printer(output.get(), '$'));
 
 
     printer->Print(
     printer->Print(
       "// Generated by the protocol buffer compiler.  DO NOT EDIT!\n"
       "// Generated by the protocol buffer compiler.  DO NOT EDIT!\n"

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

@@ -80,7 +80,7 @@ class SharedCodeGenerator {
   // improve compatibility with version 1 of protocol buffers.
   // improve compatibility with version 1 of protocol buffers.
   bool ShouldIncludeDependency(const FileDescriptor* descriptor);
   bool ShouldIncludeDependency(const FileDescriptor* descriptor);
 
 
-  scoped_ptr<ClassNameResolver> name_resolver_;
+  google::protobuf::scoped_ptr<ClassNameResolver> name_resolver_;
   const FileDescriptor* file_;
   const FileDescriptor* file_;
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SharedCodeGenerator);
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SharedCodeGenerator);
 };
 };

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

@@ -160,7 +160,7 @@ bool MockCodeGenerator::Generate(
 
 
     for (int i = 0; i < insert_into.size(); i++) {
     for (int i = 0; i < insert_into.size(); i++) {
       {
       {
-        scoped_ptr<io::ZeroCopyOutputStream> output(context->OpenForInsert(
+        google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(context->OpenForInsert(
             GetOutputFileName(insert_into[i], file), kFirstInsertionPointName));
             GetOutputFileName(insert_into[i], file), kFirstInsertionPointName));
         io::Printer printer(output.get(), '$');
         io::Printer printer(output.get(), '$');
         printer.PrintRaw(GetOutputFileContent(name_, "first_insert",
         printer.PrintRaw(GetOutputFileContent(name_, "first_insert",
@@ -172,7 +172,7 @@ bool MockCodeGenerator::Generate(
       }
       }
 
 
       {
       {
-        scoped_ptr<io::ZeroCopyOutputStream> output(
+        google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
             context->OpenForInsert(GetOutputFileName(insert_into[i], file),
             context->OpenForInsert(GetOutputFileName(insert_into[i], file),
                                    kSecondInsertionPointName));
                                    kSecondInsertionPointName));
         io::Printer printer(output.get(), '$');
         io::Printer printer(output.get(), '$');
@@ -185,7 +185,7 @@ bool MockCodeGenerator::Generate(
       }
       }
     }
     }
   } else {
   } else {
-    scoped_ptr<io::ZeroCopyOutputStream> output(
+    google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
         context->Open(GetOutputFileName(name_, file)));
         context->Open(GetOutputFileName(name_, file)));
 
 
     io::Printer printer(output.get(), '$');
     io::Printer printer(output.get(), '$');

+ 3 - 3
src/google/protobuf/compiler/parser_unittest.cc

@@ -178,9 +178,9 @@ class ParserTest : public testing::Test {
   MockErrorCollector error_collector_;
   MockErrorCollector error_collector_;
   DescriptorPool pool_;
   DescriptorPool pool_;
 
 
-  scoped_ptr<io::ZeroCopyInputStream> raw_input_;
-  scoped_ptr<io::Tokenizer> input_;
-  scoped_ptr<Parser> parser_;
+  google::protobuf::scoped_ptr<io::ZeroCopyInputStream> raw_input_;
+  google::protobuf::scoped_ptr<io::Tokenizer> input_;
+  google::protobuf::scoped_ptr<Parser> parser_;
   bool require_syntax_identifier_;
   bool require_syntax_identifier_;
 };
 };
 
 

+ 61 - 133
src/google/protobuf/compiler/plugin.pb.cc

@@ -48,15 +48,13 @@ void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto() {
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorRequest, proto_file_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorRequest, proto_file_),
   };
   };
   CodeGeneratorRequest_reflection_ =
   CodeGeneratorRequest_reflection_ =
-    new ::google::protobuf::internal::GeneratedMessageReflection(
+    ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
       CodeGeneratorRequest_descriptor_,
       CodeGeneratorRequest_descriptor_,
       CodeGeneratorRequest::default_instance_,
       CodeGeneratorRequest::default_instance_,
       CodeGeneratorRequest_offsets_,
       CodeGeneratorRequest_offsets_,
       GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorRequest, _has_bits_[0]),
       GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorRequest, _has_bits_[0]),
       -1,
       -1,
       -1,
       -1,
-      ::google::protobuf::DescriptorPool::generated_pool(),
-      ::google::protobuf::MessageFactory::generated_factory(),
       sizeof(CodeGeneratorRequest),
       sizeof(CodeGeneratorRequest),
       GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorRequest, _internal_metadata_));
       GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorRequest, _internal_metadata_));
   CodeGeneratorResponse_descriptor_ = file->message_type(1);
   CodeGeneratorResponse_descriptor_ = file->message_type(1);
@@ -65,15 +63,13 @@ void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto() {
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse, file_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse, file_),
   };
   };
   CodeGeneratorResponse_reflection_ =
   CodeGeneratorResponse_reflection_ =
-    new ::google::protobuf::internal::GeneratedMessageReflection(
+    ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
       CodeGeneratorResponse_descriptor_,
       CodeGeneratorResponse_descriptor_,
       CodeGeneratorResponse::default_instance_,
       CodeGeneratorResponse::default_instance_,
       CodeGeneratorResponse_offsets_,
       CodeGeneratorResponse_offsets_,
       GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse, _has_bits_[0]),
       GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse, _has_bits_[0]),
       -1,
       -1,
       -1,
       -1,
-      ::google::protobuf::DescriptorPool::generated_pool(),
-      ::google::protobuf::MessageFactory::generated_factory(),
       sizeof(CodeGeneratorResponse),
       sizeof(CodeGeneratorResponse),
       GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse, _internal_metadata_));
       GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse, _internal_metadata_));
   CodeGeneratorResponse_File_descriptor_ = CodeGeneratorResponse_descriptor_->nested_type(0);
   CodeGeneratorResponse_File_descriptor_ = CodeGeneratorResponse_descriptor_->nested_type(0);
@@ -83,15 +79,13 @@ void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto() {
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse_File, content_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse_File, content_),
   };
   };
   CodeGeneratorResponse_File_reflection_ =
   CodeGeneratorResponse_File_reflection_ =
-    new ::google::protobuf::internal::GeneratedMessageReflection(
+    ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
       CodeGeneratorResponse_File_descriptor_,
       CodeGeneratorResponse_File_descriptor_,
       CodeGeneratorResponse_File::default_instance_,
       CodeGeneratorResponse_File::default_instance_,
       CodeGeneratorResponse_File_offsets_,
       CodeGeneratorResponse_File_offsets_,
       GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse_File, _has_bits_[0]),
       GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse_File, _has_bits_[0]),
       -1,
       -1,
       -1,
       -1,
-      ::google::protobuf::DescriptorPool::generated_pool(),
-      ::google::protobuf::MessageFactory::generated_factory(),
       sizeof(CodeGeneratorResponse_File),
       sizeof(CodeGeneratorResponse_File),
       GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse_File, _internal_metadata_));
       GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse_File, _internal_metadata_));
 }
 }
@@ -107,11 +101,11 @@ inline void protobuf_AssignDescriptorsOnce() {
 void protobuf_RegisterTypes(const ::std::string&) {
 void protobuf_RegisterTypes(const ::std::string&) {
   protobuf_AssignDescriptorsOnce();
   protobuf_AssignDescriptorsOnce();
   ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
   ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
-    CodeGeneratorRequest_descriptor_, &CodeGeneratorRequest::default_instance());
+      CodeGeneratorRequest_descriptor_, &CodeGeneratorRequest::default_instance());
   ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
   ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
-    CodeGeneratorResponse_descriptor_, &CodeGeneratorResponse::default_instance());
+      CodeGeneratorResponse_descriptor_, &CodeGeneratorResponse::default_instance());
   ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
   ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
-    CodeGeneratorResponse_File_descriptor_, &CodeGeneratorResponse_File::default_instance());
+      CodeGeneratorResponse_File_descriptor_, &CodeGeneratorResponse_File::default_instance());
 }
 }
 
 
 }  // namespace
 }  // namespace
@@ -163,6 +157,16 @@ struct StaticDescriptorInitializer_google_2fprotobuf_2fcompiler_2fplugin_2eproto
   }
   }
 } static_descriptor_initializer_google_2fprotobuf_2fcompiler_2fplugin_2eproto_;
 } static_descriptor_initializer_google_2fprotobuf_2fcompiler_2fplugin_2eproto_;
 
 
+namespace {
+
+static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD;
+static void MergeFromFail(int line) {
+  GOOGLE_CHECK(false) << __FILE__ << ":" << line;
+}
+
+}  // namespace
+
+
 // ===================================================================
 // ===================================================================
 
 
 #ifndef _MSC_VER
 #ifndef _MSC_VER
@@ -177,16 +181,6 @@ CodeGeneratorRequest::CodeGeneratorRequest()
   // @@protoc_insertion_point(constructor:google.protobuf.compiler.CodeGeneratorRequest)
   // @@protoc_insertion_point(constructor:google.protobuf.compiler.CodeGeneratorRequest)
 }
 }
 
 
-CodeGeneratorRequest::CodeGeneratorRequest(::google::protobuf::Arena* arena)
-  : ::google::protobuf::Message(),
-  _internal_metadata_(arena),
-  file_to_generate_(arena),
-  proto_file_(arena) {
-  SharedCtor();
-  RegisterArenaDtor(arena);
-  // @@protoc_insertion_point(arena_constructor:google.protobuf.compiler.CodeGeneratorRequest)
-}
-
 void CodeGeneratorRequest::InitAsDefaultInstance() {
 void CodeGeneratorRequest::InitAsDefaultInstance() {
 }
 }
 
 
@@ -211,21 +205,11 @@ CodeGeneratorRequest::~CodeGeneratorRequest() {
 }
 }
 
 
 void CodeGeneratorRequest::SharedDtor() {
 void CodeGeneratorRequest::SharedDtor() {
-  if (GetArenaNoVirtual() != NULL) {
-    return;
-  }
-
-  parameter_.Destroy(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+  parameter_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
   if (this != default_instance_) {
   if (this != default_instance_) {
   }
   }
 }
 }
 
 
-void CodeGeneratorRequest::ArenaDtor(void* object) {
-  CodeGeneratorRequest* _this = reinterpret_cast< CodeGeneratorRequest* >(object);
-  (void)_this;
-}
-void CodeGeneratorRequest::RegisterArenaDtor(::google::protobuf::Arena* arena) {
-}
 void CodeGeneratorRequest::SetCachedSize(int size) const {
 void CodeGeneratorRequest::SetCachedSize(int size) const {
   GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
   GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
   _cached_size_ = size;
   _cached_size_ = size;
@@ -244,12 +228,16 @@ const CodeGeneratorRequest& CodeGeneratorRequest::default_instance() {
 CodeGeneratorRequest* CodeGeneratorRequest::default_instance_ = NULL;
 CodeGeneratorRequest* CodeGeneratorRequest::default_instance_ = NULL;
 
 
 CodeGeneratorRequest* CodeGeneratorRequest::New(::google::protobuf::Arena* arena) const {
 CodeGeneratorRequest* CodeGeneratorRequest::New(::google::protobuf::Arena* arena) const {
-  return ::google::protobuf::Arena::CreateMessage<CodeGeneratorRequest>(arena);
+  CodeGeneratorRequest* n = new CodeGeneratorRequest;
+  if (arena != NULL) {
+    arena->Own(n);
+  }
+  return n;
 }
 }
 
 
 void CodeGeneratorRequest::Clear() {
 void CodeGeneratorRequest::Clear() {
   if (has_parameter()) {
   if (has_parameter()) {
-    parameter_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+    parameter_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
   }
   }
   file_to_generate_.Clear();
   file_to_generate_.Clear();
   proto_file_.Clear();
   proto_file_.Clear();
@@ -365,7 +353,7 @@ void CodeGeneratorRequest::SerializeWithCachedSizes(
   }
   }
 
 
   // repeated .google.protobuf.FileDescriptorProto proto_file = 15;
   // repeated .google.protobuf.FileDescriptorProto proto_file = 15;
-  for (int i = 0; i < this->proto_file_size(); i++) {
+  for (unsigned int i = 0, n = this->proto_file_size(); i < n; i++) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
       15, this->proto_file(i), output);
       15, this->proto_file(i), output);
   }
   }
@@ -402,7 +390,7 @@ void CodeGeneratorRequest::SerializeWithCachedSizes(
   }
   }
 
 
   // repeated .google.protobuf.FileDescriptorProto proto_file = 15;
   // repeated .google.protobuf.FileDescriptorProto proto_file = 15;
-  for (int i = 0; i < this->proto_file_size(); i++) {
+  for (unsigned int i = 0, n = this->proto_file_size(); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
     target = ::google::protobuf::internal::WireFormatLite::
       WriteMessageNoVirtualToArray(
       WriteMessageNoVirtualToArray(
         15, this->proto_file(i), target);
         15, this->proto_file(i), target);
@@ -453,7 +441,7 @@ int CodeGeneratorRequest::ByteSize() const {
 }
 }
 
 
 void CodeGeneratorRequest::MergeFrom(const ::google::protobuf::Message& from) {
 void CodeGeneratorRequest::MergeFrom(const ::google::protobuf::Message& from) {
-  GOOGLE_CHECK_NE(&from, this);
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
   const CodeGeneratorRequest* source =
   const CodeGeneratorRequest* source =
     ::google::protobuf::internal::dynamic_cast_if_available<const CodeGeneratorRequest*>(
     ::google::protobuf::internal::dynamic_cast_if_available<const CodeGeneratorRequest*>(
       &from);
       &from);
@@ -465,12 +453,13 @@ void CodeGeneratorRequest::MergeFrom(const ::google::protobuf::Message& from) {
 }
 }
 
 
 void CodeGeneratorRequest::MergeFrom(const CodeGeneratorRequest& from) {
 void CodeGeneratorRequest::MergeFrom(const CodeGeneratorRequest& from) {
-  GOOGLE_CHECK_NE(&from, this);
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
   file_to_generate_.MergeFrom(from.file_to_generate_);
   file_to_generate_.MergeFrom(from.file_to_generate_);
   proto_file_.MergeFrom(from.proto_file_);
   proto_file_.MergeFrom(from.proto_file_);
   if (from._has_bits_[1 / 32] & (0xffu << (1 % 32))) {
   if (from._has_bits_[1 / 32] & (0xffu << (1 % 32))) {
     if (from.has_parameter()) {
     if (from.has_parameter()) {
-      set_parameter(from.parameter());
+      set_has_parameter();
+      parameter_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.parameter_);
     }
     }
   }
   }
   if (from._internal_metadata_.have_unknown_fields()) {
   if (from._internal_metadata_.have_unknown_fields()) {
@@ -498,18 +487,6 @@ bool CodeGeneratorRequest::IsInitialized() const {
 
 
 void CodeGeneratorRequest::Swap(CodeGeneratorRequest* other) {
 void CodeGeneratorRequest::Swap(CodeGeneratorRequest* other) {
   if (other == this) return;
   if (other == this) return;
-  if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {
-    InternalSwap(other);
-  } else {
-    CodeGeneratorRequest temp;
-    temp.MergeFrom(*this);
-    CopyFrom(*other);
-    other->CopyFrom(temp);
-  }
-}
-void CodeGeneratorRequest::UnsafeArenaSwap(CodeGeneratorRequest* other) {
-  if (other == this) return;
-  GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual());
   InternalSwap(other);
   InternalSwap(other);
 }
 }
 void CodeGeneratorRequest::InternalSwap(CodeGeneratorRequest* other) {
 void CodeGeneratorRequest::InternalSwap(CodeGeneratorRequest* other) {
@@ -544,14 +521,6 @@ CodeGeneratorResponse_File::CodeGeneratorResponse_File()
   // @@protoc_insertion_point(constructor:google.protobuf.compiler.CodeGeneratorResponse.File)
   // @@protoc_insertion_point(constructor:google.protobuf.compiler.CodeGeneratorResponse.File)
 }
 }
 
 
-CodeGeneratorResponse_File::CodeGeneratorResponse_File(::google::protobuf::Arena* arena)
-  : ::google::protobuf::Message(),
-  _internal_metadata_(arena) {
-  SharedCtor();
-  RegisterArenaDtor(arena);
-  // @@protoc_insertion_point(arena_constructor:google.protobuf.compiler.CodeGeneratorResponse.File)
-}
-
 void CodeGeneratorResponse_File::InitAsDefaultInstance() {
 void CodeGeneratorResponse_File::InitAsDefaultInstance() {
 }
 }
 
 
@@ -578,23 +547,13 @@ CodeGeneratorResponse_File::~CodeGeneratorResponse_File() {
 }
 }
 
 
 void CodeGeneratorResponse_File::SharedDtor() {
 void CodeGeneratorResponse_File::SharedDtor() {
-  if (GetArenaNoVirtual() != NULL) {
-    return;
-  }
-
-  name_.Destroy(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
-  insertion_point_.Destroy(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
-  content_.Destroy(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+  name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  insertion_point_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  content_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
   if (this != default_instance_) {
   if (this != default_instance_) {
   }
   }
 }
 }
 
 
-void CodeGeneratorResponse_File::ArenaDtor(void* object) {
-  CodeGeneratorResponse_File* _this = reinterpret_cast< CodeGeneratorResponse_File* >(object);
-  (void)_this;
-}
-void CodeGeneratorResponse_File::RegisterArenaDtor(::google::protobuf::Arena* arena) {
-}
 void CodeGeneratorResponse_File::SetCachedSize(int size) const {
 void CodeGeneratorResponse_File::SetCachedSize(int size) const {
   GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
   GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
   _cached_size_ = size;
   _cached_size_ = size;
@@ -613,19 +572,23 @@ const CodeGeneratorResponse_File& CodeGeneratorResponse_File::default_instance()
 CodeGeneratorResponse_File* CodeGeneratorResponse_File::default_instance_ = NULL;
 CodeGeneratorResponse_File* CodeGeneratorResponse_File::default_instance_ = NULL;
 
 
 CodeGeneratorResponse_File* CodeGeneratorResponse_File::New(::google::protobuf::Arena* arena) const {
 CodeGeneratorResponse_File* CodeGeneratorResponse_File::New(::google::protobuf::Arena* arena) const {
-  return ::google::protobuf::Arena::CreateMessage<CodeGeneratorResponse_File>(arena);
+  CodeGeneratorResponse_File* n = new CodeGeneratorResponse_File;
+  if (arena != NULL) {
+    arena->Own(n);
+  }
+  return n;
 }
 }
 
 
 void CodeGeneratorResponse_File::Clear() {
 void CodeGeneratorResponse_File::Clear() {
   if (_has_bits_[0 / 32] & 7) {
   if (_has_bits_[0 / 32] & 7) {
     if (has_name()) {
     if (has_name()) {
-      name_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+      name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
     }
     }
     if (has_insertion_point()) {
     if (has_insertion_point()) {
-      insertion_point_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+      insertion_point_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
     }
     }
     if (has_content()) {
     if (has_content()) {
-      content_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+      content_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
     }
     }
   }
   }
   ::memset(_has_bits_, 0, sizeof(_has_bits_));
   ::memset(_has_bits_, 0, sizeof(_has_bits_));
@@ -838,7 +801,7 @@ int CodeGeneratorResponse_File::ByteSize() const {
 }
 }
 
 
 void CodeGeneratorResponse_File::MergeFrom(const ::google::protobuf::Message& from) {
 void CodeGeneratorResponse_File::MergeFrom(const ::google::protobuf::Message& from) {
-  GOOGLE_CHECK_NE(&from, this);
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
   const CodeGeneratorResponse_File* source =
   const CodeGeneratorResponse_File* source =
     ::google::protobuf::internal::dynamic_cast_if_available<const CodeGeneratorResponse_File*>(
     ::google::protobuf::internal::dynamic_cast_if_available<const CodeGeneratorResponse_File*>(
       &from);
       &from);
@@ -850,16 +813,19 @@ void CodeGeneratorResponse_File::MergeFrom(const ::google::protobuf::Message& fr
 }
 }
 
 
 void CodeGeneratorResponse_File::MergeFrom(const CodeGeneratorResponse_File& from) {
 void CodeGeneratorResponse_File::MergeFrom(const CodeGeneratorResponse_File& from) {
-  GOOGLE_CHECK_NE(&from, this);
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
   if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
   if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
     if (from.has_name()) {
     if (from.has_name()) {
-      set_name(from.name());
+      set_has_name();
+      name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_);
     }
     }
     if (from.has_insertion_point()) {
     if (from.has_insertion_point()) {
-      set_insertion_point(from.insertion_point());
+      set_has_insertion_point();
+      insertion_point_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.insertion_point_);
     }
     }
     if (from.has_content()) {
     if (from.has_content()) {
-      set_content(from.content());
+      set_has_content();
+      content_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.content_);
     }
     }
   }
   }
   if (from._internal_metadata_.have_unknown_fields()) {
   if (from._internal_metadata_.have_unknown_fields()) {
@@ -886,18 +852,6 @@ bool CodeGeneratorResponse_File::IsInitialized() const {
 
 
 void CodeGeneratorResponse_File::Swap(CodeGeneratorResponse_File* other) {
 void CodeGeneratorResponse_File::Swap(CodeGeneratorResponse_File* other) {
   if (other == this) return;
   if (other == this) return;
-  if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {
-    InternalSwap(other);
-  } else {
-    CodeGeneratorResponse_File temp;
-    temp.MergeFrom(*this);
-    CopyFrom(*other);
-    other->CopyFrom(temp);
-  }
-}
-void CodeGeneratorResponse_File::UnsafeArenaSwap(CodeGeneratorResponse_File* other) {
-  if (other == this) return;
-  GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual());
   InternalSwap(other);
   InternalSwap(other);
 }
 }
 void CodeGeneratorResponse_File::InternalSwap(CodeGeneratorResponse_File* other) {
 void CodeGeneratorResponse_File::InternalSwap(CodeGeneratorResponse_File* other) {
@@ -931,15 +885,6 @@ CodeGeneratorResponse::CodeGeneratorResponse()
   // @@protoc_insertion_point(constructor:google.protobuf.compiler.CodeGeneratorResponse)
   // @@protoc_insertion_point(constructor:google.protobuf.compiler.CodeGeneratorResponse)
 }
 }
 
 
-CodeGeneratorResponse::CodeGeneratorResponse(::google::protobuf::Arena* arena)
-  : ::google::protobuf::Message(),
-  _internal_metadata_(arena),
-  file_(arena) {
-  SharedCtor();
-  RegisterArenaDtor(arena);
-  // @@protoc_insertion_point(arena_constructor:google.protobuf.compiler.CodeGeneratorResponse)
-}
-
 void CodeGeneratorResponse::InitAsDefaultInstance() {
 void CodeGeneratorResponse::InitAsDefaultInstance() {
 }
 }
 
 
@@ -964,21 +909,11 @@ CodeGeneratorResponse::~CodeGeneratorResponse() {
 }
 }
 
 
 void CodeGeneratorResponse::SharedDtor() {
 void CodeGeneratorResponse::SharedDtor() {
-  if (GetArenaNoVirtual() != NULL) {
-    return;
-  }
-
-  error_.Destroy(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+  error_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
   if (this != default_instance_) {
   if (this != default_instance_) {
   }
   }
 }
 }
 
 
-void CodeGeneratorResponse::ArenaDtor(void* object) {
-  CodeGeneratorResponse* _this = reinterpret_cast< CodeGeneratorResponse* >(object);
-  (void)_this;
-}
-void CodeGeneratorResponse::RegisterArenaDtor(::google::protobuf::Arena* arena) {
-}
 void CodeGeneratorResponse::SetCachedSize(int size) const {
 void CodeGeneratorResponse::SetCachedSize(int size) const {
   GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
   GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
   _cached_size_ = size;
   _cached_size_ = size;
@@ -997,12 +932,16 @@ const CodeGeneratorResponse& CodeGeneratorResponse::default_instance() {
 CodeGeneratorResponse* CodeGeneratorResponse::default_instance_ = NULL;
 CodeGeneratorResponse* CodeGeneratorResponse::default_instance_ = NULL;
 
 
 CodeGeneratorResponse* CodeGeneratorResponse::New(::google::protobuf::Arena* arena) const {
 CodeGeneratorResponse* CodeGeneratorResponse::New(::google::protobuf::Arena* arena) const {
-  return ::google::protobuf::Arena::CreateMessage<CodeGeneratorResponse>(arena);
+  CodeGeneratorResponse* n = new CodeGeneratorResponse;
+  if (arena != NULL) {
+    arena->Own(n);
+  }
+  return n;
 }
 }
 
 
 void CodeGeneratorResponse::Clear() {
 void CodeGeneratorResponse::Clear() {
   if (has_error()) {
   if (has_error()) {
-    error_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+    error_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
   }
   }
   file_.Clear();
   file_.Clear();
   ::memset(_has_bits_, 0, sizeof(_has_bits_));
   ::memset(_has_bits_, 0, sizeof(_has_bits_));
@@ -1087,7 +1026,7 @@ void CodeGeneratorResponse::SerializeWithCachedSizes(
   }
   }
 
 
   // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
   // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
-  for (int i = 0; i < this->file_size(); i++) {
+  for (unsigned int i = 0, n = this->file_size(); i < n; i++) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
       15, this->file(i), output);
       15, this->file(i), output);
   }
   }
@@ -1114,7 +1053,7 @@ void CodeGeneratorResponse::SerializeWithCachedSizes(
   }
   }
 
 
   // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
   // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
-  for (int i = 0; i < this->file_size(); i++) {
+  for (unsigned int i = 0, n = this->file_size(); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
     target = ::google::protobuf::internal::WireFormatLite::
       WriteMessageNoVirtualToArray(
       WriteMessageNoVirtualToArray(
         15, this->file(i), target);
         15, this->file(i), target);
@@ -1158,7 +1097,7 @@ int CodeGeneratorResponse::ByteSize() const {
 }
 }
 
 
 void CodeGeneratorResponse::MergeFrom(const ::google::protobuf::Message& from) {
 void CodeGeneratorResponse::MergeFrom(const ::google::protobuf::Message& from) {
-  GOOGLE_CHECK_NE(&from, this);
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
   const CodeGeneratorResponse* source =
   const CodeGeneratorResponse* source =
     ::google::protobuf::internal::dynamic_cast_if_available<const CodeGeneratorResponse*>(
     ::google::protobuf::internal::dynamic_cast_if_available<const CodeGeneratorResponse*>(
       &from);
       &from);
@@ -1170,11 +1109,12 @@ void CodeGeneratorResponse::MergeFrom(const ::google::protobuf::Message& from) {
 }
 }
 
 
 void CodeGeneratorResponse::MergeFrom(const CodeGeneratorResponse& from) {
 void CodeGeneratorResponse::MergeFrom(const CodeGeneratorResponse& from) {
-  GOOGLE_CHECK_NE(&from, this);
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
   file_.MergeFrom(from.file_);
   file_.MergeFrom(from.file_);
   if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
   if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
     if (from.has_error()) {
     if (from.has_error()) {
-      set_error(from.error());
+      set_has_error();
+      error_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.error_);
     }
     }
   }
   }
   if (from._internal_metadata_.have_unknown_fields()) {
   if (from._internal_metadata_.have_unknown_fields()) {
@@ -1201,18 +1141,6 @@ bool CodeGeneratorResponse::IsInitialized() const {
 
 
 void CodeGeneratorResponse::Swap(CodeGeneratorResponse* other) {
 void CodeGeneratorResponse::Swap(CodeGeneratorResponse* other) {
   if (other == this) return;
   if (other == this) return;
-  if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {
-    InternalSwap(other);
-  } else {
-    CodeGeneratorResponse temp;
-    temp.MergeFrom(*this);
-    CopyFrom(*other);
-    other->CopyFrom(temp);
-  }
-}
-void CodeGeneratorResponse::UnsafeArenaSwap(CodeGeneratorResponse* other) {
-  if (other == this) return;
-  GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual());
   InternalSwap(other);
   InternalSwap(other);
 }
 }
 void CodeGeneratorResponse::InternalSwap(CodeGeneratorResponse* other) {
 void CodeGeneratorResponse::InternalSwap(CodeGeneratorResponse* other) {

+ 50 - 215
src/google/protobuf/compiler/plugin.pb.h

@@ -5,7 +5,6 @@
 #define PROTOBUF_google_2fprotobuf_2fcompiler_2fplugin_2eproto__INCLUDED
 #define PROTOBUF_google_2fprotobuf_2fcompiler_2fplugin_2eproto__INCLUDED
 
 
 #include <string>
 #include <string>
-#include <stdint.h>
 
 
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/stubs/common.h>
 
 
@@ -66,14 +65,9 @@ class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message
     return _internal_metadata_.mutable_unknown_fields();
     return _internal_metadata_.mutable_unknown_fields();
   }
   }
 
 
-  inline ::google::protobuf::Arena* GetArena() const { return GetArenaNoVirtual(); }
-  inline void* GetMaybeArenaPointer() const {
-    return MaybeArenaPtr();
-  }
   static const ::google::protobuf::Descriptor* descriptor();
   static const ::google::protobuf::Descriptor* descriptor();
   static const CodeGeneratorRequest& default_instance();
   static const CodeGeneratorRequest& default_instance();
 
 
-  void UnsafeArenaSwap(CodeGeneratorRequest* other);
   void Swap(CodeGeneratorRequest* other);
   void Swap(CodeGeneratorRequest* other);
 
 
   // implements Message ----------------------------------------------
   // implements Message ----------------------------------------------
@@ -100,11 +94,6 @@ class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message
   void SharedDtor();
   void SharedDtor();
   void SetCachedSize(int size) const;
   void SetCachedSize(int size) const;
   void InternalSwap(CodeGeneratorRequest* other);
   void InternalSwap(CodeGeneratorRequest* other);
-  protected:
-  explicit CodeGeneratorRequest(::google::protobuf::Arena* arena);
-  private:
-  static void ArenaDtor(void* object);
-  inline void RegisterArenaDtor(::google::protobuf::Arena* arena);
   private:
   private:
   inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
   inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
     return _internal_metadata_.arena();
     return _internal_metadata_.arena();
@@ -147,9 +136,6 @@ class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message
   inline ::std::string* mutable_parameter();
   inline ::std::string* mutable_parameter();
   inline ::std::string* release_parameter();
   inline ::std::string* release_parameter();
   inline void set_allocated_parameter(::std::string* parameter);
   inline void set_allocated_parameter(::std::string* parameter);
-  inline ::std::string* unsafe_arena_release_parameter();
-  inline void unsafe_arena_set_allocated_parameter(
-      ::std::string* parameter);
 
 
   // repeated .google.protobuf.FileDescriptorProto proto_file = 15;
   // repeated .google.protobuf.FileDescriptorProto proto_file = 15;
   inline int proto_file_size() const;
   inline int proto_file_size() const;
@@ -169,9 +155,6 @@ class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message
   inline void clear_has_parameter();
   inline void clear_has_parameter();
 
 
   ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
   ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
-  friend class ::google::protobuf::Arena;
-  typedef void InternalArenaConstructable_;
-  typedef void DestructorSkippable_;
   ::google::protobuf::uint32 _has_bits_[1];
   ::google::protobuf::uint32 _has_bits_[1];
   mutable int _cached_size_;
   mutable int _cached_size_;
   ::google::protobuf::RepeatedPtrField< ::std::string> file_to_generate_;
   ::google::protobuf::RepeatedPtrField< ::std::string> file_to_generate_;
@@ -206,14 +189,9 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::M
     return _internal_metadata_.mutable_unknown_fields();
     return _internal_metadata_.mutable_unknown_fields();
   }
   }
 
 
-  inline ::google::protobuf::Arena* GetArena() const { return GetArenaNoVirtual(); }
-  inline void* GetMaybeArenaPointer() const {
-    return MaybeArenaPtr();
-  }
   static const ::google::protobuf::Descriptor* descriptor();
   static const ::google::protobuf::Descriptor* descriptor();
   static const CodeGeneratorResponse_File& default_instance();
   static const CodeGeneratorResponse_File& default_instance();
 
 
-  void UnsafeArenaSwap(CodeGeneratorResponse_File* other);
   void Swap(CodeGeneratorResponse_File* other);
   void Swap(CodeGeneratorResponse_File* other);
 
 
   // implements Message ----------------------------------------------
   // implements Message ----------------------------------------------
@@ -240,11 +218,6 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::M
   void SharedDtor();
   void SharedDtor();
   void SetCachedSize(int size) const;
   void SetCachedSize(int size) const;
   void InternalSwap(CodeGeneratorResponse_File* other);
   void InternalSwap(CodeGeneratorResponse_File* other);
-  protected:
-  explicit CodeGeneratorResponse_File(::google::protobuf::Arena* arena);
-  private:
-  static void ArenaDtor(void* object);
-  inline void RegisterArenaDtor(::google::protobuf::Arena* arena);
   private:
   private:
   inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
   inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
     return _internal_metadata_.arena();
     return _internal_metadata_.arena();
@@ -271,9 +244,6 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::M
   inline ::std::string* mutable_name();
   inline ::std::string* mutable_name();
   inline ::std::string* release_name();
   inline ::std::string* release_name();
   inline void set_allocated_name(::std::string* name);
   inline void set_allocated_name(::std::string* name);
-  inline ::std::string* unsafe_arena_release_name();
-  inline void unsafe_arena_set_allocated_name(
-      ::std::string* name);
 
 
   // optional string insertion_point = 2;
   // optional string insertion_point = 2;
   inline bool has_insertion_point() const;
   inline bool has_insertion_point() const;
@@ -286,9 +256,6 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::M
   inline ::std::string* mutable_insertion_point();
   inline ::std::string* mutable_insertion_point();
   inline ::std::string* release_insertion_point();
   inline ::std::string* release_insertion_point();
   inline void set_allocated_insertion_point(::std::string* insertion_point);
   inline void set_allocated_insertion_point(::std::string* insertion_point);
-  inline ::std::string* unsafe_arena_release_insertion_point();
-  inline void unsafe_arena_set_allocated_insertion_point(
-      ::std::string* insertion_point);
 
 
   // optional string content = 15;
   // optional string content = 15;
   inline bool has_content() const;
   inline bool has_content() const;
@@ -301,9 +268,6 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::M
   inline ::std::string* mutable_content();
   inline ::std::string* mutable_content();
   inline ::std::string* release_content();
   inline ::std::string* release_content();
   inline void set_allocated_content(::std::string* content);
   inline void set_allocated_content(::std::string* content);
-  inline ::std::string* unsafe_arena_release_content();
-  inline void unsafe_arena_set_allocated_content(
-      ::std::string* content);
 
 
   // @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse.File)
   // @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse.File)
  private:
  private:
@@ -315,9 +279,6 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::M
   inline void clear_has_content();
   inline void clear_has_content();
 
 
   ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
   ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
-  friend class ::google::protobuf::Arena;
-  typedef void InternalArenaConstructable_;
-  typedef void DestructorSkippable_;
   ::google::protobuf::uint32 _has_bits_[1];
   ::google::protobuf::uint32 _has_bits_[1];
   mutable int _cached_size_;
   mutable int _cached_size_;
   ::google::protobuf::internal::ArenaStringPtr name_;
   ::google::protobuf::internal::ArenaStringPtr name_;
@@ -352,14 +313,9 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Messag
     return _internal_metadata_.mutable_unknown_fields();
     return _internal_metadata_.mutable_unknown_fields();
   }
   }
 
 
-  inline ::google::protobuf::Arena* GetArena() const { return GetArenaNoVirtual(); }
-  inline void* GetMaybeArenaPointer() const {
-    return MaybeArenaPtr();
-  }
   static const ::google::protobuf::Descriptor* descriptor();
   static const ::google::protobuf::Descriptor* descriptor();
   static const CodeGeneratorResponse& default_instance();
   static const CodeGeneratorResponse& default_instance();
 
 
-  void UnsafeArenaSwap(CodeGeneratorResponse* other);
   void Swap(CodeGeneratorResponse* other);
   void Swap(CodeGeneratorResponse* other);
 
 
   // implements Message ----------------------------------------------
   // implements Message ----------------------------------------------
@@ -386,11 +342,6 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Messag
   void SharedDtor();
   void SharedDtor();
   void SetCachedSize(int size) const;
   void SetCachedSize(int size) const;
   void InternalSwap(CodeGeneratorResponse* other);
   void InternalSwap(CodeGeneratorResponse* other);
-  protected:
-  explicit CodeGeneratorResponse(::google::protobuf::Arena* arena);
-  private:
-  static void ArenaDtor(void* object);
-  inline void RegisterArenaDtor(::google::protobuf::Arena* arena);
   private:
   private:
   inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
   inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
     return _internal_metadata_.arena();
     return _internal_metadata_.arena();
@@ -419,9 +370,6 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Messag
   inline ::std::string* mutable_error();
   inline ::std::string* mutable_error();
   inline ::std::string* release_error();
   inline ::std::string* release_error();
   inline void set_allocated_error(::std::string* error);
   inline void set_allocated_error(::std::string* error);
-  inline ::std::string* unsafe_arena_release_error();
-  inline void unsafe_arena_set_allocated_error(
-      ::std::string* error);
 
 
   // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
   // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
   inline int file_size() const;
   inline int file_size() const;
@@ -441,9 +389,6 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Messag
   inline void clear_has_error();
   inline void clear_has_error();
 
 
   ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
   ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
-  friend class ::google::protobuf::Arena;
-  typedef void InternalArenaConstructable_;
-  typedef void DestructorSkippable_;
   ::google::protobuf::uint32 _has_bits_[1];
   ::google::protobuf::uint32 _has_bits_[1];
   mutable int _cached_size_;
   mutable int _cached_size_;
   ::google::protobuf::internal::ArenaStringPtr error_;
   ::google::protobuf::internal::ArenaStringPtr error_;
@@ -527,45 +472,37 @@ inline void CodeGeneratorRequest::clear_has_parameter() {
   _has_bits_[0] &= ~0x00000002u;
   _has_bits_[0] &= ~0x00000002u;
 }
 }
 inline void CodeGeneratorRequest::clear_parameter() {
 inline void CodeGeneratorRequest::clear_parameter() {
-  parameter_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+  parameter_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
   clear_has_parameter();
   clear_has_parameter();
 }
 }
 inline const ::std::string& CodeGeneratorRequest::parameter() const {
 inline const ::std::string& CodeGeneratorRequest::parameter() const {
   // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.parameter)
   // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.parameter)
-  return parameter_.Get(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  return parameter_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
 }
 }
 inline void CodeGeneratorRequest::set_parameter(const ::std::string& value) {
 inline void CodeGeneratorRequest::set_parameter(const ::std::string& value) {
   set_has_parameter();
   set_has_parameter();
-  parameter_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
+  parameter_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
   // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorRequest.parameter)
   // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorRequest.parameter)
 }
 }
 inline void CodeGeneratorRequest::set_parameter(const char* value) {
 inline void CodeGeneratorRequest::set_parameter(const char* value) {
   set_has_parameter();
   set_has_parameter();
-  parameter_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
-              GetArenaNoVirtual());
+  parameter_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
   // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorRequest.parameter)
   // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorRequest.parameter)
 }
 }
-inline void CodeGeneratorRequest::set_parameter(const char* value,
-    size_t size) {
+inline void CodeGeneratorRequest::set_parameter(const char* value, size_t size) {
   set_has_parameter();
   set_has_parameter();
-  parameter_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArenaNoVirtual());
+  parameter_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
   // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorRequest.parameter)
   // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorRequest.parameter)
 }
 }
 inline ::std::string* CodeGeneratorRequest::mutable_parameter() {
 inline ::std::string* CodeGeneratorRequest::mutable_parameter() {
   set_has_parameter();
   set_has_parameter();
   // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.parameter)
   // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.parameter)
-  return parameter_.Mutable(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+  return parameter_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
 }
 }
 inline ::std::string* CodeGeneratorRequest::release_parameter() {
 inline ::std::string* CodeGeneratorRequest::release_parameter() {
   clear_has_parameter();
   clear_has_parameter();
-  return parameter_.Release(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
-}
-inline ::std::string* CodeGeneratorRequest::unsafe_arena_release_parameter() {
-  GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
-  clear_has_parameter();
-  return parameter_.UnsafeArenaRelease(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
-      GetArenaNoVirtual());
+  return parameter_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
 }
 }
 inline void CodeGeneratorRequest::set_allocated_parameter(::std::string* parameter) {
 inline void CodeGeneratorRequest::set_allocated_parameter(::std::string* parameter) {
   if (parameter != NULL) {
   if (parameter != NULL) {
@@ -573,21 +510,7 @@ inline void CodeGeneratorRequest::set_allocated_parameter(::std::string* paramet
   } else {
   } else {
     clear_has_parameter();
     clear_has_parameter();
   }
   }
-  parameter_.SetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), parameter,
-      GetArenaNoVirtual());
-  // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorRequest.parameter)
-}
-inline void CodeGeneratorRequest::unsafe_arena_set_allocated_parameter(
-    ::std::string* parameter) {
-  GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
-  if (parameter != NULL) {
-    set_has_parameter();
-  } else {
-    clear_has_parameter();
-  }
-  set_has_parameter();
-  parameter_.UnsafeArenaSetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
-      parameter, GetArenaNoVirtual());
+  parameter_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), parameter);
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorRequest.parameter)
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorRequest.parameter)
 }
 }
 
 
@@ -636,45 +559,37 @@ inline void CodeGeneratorResponse_File::clear_has_name() {
   _has_bits_[0] &= ~0x00000001u;
   _has_bits_[0] &= ~0x00000001u;
 }
 }
 inline void CodeGeneratorResponse_File::clear_name() {
 inline void CodeGeneratorResponse_File::clear_name() {
-  name_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
   clear_has_name();
   clear_has_name();
 }
 }
 inline const ::std::string& CodeGeneratorResponse_File::name() const {
 inline const ::std::string& CodeGeneratorResponse_File::name() const {
   // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.name)
   // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.name)
-  return name_.Get(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
 }
 }
 inline void CodeGeneratorResponse_File::set_name(const ::std::string& value) {
 inline void CodeGeneratorResponse_File::set_name(const ::std::string& value) {
   set_has_name();
   set_has_name();
-  name_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
   // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.name)
   // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.name)
 }
 }
 inline void CodeGeneratorResponse_File::set_name(const char* value) {
 inline void CodeGeneratorResponse_File::set_name(const char* value) {
   set_has_name();
   set_has_name();
-  name_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
-              GetArenaNoVirtual());
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
   // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.name)
   // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.name)
 }
 }
-inline void CodeGeneratorResponse_File::set_name(const char* value,
-    size_t size) {
+inline void CodeGeneratorResponse_File::set_name(const char* value, size_t size) {
   set_has_name();
   set_has_name();
-  name_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArenaNoVirtual());
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
   // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.name)
   // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.name)
 }
 }
 inline ::std::string* CodeGeneratorResponse_File::mutable_name() {
 inline ::std::string* CodeGeneratorResponse_File::mutable_name() {
   set_has_name();
   set_has_name();
   // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.name)
   // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.name)
-  return name_.Mutable(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+  return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
 }
 }
 inline ::std::string* CodeGeneratorResponse_File::release_name() {
 inline ::std::string* CodeGeneratorResponse_File::release_name() {
   clear_has_name();
   clear_has_name();
-  return name_.Release(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
-}
-inline ::std::string* CodeGeneratorResponse_File::unsafe_arena_release_name() {
-  GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
-  clear_has_name();
-  return name_.UnsafeArenaRelease(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
-      GetArenaNoVirtual());
+  return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
 }
 }
 inline void CodeGeneratorResponse_File::set_allocated_name(::std::string* name) {
 inline void CodeGeneratorResponse_File::set_allocated_name(::std::string* name) {
   if (name != NULL) {
   if (name != NULL) {
@@ -682,21 +597,7 @@ inline void CodeGeneratorResponse_File::set_allocated_name(::std::string* name)
   } else {
   } else {
     clear_has_name();
     clear_has_name();
   }
   }
-  name_.SetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name,
-      GetArenaNoVirtual());
-  // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.name)
-}
-inline void CodeGeneratorResponse_File::unsafe_arena_set_allocated_name(
-    ::std::string* name) {
-  GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
-  if (name != NULL) {
-    set_has_name();
-  } else {
-    clear_has_name();
-  }
-  set_has_name();
-  name_.UnsafeArenaSetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
-      name, GetArenaNoVirtual());
+  name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.name)
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.name)
 }
 }
 
 
@@ -711,45 +612,37 @@ inline void CodeGeneratorResponse_File::clear_has_insertion_point() {
   _has_bits_[0] &= ~0x00000002u;
   _has_bits_[0] &= ~0x00000002u;
 }
 }
 inline void CodeGeneratorResponse_File::clear_insertion_point() {
 inline void CodeGeneratorResponse_File::clear_insertion_point() {
-  insertion_point_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+  insertion_point_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
   clear_has_insertion_point();
   clear_has_insertion_point();
 }
 }
 inline const ::std::string& CodeGeneratorResponse_File::insertion_point() const {
 inline const ::std::string& CodeGeneratorResponse_File::insertion_point() const {
   // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
   // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
-  return insertion_point_.Get(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  return insertion_point_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
 }
 }
 inline void CodeGeneratorResponse_File::set_insertion_point(const ::std::string& value) {
 inline void CodeGeneratorResponse_File::set_insertion_point(const ::std::string& value) {
   set_has_insertion_point();
   set_has_insertion_point();
-  insertion_point_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
+  insertion_point_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
   // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
   // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
 }
 }
 inline void CodeGeneratorResponse_File::set_insertion_point(const char* value) {
 inline void CodeGeneratorResponse_File::set_insertion_point(const char* value) {
   set_has_insertion_point();
   set_has_insertion_point();
-  insertion_point_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
-              GetArenaNoVirtual());
+  insertion_point_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
   // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
   // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
 }
 }
-inline void CodeGeneratorResponse_File::set_insertion_point(const char* value,
-    size_t size) {
+inline void CodeGeneratorResponse_File::set_insertion_point(const char* value, size_t size) {
   set_has_insertion_point();
   set_has_insertion_point();
-  insertion_point_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArenaNoVirtual());
+  insertion_point_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
   // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
   // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
 }
 }
 inline ::std::string* CodeGeneratorResponse_File::mutable_insertion_point() {
 inline ::std::string* CodeGeneratorResponse_File::mutable_insertion_point() {
   set_has_insertion_point();
   set_has_insertion_point();
   // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
   // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
-  return insertion_point_.Mutable(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+  return insertion_point_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
 }
 }
 inline ::std::string* CodeGeneratorResponse_File::release_insertion_point() {
 inline ::std::string* CodeGeneratorResponse_File::release_insertion_point() {
   clear_has_insertion_point();
   clear_has_insertion_point();
-  return insertion_point_.Release(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
-}
-inline ::std::string* CodeGeneratorResponse_File::unsafe_arena_release_insertion_point() {
-  GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
-  clear_has_insertion_point();
-  return insertion_point_.UnsafeArenaRelease(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
-      GetArenaNoVirtual());
+  return insertion_point_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
 }
 }
 inline void CodeGeneratorResponse_File::set_allocated_insertion_point(::std::string* insertion_point) {
 inline void CodeGeneratorResponse_File::set_allocated_insertion_point(::std::string* insertion_point) {
   if (insertion_point != NULL) {
   if (insertion_point != NULL) {
@@ -757,21 +650,7 @@ inline void CodeGeneratorResponse_File::set_allocated_insertion_point(::std::str
   } else {
   } else {
     clear_has_insertion_point();
     clear_has_insertion_point();
   }
   }
-  insertion_point_.SetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), insertion_point,
-      GetArenaNoVirtual());
-  // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
-}
-inline void CodeGeneratorResponse_File::unsafe_arena_set_allocated_insertion_point(
-    ::std::string* insertion_point) {
-  GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
-  if (insertion_point != NULL) {
-    set_has_insertion_point();
-  } else {
-    clear_has_insertion_point();
-  }
-  set_has_insertion_point();
-  insertion_point_.UnsafeArenaSetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
-      insertion_point, GetArenaNoVirtual());
+  insertion_point_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), insertion_point);
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
 }
 }
 
 
@@ -786,45 +665,37 @@ inline void CodeGeneratorResponse_File::clear_has_content() {
   _has_bits_[0] &= ~0x00000004u;
   _has_bits_[0] &= ~0x00000004u;
 }
 }
 inline void CodeGeneratorResponse_File::clear_content() {
 inline void CodeGeneratorResponse_File::clear_content() {
-  content_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+  content_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
   clear_has_content();
   clear_has_content();
 }
 }
 inline const ::std::string& CodeGeneratorResponse_File::content() const {
 inline const ::std::string& CodeGeneratorResponse_File::content() const {
   // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.content)
   // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.content)
-  return content_.Get(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  return content_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
 }
 }
 inline void CodeGeneratorResponse_File::set_content(const ::std::string& value) {
 inline void CodeGeneratorResponse_File::set_content(const ::std::string& value) {
   set_has_content();
   set_has_content();
-  content_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
+  content_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
   // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.content)
   // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.content)
 }
 }
 inline void CodeGeneratorResponse_File::set_content(const char* value) {
 inline void CodeGeneratorResponse_File::set_content(const char* value) {
   set_has_content();
   set_has_content();
-  content_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
-              GetArenaNoVirtual());
+  content_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
   // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.content)
   // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.content)
 }
 }
-inline void CodeGeneratorResponse_File::set_content(const char* value,
-    size_t size) {
+inline void CodeGeneratorResponse_File::set_content(const char* value, size_t size) {
   set_has_content();
   set_has_content();
-  content_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArenaNoVirtual());
+  content_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
   // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.content)
   // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.content)
 }
 }
 inline ::std::string* CodeGeneratorResponse_File::mutable_content() {
 inline ::std::string* CodeGeneratorResponse_File::mutable_content() {
   set_has_content();
   set_has_content();
   // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.content)
   // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.content)
-  return content_.Mutable(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+  return content_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
 }
 }
 inline ::std::string* CodeGeneratorResponse_File::release_content() {
 inline ::std::string* CodeGeneratorResponse_File::release_content() {
   clear_has_content();
   clear_has_content();
-  return content_.Release(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
-}
-inline ::std::string* CodeGeneratorResponse_File::unsafe_arena_release_content() {
-  GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
-  clear_has_content();
-  return content_.UnsafeArenaRelease(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
-      GetArenaNoVirtual());
+  return content_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
 }
 }
 inline void CodeGeneratorResponse_File::set_allocated_content(::std::string* content) {
 inline void CodeGeneratorResponse_File::set_allocated_content(::std::string* content) {
   if (content != NULL) {
   if (content != NULL) {
@@ -832,21 +703,7 @@ inline void CodeGeneratorResponse_File::set_allocated_content(::std::string* con
   } else {
   } else {
     clear_has_content();
     clear_has_content();
   }
   }
-  content_.SetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), content,
-      GetArenaNoVirtual());
-  // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.content)
-}
-inline void CodeGeneratorResponse_File::unsafe_arena_set_allocated_content(
-    ::std::string* content) {
-  GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
-  if (content != NULL) {
-    set_has_content();
-  } else {
-    clear_has_content();
-  }
-  set_has_content();
-  content_.UnsafeArenaSetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
-      content, GetArenaNoVirtual());
+  content_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), content);
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.content)
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.content)
 }
 }
 
 
@@ -865,45 +722,37 @@ inline void CodeGeneratorResponse::clear_has_error() {
   _has_bits_[0] &= ~0x00000001u;
   _has_bits_[0] &= ~0x00000001u;
 }
 }
 inline void CodeGeneratorResponse::clear_error() {
 inline void CodeGeneratorResponse::clear_error() {
-  error_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+  error_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
   clear_has_error();
   clear_has_error();
 }
 }
 inline const ::std::string& CodeGeneratorResponse::error() const {
 inline const ::std::string& CodeGeneratorResponse::error() const {
   // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.error)
   // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.error)
-  return error_.Get(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  return error_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
 }
 }
 inline void CodeGeneratorResponse::set_error(const ::std::string& value) {
 inline void CodeGeneratorResponse::set_error(const ::std::string& value) {
   set_has_error();
   set_has_error();
-  error_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
+  error_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
   // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.error)
   // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.error)
 }
 }
 inline void CodeGeneratorResponse::set_error(const char* value) {
 inline void CodeGeneratorResponse::set_error(const char* value) {
   set_has_error();
   set_has_error();
-  error_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
-              GetArenaNoVirtual());
+  error_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
   // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.error)
   // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.error)
 }
 }
-inline void CodeGeneratorResponse::set_error(const char* value,
-    size_t size) {
+inline void CodeGeneratorResponse::set_error(const char* value, size_t size) {
   set_has_error();
   set_has_error();
-  error_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArenaNoVirtual());
+  error_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
   // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.error)
   // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.error)
 }
 }
 inline ::std::string* CodeGeneratorResponse::mutable_error() {
 inline ::std::string* CodeGeneratorResponse::mutable_error() {
   set_has_error();
   set_has_error();
   // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.error)
   // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.error)
-  return error_.Mutable(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+  return error_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
 }
 }
 inline ::std::string* CodeGeneratorResponse::release_error() {
 inline ::std::string* CodeGeneratorResponse::release_error() {
   clear_has_error();
   clear_has_error();
-  return error_.Release(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
-}
-inline ::std::string* CodeGeneratorResponse::unsafe_arena_release_error() {
-  GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
-  clear_has_error();
-  return error_.UnsafeArenaRelease(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
-      GetArenaNoVirtual());
+  return error_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
 }
 }
 inline void CodeGeneratorResponse::set_allocated_error(::std::string* error) {
 inline void CodeGeneratorResponse::set_allocated_error(::std::string* error) {
   if (error != NULL) {
   if (error != NULL) {
@@ -911,21 +760,7 @@ inline void CodeGeneratorResponse::set_allocated_error(::std::string* error) {
   } else {
   } else {
     clear_has_error();
     clear_has_error();
   }
   }
-  error_.SetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), error,
-      GetArenaNoVirtual());
-  // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.error)
-}
-inline void CodeGeneratorResponse::unsafe_arena_set_allocated_error(
-    ::std::string* error) {
-  GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
-  if (error != NULL) {
-    set_has_error();
-  } else {
-    clear_has_error();
-  }
-  set_has_error();
-  error_.UnsafeArenaSetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
-      error, GetArenaNoVirtual());
+  error_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), error);
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.error)
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.error)
 }
 }
 
 

+ 7 - 42
src/google/protobuf/compiler/python/python_generator.cc

@@ -73,41 +73,6 @@ namespace python {
 
 
 namespace {
 namespace {
 
 
-const char* const kKeywordList[] = {
-  "and", "as", "break", "class", "continue", "def", "elif", "else", "except",
-  "False", "for", "from", "if", "import", "not", "or", "raise", "return",
-  "True", "try", "with", "while", "yield"
-};
-
-hash_set<string> MakeKeywordsMap() {
-  hash_set<string> result;
-  for (int i = 0; i < GOOGLE_ARRAYSIZE(kKeywordList); ++i) {
-    result.insert(kKeywordList[i]);
-  }
-  return result;
-}
-
-hash_set<string>* keywords_ = NULL;
-GOOGLE_PROTOBUF_DECLARE_ONCE(keywords_once_);
-
-void InitKeywords() {
-  keywords_ = new hash_set<string>();
-  *keywords_ = MakeKeywordsMap();
-}
-
-hash_set<string>& GetKeywords() {
-  ::google::protobuf::GoogleOnceInit(&keywords_once_, &InitKeywords);
-  return *keywords_;
-}
-
-string FieldName(const FieldDescriptor& field) {
-  string result = field.name();
-  if (GetKeywords().count(result) > 0) {
-    result.append("_");
-  }
-  return result;
-}
-
 // Returns a copy of |filename| with any trailing ".protodevel" or ".proto
 // Returns a copy of |filename| with any trailing ".protodevel" or ".proto
 // suffix stripped.
 // suffix stripped.
 // TODO(robinson): Unify with copy in compiler/cpp/internal/helpers.cc.
 // TODO(robinson): Unify with copy in compiler/cpp/internal/helpers.cc.
@@ -343,7 +308,7 @@ bool Generator::Generate(const FileDescriptor* file,
   fdp.SerializeToString(&file_descriptor_serialized_);
   fdp.SerializeToString(&file_descriptor_serialized_);
 
 
 
 
-  scoped_ptr<io::ZeroCopyOutputStream> output(context->Open(filename));
+  google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(context->Open(filename));
   GOOGLE_CHECK(output.get());
   GOOGLE_CHECK(output.get());
   io::Printer printer(output.get(), '$');
   io::Printer printer(output.get(), '$');
   printer_ = &printer;
   printer_ = &printer;
@@ -531,7 +496,7 @@ void Generator::PrintTopLevelExtensions() const {
     printer_->Print("$constant_name$ = $number$\n",
     printer_->Print("$constant_name$ = $number$\n",
       "constant_name", constant_name,
       "constant_name", constant_name,
       "number", SimpleItoa(extension_field.number()));
       "number", SimpleItoa(extension_field.number()));
-    printer_->Print("$name$ = ", "name", FieldName(extension_field));
+    printer_->Print("$name$ = ", "name", extension_field.name());
     PrintFieldDescriptor(extension_field, is_extension);
     PrintFieldDescriptor(extension_field, is_extension);
     printer_->Print("\n");
     printer_->Print("\n");
   }
   }
@@ -878,7 +843,7 @@ void Generator::AddExtensionToFileDescriptor(
     const FieldDescriptor& descriptor) const {
     const FieldDescriptor& descriptor) const {
   map<string, string> m;
   map<string, string> m;
   m["descriptor_name"] = kDescriptorKey;
   m["descriptor_name"] = kDescriptorKey;
-  m["field_name"] = FieldName(descriptor);
+  m["field_name"] = descriptor.name();
   const char file_descriptor_template[] =
   const char file_descriptor_template[] =
       "$descriptor_name$.extensions_by_name['$field_name$'] = "
       "$descriptor_name$.extensions_by_name['$field_name$'] = "
       "$field_name$\n";
       "$field_name$\n";
@@ -931,12 +896,12 @@ string Generator::FieldReferencingExpression(
   GOOGLE_CHECK_EQ(field.file(), file_) << field.file()->name() << " vs. "
   GOOGLE_CHECK_EQ(field.file(), file_) << field.file()->name() << " vs. "
                                 << file_->name();
                                 << file_->name();
   if (!containing_type) {
   if (!containing_type) {
-    return FieldName(field);
+    return field.name();
   }
   }
   return strings::Substitute(
   return strings::Substitute(
       "$0.$1['$2']",
       "$0.$1['$2']",
       ModuleLevelDescriptorName(*containing_type),
       ModuleLevelDescriptorName(*containing_type),
-      python_dict_name, FieldName(field));
+      python_dict_name, field.name());
 }
 }
 
 
 // Prints containing_type for nested descriptors or enum descriptors.
 // Prints containing_type for nested descriptors or enum descriptors.
@@ -1065,7 +1030,7 @@ void Generator::PrintFieldDescriptor(
   string options_string;
   string options_string;
   field.options().SerializeToString(&options_string);
   field.options().SerializeToString(&options_string);
   map<string, string> m;
   map<string, string> m;
-  m["name"] = FieldName(field);
+  m["name"] = field.name();
   m["full_name"] = field.full_name();
   m["full_name"] = field.full_name();
   m["index"] = SimpleItoa(field.index());
   m["index"] = SimpleItoa(field.index());
   m["number"] = SimpleItoa(field.number());
   m["number"] = SimpleItoa(field.number());
@@ -1285,7 +1250,7 @@ void Generator::FixOptionsForField(
     if (field.is_extension()) {
     if (field.is_extension()) {
       if (field.extension_scope() == NULL) {
       if (field.extension_scope() == NULL) {
         // Top level extensions.
         // Top level extensions.
-        field_name = FieldName(field);
+        field_name = field.name();
       } else {
       } else {
         field_name = FieldReferencingExpression(
         field_name = FieldReferencingExpression(
             field.extension_scope(), field, "extensions_by_name");
             field.extension_scope(), field, "extensions_by_name");

+ 1 - 1
src/google/protobuf/compiler/python/python_plugin_unittest.cc

@@ -72,7 +72,7 @@ class TestGenerator : public CodeGenerator {
 
 
   void TryInsert(const string& filename, const string& insertion_point,
   void TryInsert(const string& filename, const string& insertion_point,
                  GeneratorContext* context) const {
                  GeneratorContext* context) const {
-    scoped_ptr<io::ZeroCopyOutputStream> output(
+    google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
         context->OpenForInsert(filename, insertion_point));
         context->OpenForInsert(filename, insertion_point));
     io::Printer printer(output.get(), '$');
     io::Printer printer(output.get(), '$');
     printer.Print("// inserted $name$\n", "name", insertion_point);
     printer.Print("// inserted $name$\n", "name", insertion_point);

+ 7 - 6
src/google/protobuf/descriptor.cc

@@ -1617,6 +1617,10 @@ bool DescriptorPool::TryFindExtensionInFallbackDatabase(
 
 
 // ===================================================================
 // ===================================================================
 
 
+bool FieldDescriptor::is_map() const {
+  return type() == TYPE_MESSAGE && message_type()->options().map_entry();
+}
+
 string FieldDescriptor::DefaultValueAsString(bool quote_string_type) const {
 string FieldDescriptor::DefaultValueAsString(bool quote_string_type) const {
   GOOGLE_CHECK(has_default_value()) << "No default value";
   GOOGLE_CHECK(has_default_value()) << "No default value";
   switch (cpp_type()) {
   switch (cpp_type()) {
@@ -2184,9 +2188,7 @@ void FieldDescriptor::DebugString(int depth,
   string field_type;
   string field_type;
 
 
   // Special case map fields.
   // Special case map fields.
-  bool is_map = false;
-  if (type() == TYPE_MESSAGE && message_type()->options().map_entry()) {
-    is_map = true;
+  if (is_map()) {
     strings::SubstituteAndAppend(
     strings::SubstituteAndAppend(
         &field_type, "map<$0, $1>",
         &field_type, "map<$0, $1>",
         message_type()->field(0)->FieldTypeNameDebugString(),
         message_type()->field(0)->FieldTypeNameDebugString(),
@@ -2196,7 +2198,7 @@ void FieldDescriptor::DebugString(int depth,
   }
   }
 
 
   string label;
   string label;
-  if (print_label_flag == PRINT_LABEL && !is_map) {
+  if (print_label_flag == PRINT_LABEL && !is_map()) {
     label = kLabelToName[this->label()];
     label = kLabelToName[this->label()];
     label.push_back(' ');
     label.push_back(' ');
   }
   }
@@ -4964,8 +4966,7 @@ void DescriptorBuilder::ValidateFieldOptions(FieldDescriptor* field,
   }
   }
 
 
   // Validate map types.
   // Validate map types.
-  if (field->type() == FieldDescriptor::TYPE_MESSAGE &&
-      field->message_type()->options().map_entry()) {
+  if (field->is_map()) {
     if (!ValidateMapEntry(field, proto)) {
     if (!ValidateMapEntry(field, proto)) {
       AddError(field->full_name(), proto,
       AddError(field->full_name(), proto,
                DescriptorPool::ErrorCollector::OTHER,
                DescriptorPool::ErrorCollector::OTHER,

+ 2 - 2
src/google/protobuf/descriptor.h

@@ -117,8 +117,6 @@ struct SourceLocation {
   int end_column;
   int end_column;
 
 
   // Doc comments found at the source location.
   // Doc comments found at the source location.
-  // TODO(kenton):  Maybe this struct should have been named SourceInfo or
-  //   something instead.  Oh well.
   string leading_comments;
   string leading_comments;
   string trailing_comments;
   string trailing_comments;
 };
 };
@@ -477,6 +475,8 @@ class LIBPROTOBUF_EXPORT FieldDescriptor {
                                  //               IsTypePackable(type())
                                  //               IsTypePackable(type())
   bool is_packed() const;        // shorthand for is_packable() &&
   bool is_packed() const;        // shorthand for is_packable() &&
                                  //               options().packed()
                                  //               options().packed()
+  bool is_map() const;           // shorthand for type() == TYPE_MESSAGE &&
+                                 // message_type()->options().map_entry()
 
 
   // Index of this field within the message's field array, or the file or
   // Index of this field within the message's field array, or the file or
   // extension scope's extensions array.
   // extension scope's extensions array.

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 148 - 261
src/google/protobuf/descriptor.pb.cc


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 10 - 329
src/google/protobuf/descriptor.pb.h


+ 5 - 0
src/google/protobuf/descriptor.proto

@@ -340,6 +340,11 @@ message FileOptions {
   optional bool deprecated = 23 [default=false];
   optional bool deprecated = 23 [default=false];
 
 
 
 
+  // Enables the use of arenas for the proto messages in this file. This applies
+  // only to generated classes for C++.
+  optional bool cc_enable_arenas = 31 [default=false];
+
+
   // The parser stores options it doesn't recognize here. See above.
   // The parser stores options it doesn't recognize here. See above.
   repeated UninterpretedOption uninterpreted_option = 999;
   repeated UninterpretedOption uninterpreted_option = 999;
 
 

+ 42 - 0
src/google/protobuf/descriptor_unittest.cc

@@ -415,6 +415,11 @@ class DescriptorTest : public testing::Test {
     //     required string quux = 6;
     //     required string quux = 6;
     //   }
     //   }
     //
     //
+    //   // in "map.proto"
+    //   message TestMessage3 {
+    //     map<int32, int32> map_int32_int32 = 1;
+    //   }
+    //
     // We cheat and use TestForeign as the type for qux rather than create
     // We cheat and use TestForeign as the type for qux rather than create
     // an actual nested type.
     // an actual nested type.
     //
     //
@@ -462,6 +467,24 @@ class DescriptorTest : public testing::Test {
              FieldDescriptorProto::LABEL_REQUIRED,
              FieldDescriptorProto::LABEL_REQUIRED,
              FieldDescriptorProto::TYPE_STRING);
              FieldDescriptorProto::TYPE_STRING);
 
 
+    FileDescriptorProto map_file;
+    map_file.set_name("map.proto");
+    DescriptorProto* message3 = AddMessage(&map_file, "TestMessage3");
+
+    DescriptorProto* entry = AddNestedMessage(message3, "MapInt32Int32Entry");
+    AddField(entry, "key", 1,
+             FieldDescriptorProto::LABEL_OPTIONAL,
+             FieldDescriptorProto::TYPE_INT32);
+    AddField(entry, "value", 2,
+             FieldDescriptorProto::LABEL_OPTIONAL,
+             FieldDescriptorProto::TYPE_INT32);
+    entry->mutable_options()->set_map_entry(true);
+
+    AddField(message3, "map_int32_int32", 1,
+             FieldDescriptorProto::LABEL_REPEATED,
+             FieldDescriptorProto::TYPE_MESSAGE)
+        ->set_type_name("MapInt32Int32Entry");
+
     // Build the descriptors and get the pointers.
     // Build the descriptors and get the pointers.
     foo_file_ = pool_.BuildFile(foo_file);
     foo_file_ = pool_.BuildFile(foo_file);
     ASSERT_TRUE(foo_file_ != NULL);
     ASSERT_TRUE(foo_file_ != NULL);
@@ -469,6 +492,9 @@ class DescriptorTest : public testing::Test {
     bar_file_ = pool_.BuildFile(bar_file);
     bar_file_ = pool_.BuildFile(bar_file);
     ASSERT_TRUE(bar_file_ != NULL);
     ASSERT_TRUE(bar_file_ != NULL);
 
 
+    map_file_ = pool_.BuildFile(map_file);
+    ASSERT_TRUE(map_file_ != NULL);
+
     ASSERT_EQ(1, foo_file_->enum_type_count());
     ASSERT_EQ(1, foo_file_->enum_type_count());
     enum_ = foo_file_->enum_type(0);
     enum_ = foo_file_->enum_type(0);
 
 
@@ -489,15 +515,23 @@ class DescriptorTest : public testing::Test {
     foo2_  = message2_->field(0);
     foo2_  = message2_->field(0);
     bar2_  = message2_->field(1);
     bar2_  = message2_->field(1);
     quux2_ = message2_->field(2);
     quux2_ = message2_->field(2);
+
+    ASSERT_EQ(1, map_file_->message_type_count());
+    message3_ = map_file_->message_type(0);
+
+    ASSERT_EQ(1, message3_->field_count());
+    map_  = message3_->field(0);
   }
   }
 
 
   DescriptorPool pool_;
   DescriptorPool pool_;
 
 
   const FileDescriptor* foo_file_;
   const FileDescriptor* foo_file_;
   const FileDescriptor* bar_file_;
   const FileDescriptor* bar_file_;
+  const FileDescriptor* map_file_;
 
 
   const Descriptor* message_;
   const Descriptor* message_;
   const Descriptor* message2_;
   const Descriptor* message2_;
+  const Descriptor* message3_;
   const Descriptor* foreign_;
   const Descriptor* foreign_;
   const EnumDescriptor* enum_;
   const EnumDescriptor* enum_;
 
 
@@ -509,6 +543,8 @@ class DescriptorTest : public testing::Test {
   const FieldDescriptor* foo2_;
   const FieldDescriptor* foo2_;
   const FieldDescriptor* bar2_;
   const FieldDescriptor* bar2_;
   const FieldDescriptor* quux2_;
   const FieldDescriptor* quux2_;
+
+  const FieldDescriptor* map_;
 };
 };
 
 
 TEST_F(DescriptorTest, Name) {
 TEST_F(DescriptorTest, Name) {
@@ -638,6 +674,12 @@ TEST_F(DescriptorTest, FieldLabel) {
   EXPECT_TRUE (baz_->is_repeated());
   EXPECT_TRUE (baz_->is_repeated());
 }
 }
 
 
+TEST_F(DescriptorTest, IsMap) {
+  EXPECT_TRUE(map_->is_map());
+  EXPECT_FALSE(baz_->is_map());
+  EXPECT_TRUE(map_->message_type()->options().map_entry());
+}
+
 TEST_F(DescriptorTest, FieldHasDefault) {
 TEST_F(DescriptorTest, FieldHasDefault) {
   EXPECT_FALSE(foo_->has_default_value());
   EXPECT_FALSE(foo_->has_default_value());
   EXPECT_FALSE(bar_->has_default_value());
   EXPECT_FALSE(bar_->has_default_value());

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

@@ -72,7 +72,7 @@ TEST(DropUnknownFieldsTest, DynamicMessage) {
   foo_with_extra_fields.set_extra_int32_value(2);
   foo_with_extra_fields.set_extra_int32_value(2);
 
 
   google::protobuf::DynamicMessageFactory factory;
   google::protobuf::DynamicMessageFactory factory;
-  scoped_ptr<google::protobuf::Message> foo(
+  google::protobuf::scoped_ptr<google::protobuf::Message> foo(
       factory.GetPrototype(Foo::descriptor())->New());
       factory.GetPrototype(Foo::descriptor())->New());
   ASSERT_TRUE(foo->ParseFromString(foo_with_extra_fields.SerializeAsString()));
   ASSERT_TRUE(foo->ParseFromString(foo_with_extra_fields.SerializeAsString()));
   EXPECT_TRUE(foo->GetReflection()->GetUnknownFields(*foo).empty());
   EXPECT_TRUE(foo->GetReflection()->GetUnknownFields(*foo).empty());

+ 25 - 4
src/google/protobuf/dynamic_message.cc

@@ -73,8 +73,10 @@
 #include <google/protobuf/generated_message_util.h>
 #include <google/protobuf/generated_message_util.h>
 #include <google/protobuf/generated_message_reflection.h>
 #include <google/protobuf/generated_message_reflection.h>
 #include <google/protobuf/arenastring.h>
 #include <google/protobuf/arenastring.h>
+#include <google/protobuf/map_field_inl.h>
 #include <google/protobuf/reflection_ops.h>
 #include <google/protobuf/reflection_ops.h>
 #include <google/protobuf/repeated_field.h>
 #include <google/protobuf/repeated_field.h>
+#include <google/protobuf/map_type_handler.h>
 #include <google/protobuf/extension_set.h>
 #include <google/protobuf/extension_set.h>
 #include <google/protobuf/wire_format.h>
 #include <google/protobuf/wire_format.h>
 
 
@@ -84,6 +86,8 @@ namespace protobuf {
 using internal::WireFormat;
 using internal::WireFormat;
 using internal::ExtensionSet;
 using internal::ExtensionSet;
 using internal::GeneratedMessageReflection;
 using internal::GeneratedMessageReflection;
+using internal::MapField;
+using internal::MapFieldBase;
 
 
 
 
 using internal::ArenaStringPtr;
 using internal::ArenaStringPtr;
@@ -93,6 +97,10 @@ using internal::ArenaStringPtr;
 
 
 namespace {
 namespace {
 
 
+bool IsMapFieldInApi(const FieldDescriptor* field) {
+  return field->is_map();
+}
+
 // Compute the byte size of the in-memory representation of the field.
 // Compute the byte size of the in-memory representation of the field.
 int FieldSpaceUsed(const FieldDescriptor* field) {
 int FieldSpaceUsed(const FieldDescriptor* field) {
   typedef FieldDescriptor FD;  // avoid line wrapping
   typedef FieldDescriptor FD;  // avoid line wrapping
@@ -106,7 +114,12 @@ int FieldSpaceUsed(const FieldDescriptor* field) {
       case FD::CPPTYPE_FLOAT  : return sizeof(RepeatedField<float   >);
       case FD::CPPTYPE_FLOAT  : return sizeof(RepeatedField<float   >);
       case FD::CPPTYPE_BOOL   : return sizeof(RepeatedField<bool    >);
       case FD::CPPTYPE_BOOL   : return sizeof(RepeatedField<bool    >);
       case FD::CPPTYPE_ENUM   : return sizeof(RepeatedField<int     >);
       case FD::CPPTYPE_ENUM   : return sizeof(RepeatedField<int     >);
-      case FD::CPPTYPE_MESSAGE: return sizeof(RepeatedPtrField<Message>);
+      case FD::CPPTYPE_MESSAGE:
+        if (IsMapFieldInApi(field)) {
+          return sizeof(MapFieldBase);
+        } else {
+          return sizeof(RepeatedPtrField<Message>);
+        }
 
 
       case FD::CPPTYPE_STRING:
       case FD::CPPTYPE_STRING:
         switch (field->options().ctype()) {
         switch (field->options().ctype()) {
@@ -369,7 +382,11 @@ void DynamicMessage::SharedCtor() {
         if (!field->is_repeated()) {
         if (!field->is_repeated()) {
           new(field_ptr) Message*(NULL);
           new(field_ptr) Message*(NULL);
         } else {
         } else {
-          new(field_ptr) RepeatedPtrField<Message>();
+          if (IsMapFieldInApi(field)) {
+            new (field_ptr) MapFieldBase();
+          } else {
+            new (field_ptr) RepeatedPtrField<Message>();
+          }
         }
         }
         break;
         break;
       }
       }
@@ -456,8 +473,12 @@ DynamicMessage::~DynamicMessage() {
           break;
           break;
 
 
         case FieldDescriptor::CPPTYPE_MESSAGE:
         case FieldDescriptor::CPPTYPE_MESSAGE:
-          reinterpret_cast<RepeatedPtrField<Message>*>(field_ptr)
-              ->~RepeatedPtrField<Message>();
+          if (IsMapFieldInApi(field)) {
+            reinterpret_cast<MapFieldBase*>(field_ptr)->~MapFieldBase();
+          } else {
+            reinterpret_cast<RepeatedPtrField<Message>*>(field_ptr)
+                ->~RepeatedPtrField<Message>();
+          }
           break;
           break;
       }
       }
 
 

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

@@ -126,7 +126,7 @@ class LIBPROTOBUF_EXPORT DynamicMessageFactory : public MessageFactory {
   // public header (for good reason), but dynamic_message.h is, and public
   // public header (for good reason), but dynamic_message.h is, and public
   // headers may only #include other public headers.
   // headers may only #include other public headers.
   struct PrototypeMap;
   struct PrototypeMap;
-  scoped_ptr<PrototypeMap> prototypes_;
+  google::protobuf::scoped_ptr<PrototypeMap> prototypes_;
   mutable Mutex prototypes_mutex_;
   mutable Mutex prototypes_mutex_;
 
 
   friend class DynamicMessage;
   friend class DynamicMessage;

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

@@ -375,7 +375,7 @@ TEST(ExtensionSetTest, ArenaSetAllocatedMessageAndRelease) {
 
 
 TEST(ExtensionSetTest, SwapExtensionBothFullWithArena) {
 TEST(ExtensionSetTest, SwapExtensionBothFullWithArena) {
   ::google::protobuf::Arena arena1;
   ::google::protobuf::Arena arena1;
-  scoped_ptr<google::protobuf::Arena> arena2(new ::google::protobuf::Arena());
+  google::protobuf::scoped_ptr<google::protobuf::Arena> arena2(new ::google::protobuf::Arena());
 
 
   unittest::TestAllExtensions* message1 =
   unittest::TestAllExtensions* message1 =
       Arena::CreateMessage<unittest::TestAllExtensions>(&arena1);
       Arena::CreateMessage<unittest::TestAllExtensions>(&arena1);

+ 152 - 33
src/google/protobuf/generated_message_reflection.cc

@@ -34,13 +34,16 @@
 
 
 #include <algorithm>
 #include <algorithm>
 #include <set>
 #include <set>
+
+#include <google/protobuf/stubs/common.h>
 #include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/generated_message_reflection.h>
 #include <google/protobuf/descriptor.h>
 #include <google/protobuf/descriptor.h>
-#include <google/protobuf/repeated_field.h>
 #include <google/protobuf/extension_set.h>
 #include <google/protobuf/extension_set.h>
+#include <google/protobuf/generated_message_reflection.h>
 #include <google/protobuf/generated_message_util.h>
 #include <google/protobuf/generated_message_util.h>
-#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/map_field.h>
+#include <google/protobuf/repeated_field.h>
+
 
 
 #define GOOGLE_PROTOBUF_HAS_ONEOF
 #define GOOGLE_PROTOBUF_HAS_ONEOF
 
 
@@ -48,6 +51,12 @@ namespace google {
 namespace protobuf {
 namespace protobuf {
 namespace internal {
 namespace internal {
 
 
+namespace {
+bool IsMapFieldInApi(const FieldDescriptor* field) {
+  return field->is_map();
+}
+}  // anonymous namespace
+
 int StringSpaceUsedExcludingSelf(const string& str) {
 int StringSpaceUsedExcludingSelf(const string& str) {
   const void* start = &str;
   const void* start = &str;
   const void* end = &str + 1;
   const void* end = &str + 1;
@@ -76,14 +85,7 @@ const string& NameOfEnum(const EnumDescriptor* descriptor, int value) {
 
 
 namespace {
 namespace {
 inline bool SupportsArenas(const Descriptor* descriptor) {
 inline bool SupportsArenas(const Descriptor* descriptor) {
-  // In open-source release we enable arena support by default but as we also
-  // down-integrate descriptor.pb.(h|cc) from our internal code base which
-  // hasn't enabled arena support yet, here we need to be able to handle both
-  // cases for descriptor protos.
-  if (!Arena::is_arena_constructable<FileDescriptorProto>::type::value) {
-    return descriptor->name() != "google/protobuf/descriptor.proto";
-  }
-  return true;
+  return descriptor->file()->options().cc_enable_arenas();
 }
 }
 }  // anonymous namespace
 }  // anonymous namespace
 
 
@@ -318,11 +320,17 @@ int GeneratedMessageReflection::SpaceUsed(const Message& message) const {
           break;
           break;
 
 
         case FieldDescriptor::CPPTYPE_MESSAGE:
         case FieldDescriptor::CPPTYPE_MESSAGE:
-          // We don't know which subclass of RepeatedPtrFieldBase the type is,
-          // so we use RepeatedPtrFieldBase directly.
-          total_size +=
-              GetRaw<RepeatedPtrFieldBase>(message, field)
-                .SpaceUsedExcludingSelf<GenericTypeHandler<Message> >();
+          if (IsMapFieldInApi(field)) {
+            total_size +=
+                GetRaw<MapFieldBase>(message, field).SpaceUsedExcludingSelf();
+          } else {
+            // We don't know which subclass of RepeatedPtrFieldBase the type is,
+            // so we use RepeatedPtrFieldBase directly.
+            total_size +=
+                GetRaw<RepeatedPtrFieldBase>(message, field)
+                  .SpaceUsedExcludingSelf<GenericTypeHandler<Message> >();
+          }
+
           break;
           break;
       }
       }
     } else {
     } else {
@@ -406,9 +414,17 @@ void GeneratedMessageReflection::SwapField(
 
 
       case FieldDescriptor::CPPTYPE_STRING:
       case FieldDescriptor::CPPTYPE_STRING:
       case FieldDescriptor::CPPTYPE_MESSAGE:
       case FieldDescriptor::CPPTYPE_MESSAGE:
-        MutableRaw<RepeatedPtrFieldBase>(message1, field)->
+        if (IsMapFieldInApi(field)) {
+          MutableRaw<MapFieldBase>(message1, field)->
+            MutableRepeatedField()->
+              Swap<GenericTypeHandler<google::protobuf::Message> >(
+                MutableRaw<MapFieldBase>(message2, field)->
+                  MutableRepeatedField());
+        } else {
+          MutableRaw<RepeatedPtrFieldBase>(message1, field)->
             Swap<GenericTypeHandler<google::protobuf::Message> >(
             Swap<GenericTypeHandler<google::protobuf::Message> >(
               MutableRaw<RepeatedPtrFieldBase>(message2, field));
               MutableRaw<RepeatedPtrFieldBase>(message2, field));
+        }
         break;
         break;
 
 
       default:
       default:
@@ -728,7 +744,11 @@ int GeneratedMessageReflection::FieldSize(const Message& message,
 
 
       case FieldDescriptor::CPPTYPE_STRING:
       case FieldDescriptor::CPPTYPE_STRING:
       case FieldDescriptor::CPPTYPE_MESSAGE:
       case FieldDescriptor::CPPTYPE_MESSAGE:
-        return GetRaw<RepeatedPtrFieldBase>(message, field).size();
+        if (IsMapFieldInApi(field)) {
+          return GetRaw<MapFieldBase>(message, field).GetRepeatedField().size();
+        } else {
+          return GetRaw<RepeatedPtrFieldBase>(message, field).size();
+        }
     }
     }
 
 
     GOOGLE_LOG(FATAL) << "Can't get here.";
     GOOGLE_LOG(FATAL) << "Can't get here.";
@@ -820,10 +840,16 @@ void GeneratedMessageReflection::ClearField(
       }
       }
 
 
       case FieldDescriptor::CPPTYPE_MESSAGE: {
       case FieldDescriptor::CPPTYPE_MESSAGE: {
-        // We don't know which subclass of RepeatedPtrFieldBase the type is,
-        // so we use RepeatedPtrFieldBase directly.
-        MutableRaw<RepeatedPtrFieldBase>(message, field)
-            ->Clear<GenericTypeHandler<Message> >();
+        if (IsMapFieldInApi(field)) {
+          MutableRaw<MapFieldBase>(message, field)
+              ->MutableRepeatedField()
+              ->Clear<GenericTypeHandler<Message> >();
+        } else {
+          // We don't know which subclass of RepeatedPtrFieldBase the type is,
+          // so we use RepeatedPtrFieldBase directly.
+          MutableRaw<RepeatedPtrFieldBase>(message, field)
+              ->Clear<GenericTypeHandler<Message> >();
+        }
         break;
         break;
       }
       }
     }
     }
@@ -865,8 +891,14 @@ void GeneratedMessageReflection::RemoveLast(
         break;
         break;
 
 
       case FieldDescriptor::CPPTYPE_MESSAGE:
       case FieldDescriptor::CPPTYPE_MESSAGE:
-        MutableRaw<RepeatedPtrFieldBase>(message, field)
+        if (IsMapFieldInApi(field)) {
+          MutableRaw<MapFieldBase>(message, field)
+              ->MutableRepeatedField()
+              ->RemoveLast<GenericTypeHandler<Message> >();
+        } else {
+          MutableRaw<RepeatedPtrFieldBase>(message, field)
             ->RemoveLast<GenericTypeHandler<Message> >();
             ->RemoveLast<GenericTypeHandler<Message> >();
+        }
         break;
         break;
     }
     }
   }
   }
@@ -881,8 +913,14 @@ Message* GeneratedMessageReflection::ReleaseLast(
     return static_cast<Message*>(
     return static_cast<Message*>(
         MutableExtensionSet(message)->ReleaseLast(field->number()));
         MutableExtensionSet(message)->ReleaseLast(field->number()));
   } else {
   } else {
-    return MutableRaw<RepeatedPtrFieldBase>(message, field)
+    if (IsMapFieldInApi(field)) {
+      return MutableRaw<MapFieldBase>(message, field)
+          ->MutableRepeatedField()
+          ->ReleaseLast<GenericTypeHandler<Message> >();
+    } else {
+      return MutableRaw<RepeatedPtrFieldBase>(message, field)
         ->ReleaseLast<GenericTypeHandler<Message> >();
         ->ReleaseLast<GenericTypeHandler<Message> >();
+    }
   }
   }
 }
 }
 
 
@@ -916,8 +954,14 @@ void GeneratedMessageReflection::SwapElements(
 
 
       case FieldDescriptor::CPPTYPE_STRING:
       case FieldDescriptor::CPPTYPE_STRING:
       case FieldDescriptor::CPPTYPE_MESSAGE:
       case FieldDescriptor::CPPTYPE_MESSAGE:
-        MutableRaw<RepeatedPtrFieldBase>(message, field)
+        if (IsMapFieldInApi(field)) {
+          MutableRaw<MapFieldBase>(message, field)
+              ->MutableRepeatedField()
+              ->SwapElements(index1, index2);
+        } else {
+          MutableRaw<RepeatedPtrFieldBase>(message, field)
             ->SwapElements(index1, index2);
             ->SwapElements(index1, index2);
+        }
         break;
         break;
     }
     }
   }
   }
@@ -1519,8 +1563,14 @@ const Message& GeneratedMessageReflection::GetRepeatedMessage(
     return static_cast<const Message&>(
     return static_cast<const Message&>(
         GetExtensionSet(message).GetRepeatedMessage(field->number(), index));
         GetExtensionSet(message).GetRepeatedMessage(field->number(), index));
   } else {
   } else {
-    return GetRaw<RepeatedPtrFieldBase>(message, field)
-        .Get<GenericTypeHandler<Message> >(index);
+    if (IsMapFieldInApi(field)) {
+      return GetRaw<MapFieldBase>(message, field)
+          .GetRepeatedField()
+          .Get<GenericTypeHandler<Message> >(index);
+    } else {
+      return GetRaw<RepeatedPtrFieldBase>(message, field)
+          .Get<GenericTypeHandler<Message> >(index);
+    }
   }
   }
 }
 }
 
 
@@ -1533,8 +1583,14 @@ Message* GeneratedMessageReflection::MutableRepeatedMessage(
         MutableExtensionSet(message)->MutableRepeatedMessage(
         MutableExtensionSet(message)->MutableRepeatedMessage(
           field->number(), index));
           field->number(), index));
   } else {
   } else {
-    return MutableRaw<RepeatedPtrFieldBase>(message, field)
+    if (IsMapFieldInApi(field)) {
+      return MutableRaw<MapFieldBase>(message, field)
+          ->MutableRepeatedField()
+          ->Mutable<GenericTypeHandler<Message> >(index);
+    } else {
+      return MutableRaw<RepeatedPtrFieldBase>(message, field)
         ->Mutable<GenericTypeHandler<Message> >(index);
         ->Mutable<GenericTypeHandler<Message> >(index);
+    }
   }
   }
 }
 }
 
 
@@ -1549,11 +1605,18 @@ Message* GeneratedMessageReflection::AddMessage(
     return static_cast<Message*>(
     return static_cast<Message*>(
         MutableExtensionSet(message)->AddMessage(field, factory));
         MutableExtensionSet(message)->AddMessage(field, factory));
   } else {
   } else {
+    Message* result = NULL;
+
     // We can't use AddField<Message>() because RepeatedPtrFieldBase doesn't
     // We can't use AddField<Message>() because RepeatedPtrFieldBase doesn't
     // know how to allocate one.
     // know how to allocate one.
-    RepeatedPtrFieldBase* repeated =
-        MutableRaw<RepeatedPtrFieldBase>(message, field);
-    Message* result = repeated->AddFromCleared<GenericTypeHandler<Message> >();
+    RepeatedPtrFieldBase* repeated = NULL;
+    if (IsMapFieldInApi(field)) {
+      repeated =
+          MutableRaw<MapFieldBase>(message, field)->MutableRepeatedField();
+    } else {
+      repeated = MutableRaw<RepeatedPtrFieldBase>(message, field);
+    }
+    result = repeated->AddFromCleared<GenericTypeHandler<Message> >();
     if (result == NULL) {
     if (result == NULL) {
       // We must allocate a new object.
       // We must allocate a new object.
       const Message* prototype;
       const Message* prototype;
@@ -1568,6 +1631,7 @@ Message* GeneratedMessageReflection::AddMessage(
       // of AddAllocated.
       // of AddAllocated.
       repeated->UnsafeArenaAddAllocated<GenericTypeHandler<Message> >(result);
       repeated->UnsafeArenaAddAllocated<GenericTypeHandler<Message> >(result);
     }
     }
+
     return result;
     return result;
   }
   }
 }
 }
@@ -1584,11 +1648,18 @@ void* GeneratedMessageReflection::MutableRawRepeatedField(
     GOOGLE_CHECK_EQ(field->options().ctype(), ctype) << "subtype mismatch";
     GOOGLE_CHECK_EQ(field->options().ctype(), ctype) << "subtype mismatch";
   if (desc != NULL)
   if (desc != NULL)
     GOOGLE_CHECK_EQ(field->message_type(), desc) << "wrong submessage type";
     GOOGLE_CHECK_EQ(field->message_type(), desc) << "wrong submessage type";
-  if (field->is_extension())
+  if (field->is_extension()) {
     return MutableExtensionSet(message)->MutableRawRepeatedField(
     return MutableExtensionSet(message)->MutableRawRepeatedField(
         field->number(), field->type(), field->is_packed(), field);
         field->number(), field->type(), field->is_packed(), field);
-  else
+  } else {
+    // Trigger transform for MapField
+    if (IsMapFieldInApi(field)) {
+      return reinterpret_cast<MapFieldBase*>(reinterpret_cast<uint8*>(message) +
+                                             offsets_[field->index()])
+          ->MutableRepeatedField();
+    }
     return reinterpret_cast<uint8*>(message) + offsets_[field->index()];
     return reinterpret_cast<uint8*>(message) + offsets_[field->index()];
+  }
 }
 }
 
 
 const FieldDescriptor* GeneratedMessageReflection::GetOneofFieldDescriptor(
 const FieldDescriptor* GeneratedMessageReflection::GetOneofFieldDescriptor(
@@ -2000,6 +2071,54 @@ void* GeneratedMessageReflection::RepeatedFieldData(
   }
   }
 }
 }
 
 
+GeneratedMessageReflection*
+GeneratedMessageReflection::NewGeneratedMessageReflection(
+    const Descriptor* descriptor,
+    const Message* default_instance,
+    const int offsets[],
+    int has_bits_offset,
+    int unknown_fields_offset,
+    int extensions_offset,
+    const void* default_oneof_instance,
+    int oneof_case_offset,
+    int object_size,
+    int arena_offset) {
+  return new GeneratedMessageReflection(descriptor,
+                                        default_instance,
+                                        offsets,
+                                        has_bits_offset,
+                                        unknown_fields_offset,
+                                        extensions_offset,
+                                        default_oneof_instance,
+                                        oneof_case_offset,
+                                        DescriptorPool::generated_pool(),
+                                        MessageFactory::generated_factory(),
+                                        object_size,
+                                        arena_offset);
+}
+
+GeneratedMessageReflection*
+GeneratedMessageReflection::NewGeneratedMessageReflection(
+    const Descriptor* descriptor,
+    const Message* default_instance,
+    const int offsets[],
+    int has_bits_offset,
+    int unknown_fields_offset,
+    int extensions_offset,
+    int object_size,
+    int arena_offset) {
+  return new GeneratedMessageReflection(descriptor,
+                                        default_instance,
+                                        offsets,
+                                        has_bits_offset,
+                                        unknown_fields_offset,
+                                        extensions_offset,
+                                        DescriptorPool::generated_pool(),
+                                        MessageFactory::generated_factory(),
+                                        object_size,
+                                        arena_offset);
+}
+
 }  // namespace internal
 }  // namespace internal
 }  // namespace protobuf
 }  // namespace protobuf
 }  // namespace google
 }  // namespace google

+ 26 - 0
src/google/protobuf/generated_message_reflection.h

@@ -176,6 +176,32 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection {
                              int arena_offset);
                              int arena_offset);
   ~GeneratedMessageReflection();
   ~GeneratedMessageReflection();
 
 
+  // Shorter-to-call helpers for the above two constructions that work if the
+  // pool and factory are the usual, namely, DescriptorPool::generated_pool()
+  // and MessageFactory::generated_factory().
+
+  static GeneratedMessageReflection* NewGeneratedMessageReflection(
+      const Descriptor* descriptor,
+      const Message* default_instance,
+      const int offsets[],
+      int has_bits_offset,
+      int unknown_fields_offset,
+      int extensions_offset,
+      const void* default_oneof_instance,
+      int oneof_case_offset,
+      int object_size,
+      int arena_offset);
+
+  static GeneratedMessageReflection* NewGeneratedMessageReflection(
+      const Descriptor* descriptor,
+      const Message* default_instance,
+      const int offsets[],
+      int has_bits_offset,
+      int unknown_fields_offset,
+      int extensions_offset,
+      int object_size,
+      int arena_offset);
+
   // implements Reflection -------------------------------------------
   // implements Reflection -------------------------------------------
 
 
   const UnknownFieldSet& GetUnknownFields(const Message& message) const;
   const UnknownFieldSet& GetUnknownFields(const Message& message) const;

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

@@ -36,6 +36,7 @@
 
 
 #include <limits>
 #include <limits>
 
 
+
 namespace google {
 namespace google {
 namespace protobuf {
 namespace protobuf {
 namespace internal {
 namespace internal {

+ 282 - 0
src/google/protobuf/map.h

@@ -0,0 +1,282 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_MAP_H__
+#define GOOGLE_PROTOBUF_MAP_H__
+
+#include <vector>
+
+#include <google/protobuf/map_type_handler.h>
+#include <google/protobuf/stubs/hash.h>
+
+namespace google {
+namespace protobuf {
+
+template <typename Key, typename T>
+class Map;
+
+template <typename Enum> struct is_proto_enum;
+
+namespace internal {
+template <typename K, typename V, FieldDescriptor::Type KeyProto,
+          FieldDescriptor::Type ValueProto, int default_enum_value>
+class MapField;
+}
+
+// This is the class for google::protobuf::Map's internal value_type. Instead of using
+// std::pair as value_type, we use this class which provides us more control of
+// its process of construction and destruction.
+template <typename Key, typename T>
+class MapPair {
+ public:
+  typedef Key first_type;
+  typedef T second_type;
+
+  MapPair(const Key& other_first, const T& other_second)
+      : first(other_first), second(other_second) {}
+
+  MapPair(const Key& other_first) : first(other_first), second() {}
+
+  MapPair(const MapPair& other)
+      : first(other.first), second(other.second) {}
+
+  MapPair& operator=(const MapPair& other) {
+    first = other.first;
+    second = other.second;
+    return *this;
+  }
+
+  ~MapPair() {}
+
+  const Key first;
+  T second;
+
+ private:
+  friend class Map<Key, T>;
+};
+
+// STL-like iterator implementation for google::protobuf::Map. Users should not refer to
+// this class directly; use google::protobuf::Map<Key, T>::iterator instead.
+template <typename Key, typename T>
+class MapIterator {
+ public:
+  typedef MapPair<Key, T> value_type;
+  typedef value_type* pointer;
+  typedef value_type& reference;
+  typedef MapIterator iterator;
+
+  // constructor
+  MapIterator(const typename hash_map<Key, value_type*>::iterator& it)
+      : it_(it) {}
+  MapIterator(const MapIterator& other) : it_(other.it_) {}
+  MapIterator& operator=(const MapIterator& other) {
+    it_ = other.it_;
+    return *this;
+  }
+
+  // deferenceable
+  reference operator*() const { return *it_->second; }
+  pointer operator->() const { return it_->second; }
+
+  // incrementable
+  iterator& operator++() {
+    ++it_;
+    return *this;
+  }
+  iterator operator++(int) { return iterator(it_++); }
+
+  // equality_comparable
+  bool operator==(const iterator& x) const { return it_ == x.it_; }
+  bool operator!=(const iterator& x) const { return it_ != x.it_; }
+
+ private:
+  typename hash_map<Key, value_type*>::iterator it_;
+
+  friend Map<Key, T>;
+};
+
+// google::protobuf::Map is an associative container type used to store protobuf map
+// fields. Its interface is similar to std::unordered_map. Users should use this
+// interface directly to visit or change map fields.
+template <typename Key, typename T>
+class Map {
+  typedef internal::MapCppTypeHandler<T> ValueTypeHandler;
+ public:
+  typedef Key key_type;
+  typedef T mapped_type;
+  typedef MapPair<Key, T> value_type;
+
+  typedef value_type* pointer;
+  typedef const value_type* const_pointer;
+  typedef value_type& reference;
+  typedef const value_type& const_reference;
+
+  typedef MapIterator<Key, T> iterator;
+  typedef MapIterator<Key, T> const_iterator;
+
+  typedef size_t size_type;
+  typedef hash<Key> hasher;
+
+  Map() : default_enum_value_(0) {}
+
+  Map(const Map& other) {
+    insert(other.begin(), other.end());
+  }
+
+  ~Map() { clear(); }
+
+  // Iterators
+  iterator begin() { return iterator(elements_.begin()); }
+  iterator end() { return iterator(elements_.end()); }
+  const_iterator begin() const {
+    return const_iterator(
+        const_cast<hash_map<Key, value_type*>&>(elements_).begin());
+  }
+  const_iterator end() const {
+    return const_iterator(
+        const_cast<hash_map<Key, value_type*>&>(elements_).end());
+  }
+  const_iterator cbegin() const { return begin(); }
+  const_iterator cend() const { return end(); }
+
+  // Capacity
+  size_type size() const { return elements_.size(); }
+  bool empty() const { return elements_.empty(); }
+
+  // Element access
+  T& operator[](const key_type& key) {
+    value_type** value = &elements_[key];
+    if (*value == NULL) {
+      *value = new value_type(key);
+      internal::MapValueInitializer<google::protobuf::is_proto_enum<T>::value,
+                                    T>::Initialize((*value)->second,
+                                                   default_enum_value_);
+    }
+    return (*value)->second;
+  }
+  const T& at(const key_type& key) const {
+    const_iterator it = find(key);
+    GOOGLE_CHECK(it != end());
+    return it->second;
+  }
+  T& at(const key_type& key) {
+    iterator it = find(key);
+    GOOGLE_CHECK(it != end());
+    return it->second;
+  }
+
+  // Lookup
+  size_type count(const key_type& key) const {
+    return elements_.count(key);
+  }
+  const_iterator find(const key_type& key) const {
+    // When elements_ is a const instance, find(key) returns a const iterator.
+    // However, to reduce code complexity, we use MapIterator for Map's both
+    // const and non-const iterator, which only takes non-const iterator to
+    // construct.
+    return const_iterator(
+        const_cast<hash_map<Key, value_type*>&>(elements_).find(key));
+  }
+  iterator find(const key_type& key) {
+    return iterator(elements_.find(key));
+  }
+
+  // insert
+  std::pair<iterator, bool> insert(const value_type& value) {
+    iterator it = find(value.first);
+    if (it != end()) {
+      return std::pair<iterator, bool>(it, false);
+    } else {
+      return elements_.insert(
+          std::pair<Key, value_type*>(value.first, new value_type(value)));
+    }
+  }
+  template <class InputIt>
+  void insert(InputIt first, InputIt last) {
+    for (InputIt it = first; it != last; ++it) {
+      iterator exist_it = find(it->first);
+      if (exist_it == end()) {
+        operator[](it->first) = it->second;
+      }
+    }
+  }
+
+  // Erase
+  size_type erase(const key_type& key) {
+    typename hash_map<Key, value_type*>::iterator it = elements_.find(key);
+    if (it == elements_.end()) {
+      return 0;
+    } else {
+      delete it->second;
+      elements_.erase(it);
+      return 1;
+    }
+  }
+  void erase(iterator pos) {
+    delete pos.it_->second;
+    elements_.erase(pos.it_);
+  }
+  void erase(iterator first, iterator last) {
+    for (iterator it = first; it != last;) {
+      delete it.it_->second;
+      elements_.erase((it++).it_);
+    }
+  }
+  void clear() {
+    for (iterator it = begin(); it != end(); ++it) {
+      delete it.it_->second;
+    }
+    elements_.clear();
+  }
+
+  // Assign
+  Map& operator=(const Map& other) {
+    insert(other.begin(), other.end());
+    return *this;
+  }
+
+ private:
+  // Set default enum value only for proto2 map field whose value is enum type.
+  void SetDefaultEnumValue(int default_enum_value) {
+    default_enum_value_ = default_enum_value;
+  }
+
+  hash_map<Key, value_type*> elements_;
+  int default_enum_value_;
+
+  template <typename K, typename V, FieldDescriptor::Type KeyProto,
+            FieldDescriptor::Type ValueProto, int default_enum>
+  friend class LIBPROTOBUF_EXPORT internal::MapField;
+};
+
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_MAP_H__

+ 449 - 0
src/google/protobuf/map_entry.h

@@ -0,0 +1,449 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_MAP_ENTRY_H__
+#define GOOGLE_PROTOBUF_MAP_ENTRY_H__
+
+#include <google/protobuf/reflection_ops.h>
+#include <google/protobuf/map_type_handler.h>
+#include <google/protobuf/wire_format_lite_inl.h>
+
+namespace google {
+namespace protobuf {
+class Arena;
+}
+
+namespace protobuf {
+namespace internal {
+
+// This is the common base class for MapEntry. It is used by MapFieldBase in
+// reflection api, in which the static type of key and value is unknown.
+class LIBPROTOBUF_EXPORT MapEntryBase : public Message {
+ public:
+  ::google::protobuf::Metadata GetMetadata() const {
+    ::google::protobuf::Metadata metadata;
+    metadata.descriptor = descriptor_;
+    metadata.reflection = reflection_;
+    return metadata;
+  }
+
+ protected:
+  MapEntryBase() : descriptor_(NULL), reflection_(NULL) {  }
+  virtual ~MapEntryBase() {}
+
+  const Descriptor* descriptor_;
+  const Reflection* reflection_;
+};
+
+// MapEntry is the returned google::protobuf::Message when calling AddMessage of
+// google::protobuf::Reflection. In order to let it work with generated message
+// reflection, its internal layout is the same as generated message with the
+// same fields. However, in order to decide the internal layout of key/value, we
+// need to know both their cpp type in generated api and proto type.
+//
+// cpp type | proto type  | internal layout
+// int32      TYPE_INT32    int32
+// int32      TYPE_FIXED32  int32
+// FooEnum    TYPE_ENUM     int
+// FooMessage TYPE_MESSAGE  FooMessage*
+//
+// The internal layouts of primitive types can be inferred from its proto type,
+// while we need to explicitly tell cpp type if proto type is TYPE_MESSAGE to
+// get internal layout.
+// Moreover, default_enum_value is used to initialize enum field in proto2.
+template <typename Key, typename Value, FieldDescriptor::Type KeyProtoType,
+          FieldDescriptor::Type ValueProtoType, int default_enum_value>
+class LIBPROTOBUF_EXPORT MapEntry : public MapEntryBase {
+  // Handlers for key/value's proto field type. Used to infer internal layout
+  // and provide parsing/serialization support.
+  typedef MapProtoTypeHandler<KeyProtoType> KeyProtoHandler;
+  typedef MapProtoTypeHandler<ValueProtoType> ValueProtoHandler;
+
+  // Define key/value's internal stored type. Message is the only one whose
+  // internal stored type cannot be inferred from its proto type.
+  typedef typename KeyProtoHandler::CppType KeyProtoHandlerCppType;
+  typedef typename ValueProtoHandler::CppType ValueProtoHandlerCppType;
+  static const bool kIsKeyMessage = KeyProtoHandler::kIsMessage;
+  static const bool kIsValueMessage = ValueProtoHandler::kIsMessage;
+  typedef typename MapIf<kIsKeyMessage, Key, KeyProtoHandlerCppType>::type
+      KeyCppType;
+  typedef typename MapIf<kIsValueMessage, Value, ValueProtoHandlerCppType>::type
+      ValCppType;
+
+  // Handlers for key/value's internal stored type. Provide utilities to
+  // manipulate internal stored type. We need it because some types are stored
+  // as values and others are stored as pointers (Message and string), but we
+  // need to keep the code in MapEntry unified instead of providing different
+  // codes for each type.
+  typedef MapCppTypeHandler<KeyCppType> KeyCppHandler;
+  typedef MapCppTypeHandler<ValCppType> ValueCppHandler;
+
+  // Define internal memory layout. Strings and messages are stored as
+  // pointers, while other types are stored as values.
+  static const bool kKeyIsStringOrMessage = KeyCppHandler::kIsStringOrMessage;
+  static const bool kValIsStringOrMessage = ValueCppHandler::kIsStringOrMessage;
+  typedef typename MapIf<kKeyIsStringOrMessage, KeyCppType*, KeyCppType>::type
+      KeyBase;
+  typedef typename MapIf<kValIsStringOrMessage, ValCppType*, ValCppType>::type
+      ValueBase;
+
+  // Abbreviation for MapEntry
+  typedef typename google::protobuf::internal::MapEntry<
+      Key, Value, KeyProtoType, ValueProtoType, default_enum_value> EntryType;
+
+  // Constants for field number.
+  static const int kKeyFieldNumber = 1;
+  static const int kValueFieldNumber = 2;
+
+  // Constants for field tag.
+  static const uint8 kKeyTag   = GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(
+      kKeyFieldNumber,   KeyProtoHandler::kWireType);
+  static const uint8 kValueTag = GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(
+      kValueFieldNumber, ValueProtoHandler::kWireType);
+  static const int kTagSize = 1;
+
+ public:
+  ~MapEntry() {
+    if (this == default_instance_) {
+      delete reflection_;
+    } else {
+      KeyCppHandler::Delete(key_);
+      ValueCppHandler::Delete(value_);
+    }
+  }
+
+  // accessors ======================================================
+
+  inline void set_key(const KeyCppType& key) {
+    KeyCppHandler::EnsureMutable(&key_);
+    KeyCppHandler::Merge(key, &key_);
+    set_has_key();
+  }
+  virtual inline const KeyCppType& key() const {
+    return KeyCppHandler::Reference(key_);
+  }
+  inline KeyCppType* mutable_key() {
+    set_has_key();
+    KeyCppHandler::EnsureMutable(&key_);
+    return KeyCppHandler::Pointer(key_);
+  }
+  inline void set_value(const ValCppType& value) {
+    ValueCppHandler::EnsureMutable(&value_);
+    ValueCppHandler::Merge(value, &value_);
+    set_has_value();
+  }
+  virtual inline const ValCppType& value() const {
+    GOOGLE_CHECK(default_instance_ != NULL);
+    return ValueCppHandler::DefaultIfNotInitialized(value_,
+                                               default_instance_->value_);
+  }
+  inline ValCppType* mutable_value() {
+    set_has_value();
+    ValueCppHandler::EnsureMutable(&value_);
+    return ValueCppHandler::Pointer(value_);
+  }
+
+  // implements Message =============================================
+
+  bool MergePartialFromCodedStream(::google::protobuf::io::CodedInputStream* input) {
+    uint32 tag;
+
+    for (;;) {
+      // 1) corrupted data: return false;
+      // 2) unknown field: skip without putting into unknown field set;
+      // 3) unknown enum value: keep it in parsing. In proto2, caller should
+      // check the value and put this entry into containing message's unknown
+      // field set if the value is an unknown enum. In proto3, caller doesn't
+      // need to care whether the value is unknown enum;
+      // 4) missing key/value: missed key/value will have default value. caller
+      // should take this entry as if key/value is set to default value.
+      tag = input->ReadTag();
+      switch (tag) {
+        case kKeyTag:
+          if (!KeyProtoHandler::Read(input, mutable_key())) return false;
+          set_has_key();
+          if (!input->ExpectTag(kValueTag)) break;
+          GOOGLE_FALLTHROUGH_INTENDED;
+
+        case kValueTag:
+          if (!ValueProtoHandler::Read(input, mutable_value())) return false;
+          set_has_value();
+          if (input->ExpectAtEnd()) return true;
+          break;
+
+        default:
+          if (tag == 0 ||
+              WireFormatLite::GetTagWireType(tag) ==
+              WireFormatLite::WIRETYPE_END_GROUP) {
+            return true;
+          }
+          if (!WireFormatLite::SkipField(input, tag)) return false;
+          break;
+      }
+    }
+  }
+
+  int ByteSize() const {
+    int size = 0;
+    size += has_key() ? kTagSize + KeyProtoHandler::ByteSize(key()) : 0;
+    size += has_value() ? kTagSize + ValueProtoHandler::ByteSize(value()) : 0;
+    return size;
+  }
+
+  void SerializeWithCachedSizes(::google::protobuf::io::CodedOutputStream* output) const {
+    KeyProtoHandler::Write(kKeyFieldNumber, key(), output);
+    ValueProtoHandler::Write(kValueFieldNumber, value(), output);
+  }
+
+  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const {
+    output = KeyProtoHandler::WriteToArray(kKeyFieldNumber, key(), output);
+    output =
+        ValueProtoHandler::WriteToArray(kValueFieldNumber, value(), output);
+    return output;
+  }
+
+  int GetCachedSize() const {
+    int size = 0;
+    size += has_key() ? kTagSize + KeyProtoHandler::GetCachedSize(key()) : 0;
+    size +=
+        has_value() ? kTagSize + ValueProtoHandler::GetCachedSize(value()) : 0;
+    return size;
+  }
+
+  bool IsInitialized() const { return ValueCppHandler::IsInitialized(value_); }
+
+  Message* New() const {
+    MapEntry* entry = new MapEntry;
+    entry->descriptor_ = descriptor_;
+    entry->reflection_ = reflection_;
+    entry->default_instance_ = default_instance_;
+    return entry;
+  }
+
+  int SpaceUsed() const {
+    int size = sizeof(MapEntry);
+    size += KeyCppHandler::SpaceUsedInMapEntry(key_);
+    size += ValueCppHandler::SpaceUsedInMapEntry(value_);
+    return size;
+  }
+
+  void CopyFrom(const ::google::protobuf::Message& from) {
+    Clear();
+    MergeFrom(from);
+  }
+
+  void MergeFrom(const ::google::protobuf::Message& from) {
+    GOOGLE_CHECK_NE(&from, this);
+    const MapEntry* source = dynamic_cast_if_available<const MapEntry*>(&from);
+    if (source == NULL) {
+      ReflectionOps::Merge(from, this);
+    } else {
+      MergeFrom(*source);
+    }
+  }
+
+  void CopyFrom(const MapEntry& from) {
+    Clear();
+    MergeFrom(from);
+  }
+
+  void MergeFrom(const MapEntry& from) {
+    if (from._has_bits_[0]) {
+      if (from.has_key()) {
+        KeyCppHandler::EnsureMutable(&key_);
+        KeyCppHandler::Merge(from.key(), &key_);
+        set_has_key();
+      }
+      if (from.has_value()) {
+        ValueCppHandler::EnsureMutable(&value_);
+        ValueCppHandler::Merge(from.value(), &value_);
+        set_has_value();
+      }
+    }
+  }
+
+  void Clear() {
+    KeyCppHandler::Clear(&key_);
+    ValueCppHandler::ClearMaybeByDefaultEnum(&value_, default_enum_value);
+    clear_has_key();
+    clear_has_value();
+  }
+
+  void InitAsDefaultInstance() {
+    KeyCppHandler::AssignDefaultValue(&key_);
+    ValueCppHandler::AssignDefaultValue(&value_);
+  }
+
+  // Create default MapEntry instance for given descriptor. Descriptor has to be
+  // given when creating default MapEntry instance because different map field
+  // may have the same type and MapEntry class. The given descriptor is needed
+  // to distinguish instances of the same MapEntry class.
+  static MapEntry* CreateDefaultInstance(const Descriptor* descriptor) {
+    MapEntry* entry = new MapEntry();
+    const Reflection* reflection = new GeneratedMessageReflection(
+        descriptor, entry, offsets_,
+        GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, _has_bits_),
+        GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, _unknown_fields_), -1,
+        DescriptorPool::generated_pool(),
+        ::google::protobuf::MessageFactory::generated_factory(), sizeof(MapEntry), -1);
+    entry->descriptor_ = descriptor;
+    entry->reflection_ = reflection;
+    entry->default_instance_ = entry;
+    entry->InitAsDefaultInstance();
+    return entry;
+  }
+
+  // Create a MapEntry for given key and value from google::protobuf::Map in
+  // serialization. This function is only called when value is enum. Enum is
+  // treated differently because its type in MapEntry is int and its type in
+  // google::protobuf::Map is enum. We cannot create a reference to int from an enum.
+  static MapEntry* EnumWrap(const Key& key, const Value value) {
+    return new MapEnumEntryWrapper<Key, Value, KeyProtoType, ValueProtoType,
+                                   default_enum_value>(key, value);
+  }
+
+  // Like above, but for all the other types. This avoids value copy to create
+  // MapEntry from google::protobuf::Map in serialization.
+  static MapEntry* Wrap(const Key& key, const Value& value) {
+    return new MapEntryWrapper<Key, Value, KeyProtoType, ValueProtoType,
+                               default_enum_value>(key, value);
+  }
+
+ protected:
+  void set_has_key() { _has_bits_[0] |= 0x00000001u; }
+  bool has_key() const { return (_has_bits_[0] & 0x00000001u) != 0; }
+  void clear_has_key() { _has_bits_[0] &= ~0x00000001u; }
+  void set_has_value() { _has_bits_[0] |= 0x00000002u; }
+  bool has_value() const { return (_has_bits_[0] & 0x00000002u) != 0; }
+  void clear_has_value() { _has_bits_[0] &= ~0x00000002u; }
+
+ private:
+  // Serializing a generated message containing map field involves serializing
+  // key-value pairs from google::protobuf::Map. The wire format of each key-value pair
+  // after serialization should be the same as that of a MapEntry message
+  // containing the same key and value inside it.  However, google::protobuf::Map doesn't
+  // store key and value as MapEntry message, which disables us to use existing
+  // code to serialize message. In order to use existing code to serialize
+  // message, we need to construct a MapEntry from key-value pair. But it
+  // involves copy of key and value to construct a MapEntry. In order to avoid
+  // this copy in constructing a MapEntry, we need the following class which
+  // only takes references of given key and value.
+  template <typename KeyNested, typename ValueNested,
+            FieldDescriptor::Type KeyProtoNested,
+            FieldDescriptor::Type ValueProtoNested, int default_enum>
+  class LIBPROTOBUF_EXPORT MapEntryWrapper
+      : public MapEntry<KeyNested, ValueNested, KeyProtoNested,
+                        ValueProtoNested, default_enum> {
+    typedef MapEntry<KeyNested, ValueNested, KeyProtoNested, ValueProtoNested,
+                     default_enum_value> Base;
+    typedef typename Base::KeyCppType KeyCppType;
+    typedef typename Base::ValCppType ValCppType;
+
+   public:
+    MapEntryWrapper(const KeyNested& key, const ValueNested& value)
+        : key_(key), value_(value) {
+      Base::set_has_key();
+      Base::set_has_value();
+    }
+    inline const KeyCppType& key() const { return key_; }
+    inline const ValCppType& value() const { return value_; }
+
+   private:
+    const Key& key_;
+    const Value& value_;
+  };
+
+  // Like above, but for enum value only, which stores value instead of
+  // reference of value field inside. This is needed because the type of value
+  // field in constructor is an enum, while we need to store it as an int. If we
+  // initialize a reference to int with a reference to enum, compiler will
+  // generate a temporary int from enum and initialize the reference to int with
+  // the temporary.
+  template <typename KeyNested, typename ValueNested,
+            FieldDescriptor::Type KeyProtoNested,
+            FieldDescriptor::Type ValueProtoNested, int default_enum>
+  class LIBPROTOBUF_EXPORT MapEnumEntryWrapper
+      : public MapEntry<KeyNested, ValueNested, KeyProtoNested,
+                        ValueProtoNested, default_enum> {
+    typedef MapEntry<KeyNested, ValueNested, KeyProtoNested, ValueProtoNested,
+                     default_enum> Base;
+    typedef typename Base::KeyCppType KeyCppType;
+    typedef typename Base::ValCppType ValCppType;
+
+   public:
+    MapEnumEntryWrapper(const KeyNested& key, const ValueNested& value)
+        : key_(key), value_(value) {
+      Base::set_has_key();
+      Base::set_has_value();
+    }
+    inline const KeyCppType& key() const { return key_; }
+    inline const ValCppType& value() const { return value_; }
+
+   private:
+    const KeyCppType& key_;
+    const ValCppType value_;
+  };
+
+  MapEntry() : default_instance_(NULL) {
+    KeyCppHandler::Initialize(&key_);
+    ValueCppHandler::InitializeMaybeByDefaultEnum(&value_, default_enum_value);
+    _has_bits_[0] = 0;
+  }
+
+  KeyBase key_;
+  ValueBase value_;
+  static int offsets_[2];
+  UnknownFieldSet _unknown_fields_;
+  uint32 _has_bits_[1];
+  MapEntry* default_instance_;
+
+  friend class ::google::protobuf::Arena;
+  template <typename K, typename V,
+            FieldDescriptor::Type KType,
+            FieldDescriptor::Type VType, int default_enum>
+  friend class LIBPROTOBUF_EXPORT internal::MapField;
+  friend class LIBPROTOBUF_EXPORT internal::GeneratedMessageReflection;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapEntry);
+};
+
+template <typename Key, typename Value, FieldDescriptor::Type KeyProtoType,
+          FieldDescriptor::Type ValueProtoType, int default_enum_value>
+int MapEntry<Key, Value, KeyProtoType, ValueProtoType,
+             default_enum_value>::offsets_[2] = {
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, key_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, value_),
+};
+
+}  // namespace internal
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_MAP_ENTRY_H__

+ 113 - 0
src/google/protobuf/map_field.cc

@@ -0,0 +1,113 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <google/protobuf/map_field.h>
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+MapFieldBase::~MapFieldBase() {
+  if (repeated_field_ != NULL) delete repeated_field_;
+}
+
+const RepeatedPtrFieldBase& MapFieldBase::GetRepeatedField() const {
+  SyncRepeatedFieldWithMap();
+  return *repeated_field_;
+}
+
+RepeatedPtrFieldBase* MapFieldBase::MutableRepeatedField() {
+  SyncRepeatedFieldWithMap();
+  SetRepeatedDirty();
+  return repeated_field_;
+}
+
+int MapFieldBase::SpaceUsedExcludingSelf() const {
+  mutex_.Lock();
+  int size = SpaceUsedExcludingSelfNoLock();
+  mutex_.Unlock();
+  return size;
+}
+
+int MapFieldBase::SpaceUsedExcludingSelfNoLock() const {
+  if (repeated_field_ != NULL) {
+    return repeated_field_->SpaceUsedExcludingSelf();
+  } else {
+    return 0;
+  }
+}
+
+void MapFieldBase::InitMetadataOnce() const {
+  GOOGLE_CHECK(entry_descriptor_ != NULL);
+  GOOGLE_CHECK(assign_descriptor_callback_ != NULL);
+  (*assign_descriptor_callback_)();
+}
+
+void MapFieldBase::SetMapDirty() { state_ = STATE_MODIFIED_MAP; }
+
+void MapFieldBase::SetRepeatedDirty() { state_ = STATE_MODIFIED_REPEATED; }
+
+void* MapFieldBase::MutableRepeatedPtrField() const { return repeated_field_; }
+
+void MapFieldBase::SyncRepeatedFieldWithMap() const {
+  Atomic32 state = google::protobuf::internal::NoBarrier_Load(&state_);
+  if (state == STATE_MODIFIED_MAP) {
+    mutex_.Lock();
+    // Double check state, because another thread may have seen the same state
+    // and done the synchronization before the current thread.
+    if (state_ == STATE_MODIFIED_MAP) {
+      SyncRepeatedFieldWithMapNoLock();
+      google::protobuf::internal::NoBarrier_Store(&state_, CLEAN);
+    }
+    mutex_.Unlock();
+  }
+}
+
+void MapFieldBase::SyncRepeatedFieldWithMapNoLock() const {
+  if (repeated_field_ == NULL) repeated_field_ = new RepeatedPtrField<Message>;
+}
+
+void MapFieldBase::SyncMapWithRepeatedField() const {
+  Atomic32 state = google::protobuf::internal::NoBarrier_Load(&state_);
+  if (state == STATE_MODIFIED_REPEATED) {
+    mutex_.Lock();
+    // Double check state, because another thread may have seen the same state
+    // and done the synchronization before the current thread.
+    if (state_ == STATE_MODIFIED_REPEATED) {
+      SyncMapWithRepeatedFieldNoLock();
+      google::protobuf::internal::NoBarrier_Store(&state_, CLEAN);
+    }
+    mutex_.Unlock();
+  }
+}
+
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google

+ 220 - 0
src/google/protobuf/map_field.h

@@ -0,0 +1,220 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_MAP_FIELD_H__
+#define GOOGLE_PROTOBUF_MAP_FIELD_H__
+
+#include <google/protobuf/stubs/atomicops.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/generated_message_reflection.h>
+#include <google/protobuf/map.h>
+#include <google/protobuf/map_entry.h>
+#include <google/protobuf/message.h>
+#include <google/protobuf/repeated_field.h>
+#include <google/protobuf/unknown_field_set.h>
+
+
+namespace google {
+namespace protobuf {
+
+namespace internal {
+
+class ContendedMapCleanTest;
+class GeneratedMessageReflection;
+class MapFieldAccessor;
+
+// This class provides accesss to map field using reflection, which is the same
+// as those provided for RepeatedPtrField<Message>. It is used for internal
+// reflection implentation only. Users should never use this directly.
+class LIBPROTOBUF_EXPORT MapFieldBase {
+ public:
+  MapFieldBase()
+      : base_map_(NULL),
+        repeated_field_(NULL),
+        entry_descriptor_(NULL),
+        assign_descriptor_callback_(NULL),
+        state_(STATE_MODIFIED_MAP) {}
+  virtual ~MapFieldBase();
+
+  // Returns reference to internal repeated field. Data written using
+  // google::protobuf::Map's api prior to calling this function is guarantted to be
+  // included in repeated field.
+  const RepeatedPtrFieldBase& GetRepeatedField() const;
+
+  // Like above. Returns mutable pointer to the internal repeated field.
+  RepeatedPtrFieldBase* MutableRepeatedField();
+
+  // Returns the number of bytes used by the repeated field, excluding
+  // sizeof(*this)
+  int SpaceUsedExcludingSelf() const;
+
+ protected:
+  // Gets the size of space used by map field.
+  virtual int SpaceUsedExcludingSelfNoLock() const;
+
+  // Synchronizes the content in Map to RepeatedPtrField if there is any change
+  // to Map after last synchronization.
+  void SyncRepeatedFieldWithMap() const;
+  virtual void SyncRepeatedFieldWithMapNoLock() const;
+
+  // Synchronizes the content in RepeatedPtrField to Map if there is any change
+  // to RepeatedPtrField after last synchronization.
+  void SyncMapWithRepeatedField() const;
+  virtual void SyncMapWithRepeatedFieldNoLock() const {}
+
+  // Tells MapFieldBase that there is new change to Map.
+  void SetMapDirty();
+
+  // Tells MapFieldBase that there is new change to RepeatedPTrField.
+  void SetRepeatedDirty();
+
+  // Provides derived class the access to repeated field.
+  void* MutableRepeatedPtrField() const;
+
+  // Creates descriptor for only one time.
+  void InitMetadataOnce() const;
+
+  enum State {
+    STATE_MODIFIED_MAP = 0,       // map has newly added data that has not been
+                                  // synchronized to repeated field
+    STATE_MODIFIED_REPEATED = 1,  // repeated field has newly added data that
+                                  // has not been synchronized to map
+    CLEAN = 2,  // data in map and repeated field are same
+  };
+
+  mutable void* base_map_;
+  mutable RepeatedPtrField<Message>* repeated_field_;
+  // MapEntry can only be created from MapField. To create MapEntry, MapField
+  // needs to know its descriptor, because MapEntry is not generated class which
+  // cannot initialize its own descriptor by calling generated
+  // descriptor-assign-function. Thus, we need to register a callback to
+  // initialize MapEntry's descriptor.
+  const Descriptor** entry_descriptor_;
+  void (*assign_descriptor_callback_)();
+
+  mutable Mutex mutex_;  // The thread to synchronize map and repeated field
+                         // needs to get lock first;
+  mutable volatile Atomic32 state_;  // 0: STATE_MODIFIED_MAP
+                                     // 1: STATE_MODIFIED_REPEATED
+                                     // 2: CLEAN
+
+ private:
+  friend class ContendedMapCleanTest;
+  friend class GeneratedMessageReflection;
+  friend class MapFieldAccessor;
+};
+
+// This class provides accesss to map field using generated api. It is used for
+// internal generated message implentation only. Users should never use this
+// directly.
+template<typename Key, typename T,
+         FieldDescriptor::Type KeyProto,
+         FieldDescriptor::Type ValueProto, int default_enum_value = 0>
+class LIBPROTOBUF_EXPORT MapField : public MapFieldBase {
+  // Handlers for key/value's proto field type.
+  typedef MapProtoTypeHandler<KeyProto> KeyProtoHandler;
+  typedef MapProtoTypeHandler<ValueProto> ValueProtoHandler;
+
+  // Define key/value's internal stored type.
+  typedef typename KeyProtoHandler::CppType KeyHandlerCpp;
+  typedef typename ValueProtoHandler::CppType ValHandlerCpp;
+  static const bool kIsKeyMessage = KeyProtoHandler::kIsMessage;
+  static const bool kIsValMessage = ValueProtoHandler::kIsMessage;
+  typedef typename MapIf<kIsKeyMessage, Key, KeyHandlerCpp>::type KeyCpp;
+  typedef typename MapIf<kIsValMessage, T  , ValHandlerCpp>::type ValCpp;
+
+  // Handlers for key/value's internal stored type.
+  typedef MapCppTypeHandler<KeyCpp> KeyHandler;
+  typedef MapCppTypeHandler<ValCpp> ValHandler;
+
+  // Define message type for internal repeated field.
+  typedef MapEntry<Key, T, KeyProto, ValueProto, default_enum_value> EntryType;
+
+  // Enum needs to be handled differently from other types because it has
+  // different exposed type in google::protobuf::Map's api and repeated field's api. For
+  // details see the comment in the implementation of
+  // SyncMapWithRepeatedFieldNoLocki.
+  static const bool kIsValueEnum = ValueProtoHandler::kIsEnum;
+  typedef typename MapIf<kIsValueEnum, T, const T&>::type CastValueType;
+
+ public:
+  MapField();
+  // MapField doesn't own the default_entry, which means default_entry must
+  // outlive the lifetime of MapField.
+  MapField(const Message* default_entry);
+  ~MapField();
+
+  // Accessors
+  const Map<Key, T>& GetMap() const;
+  Map<Key, T>* MutableMap();
+
+  // Convenient methods for generated message implementation.
+  int size() const;
+  void Clear();
+  void MergeFrom(const MapField& other);
+  void Swap(MapField* other);
+
+  // Allocates metadata only if this MapField is part of a generated message.
+  void SetEntryDescriptor(const Descriptor** descriptor);
+  void SetAssignDescriptorCallback(void (*callback)());
+
+  // Set default enum value only for proto2 map field whose value is enum type.
+  void SetDefaultEnumValue();
+
+  // Used in the implementation of parsing. Caller should take the ownership.
+  EntryType* NewEntry() const;
+  // Used in the implementation of serializing enum value type. Caller should
+  // take the ownership.
+  EntryType* NewEnumEntryWrapper(const Key& key, const T t) const;
+  // Used in the implementation of serializing other value types. Caller should
+  // take the ownership.
+  EntryType* NewEntryWrapper(const Key& key, const T& t) const;
+
+ private:
+  // MapField needs MapEntry's default instance to create new MapEntry.
+  void InitDefaultEntryOnce() const;
+
+  // Convenient methods to get internal google::protobuf::Map
+  const Map<Key, T>& GetInternalMap() const;
+  Map<Key, T>* MutableInternalMap();
+
+  // Implements MapFieldBase
+  void SyncRepeatedFieldWithMapNoLock() const;
+  void SyncMapWithRepeatedFieldNoLock() const;
+  int SpaceUsedExcludingSelfNoLock() const;
+
+  mutable const EntryType* default_entry_;
+};
+
+}  // namespace internal
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_MAP_FIELD_H__

+ 269 - 0
src/google/protobuf/map_field_inl.h

@@ -0,0 +1,269 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_MAP_FIELD_INL_H__
+#define GOOGLE_PROTOBUF_MAP_FIELD_INL_H__
+
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+
+#include <google/protobuf/map_field.h>
+#include <google/protobuf/map_type_handler.h>
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+template <typename Key, typename T, FieldDescriptor::Type KeyProto,
+          FieldDescriptor::Type ValueProto, int default_enum_value>
+MapField<Key, T, KeyProto, ValueProto, default_enum_value>::MapField()
+    : default_entry_(NULL) {
+  MapFieldBase::base_map_ = new Map<Key, T>;
+  SetDefaultEnumValue();
+}
+
+template <typename Key, typename T, FieldDescriptor::Type KeyProto,
+          FieldDescriptor::Type ValueProto, int default_enum_value>
+MapField<Key, T, KeyProto, ValueProto, default_enum_value>::MapField(
+    const Message* default_entry)
+    : default_entry_(down_cast<const EntryType*>(default_entry)) {
+  MapFieldBase::base_map_ = new Map<Key, T>;
+  SetDefaultEnumValue();
+}
+
+template <typename Key, typename T, FieldDescriptor::Type KeyProto,
+          FieldDescriptor::Type ValueProto, int default_enum_value>
+MapField<Key, T, KeyProto, ValueProto, default_enum_value>::~MapField() {
+  delete reinterpret_cast<Map<Key, T>*>(MapFieldBase::base_map_);
+}
+
+template <typename Key, typename T, FieldDescriptor::Type KeyProto,
+          FieldDescriptor::Type ValueProto, int default_enum_value>
+int MapField<Key, T, KeyProto, ValueProto, default_enum_value>::size() const {
+  SyncMapWithRepeatedField();
+  return GetInternalMap().size();
+}
+
+template <typename Key, typename T, FieldDescriptor::Type KeyProto,
+          FieldDescriptor::Type ValueProto, int default_enum_value>
+void MapField<Key, T, KeyProto, ValueProto, default_enum_value>::Clear() {
+  SyncMapWithRepeatedField();
+  MutableInternalMap()->clear();
+  SetMapDirty();
+}
+
+template <typename Key, typename T, FieldDescriptor::Type KeyProto,
+          FieldDescriptor::Type ValueProto, int default_enum_value>
+const Map<Key, T>&
+MapField<Key, T, KeyProto, ValueProto, default_enum_value>::GetMap() const {
+  SyncMapWithRepeatedField();
+  return GetInternalMap();
+}
+
+template <typename Key, typename T, FieldDescriptor::Type KeyProto,
+          FieldDescriptor::Type ValueProto, int default_enum_value>
+Map<Key, T>*
+MapField<Key, T, KeyProto, ValueProto, default_enum_value>::MutableMap() {
+  SyncMapWithRepeatedField();
+  Map<Key, T>* result = MutableInternalMap();
+  SetMapDirty();
+  return result;
+}
+
+template <typename Key, typename T, FieldDescriptor::Type KeyProto,
+          FieldDescriptor::Type ValueProto, int default_enum_value>
+void MapField<Key, T, KeyProto, ValueProto, default_enum_value>::MergeFrom(
+    const MapField& other) {
+  SyncMapWithRepeatedField();
+  other.SyncMapWithRepeatedField();
+
+  Map<Key, T>* map = MutableInternalMap();
+  const Map<Key, T>& other_map = other.GetInternalMap();
+  for (typename Map<Key, T>::const_iterator it = other_map.begin();
+       it != other_map.end(); ++it) {
+    (*map)[it->first] = it->second;
+  }
+  SetMapDirty();
+}
+
+template <typename Key, typename T, FieldDescriptor::Type KeyProto,
+          FieldDescriptor::Type ValueProto, int default_enum_value>
+void MapField<Key, T, KeyProto, ValueProto, default_enum_value>::Swap(
+    MapField* other) {
+  std::swap(repeated_field_, other->repeated_field_);
+  std::swap(base_map_, other->base_map_);
+  std::swap(state_, other->state_);
+}
+
+template <typename Key, typename T, FieldDescriptor::Type KeyProto,
+          FieldDescriptor::Type ValueProto, int default_enum_value>
+void
+MapField<Key, T, KeyProto, ValueProto, default_enum_value>::SetEntryDescriptor(
+    const Descriptor** descriptor) {
+  entry_descriptor_ = descriptor;
+}
+
+template <typename Key, typename T, FieldDescriptor::Type KeyProto,
+          FieldDescriptor::Type ValueProto, int default_enum_value>
+void
+MapField<Key, T, KeyProto, ValueProto,
+         default_enum_value>::SetAssignDescriptorCallback(void (*callback)()) {
+  assign_descriptor_callback_ = callback;
+}
+
+template <typename Key, typename T, FieldDescriptor::Type KeyProto,
+          FieldDescriptor::Type ValueProto, int default_enum_value>
+void MapField<Key, T, KeyProto, ValueProto,
+              default_enum_value>::SetDefaultEnumValue() {
+  MutableInternalMap()->SetDefaultEnumValue(default_enum_value);
+}
+
+template <typename Key, typename T, FieldDescriptor::Type KeyProto,
+          FieldDescriptor::Type ValueProto, int default_enum_value>
+MapEntry<Key, T, KeyProto, ValueProto, default_enum_value>*
+MapField<Key, T, KeyProto, ValueProto, default_enum_value>::NewEntry() const {
+  // The MapEntry instance created here is only used in generated code for
+  // parsing. It doesn't have default instance, descriptor or reflection,
+  // because these are not needed in parsing and will prevent us from using it
+  // for parsing MessageLite.
+  return new EntryType();
+}
+
+template <typename Key, typename T, FieldDescriptor::Type KeyProto,
+          FieldDescriptor::Type ValueProto, int default_enum_value>
+MapEntry<Key, T, KeyProto, ValueProto, default_enum_value>*
+MapField<Key, T, KeyProto, ValueProto, default_enum_value>::NewEntryWrapper(
+    const Key& key, const T& t) const {
+  return EntryType::Wrap(key, t);
+}
+
+template <typename Key, typename T, FieldDescriptor::Type KeyProto,
+          FieldDescriptor::Type ValueProto, int default_enum_value>
+MapEntry<Key, T, KeyProto, ValueProto, default_enum_value>*
+MapField<Key, T, KeyProto, ValueProto, default_enum_value>::NewEnumEntryWrapper(
+    const Key& key, const T t) const {
+  return EntryType::EnumWrap(key, t);
+}
+
+template <typename Key, typename T, FieldDescriptor::Type KeyProto,
+          FieldDescriptor::Type ValueProto, int default_enum_value>
+const Map<Key, T>& MapField<Key, T, KeyProto, ValueProto,
+                            default_enum_value>::GetInternalMap() const {
+  return *reinterpret_cast<Map<Key, T>*>(MapFieldBase::base_map_);
+}
+
+template <typename Key, typename T, FieldDescriptor::Type KeyProto,
+          FieldDescriptor::Type ValueProto, int default_enum_value>
+Map<Key, T>* MapField<Key, T, KeyProto, ValueProto,
+                      default_enum_value>::MutableInternalMap() {
+  return reinterpret_cast<Map<Key, T>*>(MapFieldBase::base_map_);
+}
+
+template <typename Key, typename T, FieldDescriptor::Type KeyProto,
+          FieldDescriptor::Type ValueProto, int default_enum_value>
+void MapField<Key, T, KeyProto, ValueProto,
+              default_enum_value>::SyncRepeatedFieldWithMapNoLock() const {
+  if (repeated_field_ == NULL) {
+    repeated_field_ = new RepeatedPtrField<Message>();
+  }
+  const Map<Key, T>& map =
+      *static_cast<const Map<Key, T>*>(MapFieldBase::base_map_);
+  RepeatedPtrField<EntryType>* repeated_field =
+      reinterpret_cast<RepeatedPtrField<EntryType>*>(repeated_field_);
+
+  repeated_field->Clear();
+
+  for (typename Map<Key, T>::const_iterator it = map.begin();
+       it != map.end(); ++it) {
+    InitDefaultEntryOnce();
+    GOOGLE_CHECK(default_entry_ != NULL);
+    EntryType* new_entry = down_cast<EntryType*>(default_entry_->New());
+    repeated_field->AddAllocated(new_entry);
+    new_entry->set_key(it->first);
+    new_entry->set_value(it->second);
+  }
+}
+
+template <typename Key, typename T, FieldDescriptor::Type KeyProto,
+          FieldDescriptor::Type ValueProto, int default_enum_value>
+void MapField<Key, T, KeyProto, ValueProto,
+              default_enum_value>::SyncMapWithRepeatedFieldNoLock() const {
+  Map<Key, T>* map = reinterpret_cast<Map<Key, T>*>(MapFieldBase::base_map_);
+  RepeatedPtrField<EntryType>* repeated_field =
+      reinterpret_cast<RepeatedPtrField<EntryType>*>(repeated_field_);
+  map->clear();
+  for (typename RepeatedPtrField<EntryType>::iterator it =
+           repeated_field->begin(); it != repeated_field->end(); ++it) {
+    // Cast is needed because Map's api and internal storage is different when
+    // value is enum. For enum, we cannot cast an int to enum. Thus, we have to
+    // copy value. For other types, they have same exposed api type and internal
+    // stored type. We should not introduce value copy for them. We achieve this
+    // by casting to value for enum while casting to reference for other types.
+    (*map)[it->key()] = static_cast<CastValueType>(it->value());
+  }
+}
+
+template <typename Key, typename T, FieldDescriptor::Type KeyProto,
+          FieldDescriptor::Type ValueProto, int default_enum_value>
+int MapField<Key, T, KeyProto, ValueProto,
+             default_enum_value>::SpaceUsedExcludingSelfNoLock() const {
+  int size = 0;
+  if (repeated_field_ != NULL) {
+    size += repeated_field_->SpaceUsedExcludingSelf();
+  }
+  Map<Key, T>* map = reinterpret_cast<Map<Key, T>*>(MapFieldBase::base_map_);
+  size += sizeof(*map);
+  for (typename Map<Key, T>::iterator it = map->begin();
+       it != map->end(); ++it) {
+    size += KeyHandler::SpaceUsedInMap(it->first);
+    size += ValHandler::SpaceUsedInMap(it->second);
+  }
+  return size;
+}
+
+template <typename Key, typename T, FieldDescriptor::Type KeyProto,
+          FieldDescriptor::Type ValueProto, int default_enum_value>
+void MapField<Key, T, KeyProto, ValueProto,
+              default_enum_value>::InitDefaultEntryOnce() const {
+  if (default_entry_ == NULL) {
+    InitMetadataOnce();
+    GOOGLE_CHECK(*entry_descriptor_ != NULL);
+    default_entry_ = down_cast<const EntryType*>(
+        MessageFactory::generated_factory()->GetPrototype(*entry_descriptor_));
+  }
+}
+
+}  // namespace internal
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_MAP_FIELD_INL_H__

+ 470 - 0
src/google/protobuf/map_field_test.cc

@@ -0,0 +1,470 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <map>
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/map.h>
+#include <google/protobuf/map_unittest.pb.h>
+#include <google/protobuf/map_test_util.h>
+#include <google/protobuf/unittest.pb.h>
+#include <google/protobuf/map_field_inl.h>
+#include <google/protobuf/message.h>
+#include <google/protobuf/repeated_field.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+
+namespace internal {
+
+using unittest::TestAllTypes;
+
+class MapFieldBaseStub : public MapFieldBase {
+ public:
+  void SyncRepeatedFieldWithMap() const {
+    MapFieldBase::SyncRepeatedFieldWithMap();
+  }
+  void SyncMapWithRepeatedField() const {
+    MapFieldBase::SyncMapWithRepeatedField();
+  }
+  // Get underlined repeated field without synchronizing map.
+  RepeatedPtrField<Message>* InternalRepeatedField() {
+    return repeated_field_;
+  }
+  // Get underlined map without synchronizing repeated field.
+  template <typename MapType>
+  const MapType& GetMap() {
+    return *reinterpret_cast<MapType*>(base_map_);
+  }
+  // Get underlined map without synchronizing repeated field.
+  template <typename MapType>
+  MapType* MutableMap() {
+    return reinterpret_cast<MapType*>(base_map_);
+  }
+  bool IsMapClean() { return state_ != 0; }
+  bool IsRepeatedClean() { return state_ != 1; }
+  void SetMapDirty() { state_ = 0; }
+  void SetRepeatedDirty() { state_ = 1; }
+};
+
+class MapFieldBasePrimitiveTest : public ::testing::Test {
+ protected:
+  typedef MapField<int32, int32, FieldDescriptor::TYPE_INT32,
+                   FieldDescriptor::TYPE_INT32> MapFieldType;
+
+  MapFieldBasePrimitiveTest() {
+    // Get descriptors
+    map_descriptor_ = unittest::TestMap::descriptor()
+                          ->FindFieldByName("map_int32_int32")
+                          ->message_type();
+    key_descriptor_ = map_descriptor_->FindFieldByName("key");
+    value_descriptor_ = map_descriptor_->FindFieldByName("value");
+
+    // Build map field
+    default_entry_ =
+        MessageFactory::generated_factory()->GetPrototype(map_descriptor_);
+    map_field_.reset(new MapFieldType(default_entry_));
+    map_field_base_ = map_field_.get();
+    map_ = map_field_->MutableMap();
+    initial_value_map_[0] = 100;
+    initial_value_map_[1] = 101;
+    map_->insert(initial_value_map_.begin(), initial_value_map_.end());
+    EXPECT_EQ(2, map_->size());
+  }
+
+  google::protobuf::scoped_ptr<MapFieldType> map_field_;
+  MapFieldBase* map_field_base_;
+  Map<int32, int32>* map_;
+  const Descriptor* map_descriptor_;
+  const FieldDescriptor* key_descriptor_;
+  const FieldDescriptor* value_descriptor_;
+  const Message* default_entry_;
+  std::map<int32, int32> initial_value_map_;  // copy of initial values inserted
+};
+
+TEST_F(MapFieldBasePrimitiveTest, SpaceUsedExcludingSelf) {
+  EXPECT_LT(0, map_field_base_->SpaceUsedExcludingSelf());
+}
+
+TEST_F(MapFieldBasePrimitiveTest, GetRepeatedField) {
+  const RepeatedPtrField<Message>& repeated =
+      reinterpret_cast<const RepeatedPtrField<Message>&>(
+          map_field_base_->GetRepeatedField());
+  EXPECT_EQ(2, repeated.size());
+  for (int i = 0; i < repeated.size(); i++) {
+    const Message& message = repeated.Get(i);
+    int key = message.GetReflection()->GetInt32(message, key_descriptor_);
+    int value = message.GetReflection()->GetInt32(message, value_descriptor_);
+    EXPECT_EQ(value, initial_value_map_[key]);
+  }
+}
+
+TEST_F(MapFieldBasePrimitiveTest, MutableRepeatedField) {
+  RepeatedPtrField<Message>* repeated =
+      reinterpret_cast<RepeatedPtrField<Message>*>(
+          map_field_base_->MutableRepeatedField());
+  EXPECT_EQ(2, repeated->size());
+  for (int i = 0; i < repeated->size(); i++) {
+    const Message& message = repeated->Get(i);
+    int key = message.GetReflection()->GetInt32(message, key_descriptor_);
+    int value = message.GetReflection()->GetInt32(message, value_descriptor_);
+    EXPECT_EQ(value, initial_value_map_[key]);
+  }
+}
+
+namespace {
+enum State { CLEAN, MAP_DIRTY, REPEATED_DIRTY };
+}  // anonymous namespace
+
+class MapFieldStateTest
+    : public testing::TestWithParam<State> {
+ public:
+ protected:
+  typedef MapField<int32, int32, FieldDescriptor::TYPE_INT32,
+                FieldDescriptor::TYPE_INT32> MapFieldType;
+  MapFieldStateTest() : state_(GetParam()) {
+    // Build map field
+    const Descriptor* map_descriptor =
+        unittest::TestMap::descriptor()
+            ->FindFieldByName("map_int32_int32")
+            ->message_type();
+    default_entry_ =
+        MessageFactory::generated_factory()->GetPrototype(map_descriptor);
+    map_field_.reset(new MapFieldType(default_entry_));
+    map_field_base_ = map_field_.get();
+
+    Expect(map_field_.get(), MAP_DIRTY, 0, 0, true);
+    switch (state_) {
+      case CLEAN:
+        AddOneStillClean(map_field_.get());
+        break;
+      case MAP_DIRTY:
+        MakeMapDirty(map_field_.get());
+        break;
+      case REPEATED_DIRTY:
+        MakeRepeatedDirty(map_field_.get());
+        break;
+      default:
+        break;
+    }
+  }
+
+  void AddOneStillClean(MapFieldType* map_field) {
+    MapFieldBase* map_field_base = map_field;
+    Map<int32, int32>* map = map_field->MutableMap();
+    (*map)[0] = 0;
+    map_field_base->GetRepeatedField();
+    Expect(map_field, CLEAN, 1, 1, false);
+  }
+
+  void MakeMapDirty(MapFieldType* map_field) {
+    Map<int32, int32>* map = map_field->MutableMap();
+    (*map)[0] = 0;
+    Expect(map_field, MAP_DIRTY, 1, 0, true);
+  }
+
+  void MakeRepeatedDirty(MapFieldType* map_field) {
+    MakeMapDirty(map_field);
+    MapFieldBase* map_field_base = map_field;
+    map_field_base->MutableRepeatedField();
+    MapFieldBaseStub* stub =
+        reinterpret_cast<MapFieldBaseStub*>(map_field_base);
+    Map<int32, int32>* map = stub->MutableMap<Map<int32, int32> >();
+    map->clear();
+
+    Expect(map_field, REPEATED_DIRTY, 0, 1, false);
+  }
+
+  void Expect(MapFieldType* map_field, State state, int map_size,
+              int repeated_size, bool is_repeated_null) {
+    MapFieldBase* map_field_base = map_field;
+    MapFieldBaseStub* stub =
+        reinterpret_cast<MapFieldBaseStub*>(map_field_base);
+
+    Map<int32, int32>* map = stub->MutableMap<Map<int32, int32> >();
+    RepeatedPtrField<Message>* repeated_field = stub->InternalRepeatedField();
+
+    switch (state) {
+      case MAP_DIRTY:
+        EXPECT_FALSE(stub->IsMapClean());
+        EXPECT_TRUE(stub->IsRepeatedClean());
+        break;
+      case REPEATED_DIRTY:
+        EXPECT_TRUE(stub->IsMapClean());
+        EXPECT_FALSE(stub->IsRepeatedClean());
+        break;
+      case CLEAN:
+        EXPECT_TRUE(stub->IsMapClean());
+        EXPECT_TRUE(stub->IsRepeatedClean());
+        break;
+      default:
+        FAIL();
+    }
+
+    EXPECT_EQ(map_size, map->size());
+    if (is_repeated_null) {
+      EXPECT_TRUE(repeated_field == NULL);
+    } else {
+      EXPECT_EQ(repeated_size, repeated_field->size());
+    }
+  }
+
+  google::protobuf::scoped_ptr<MapFieldType> map_field_;
+  MapFieldBase* map_field_base_;
+  State state_;
+  const Message* default_entry_;
+};
+
+INSTANTIATE_TEST_CASE_P(MapFieldStateTestInstance, MapFieldStateTest,
+                        ::testing::Values(CLEAN, MAP_DIRTY, REPEATED_DIRTY));
+
+TEST_P(MapFieldStateTest, GetMap) {
+  map_field_->GetMap();
+  if (state_ != MAP_DIRTY) {
+    Expect(map_field_.get(), CLEAN, 1, 1, false);
+  } else {
+    Expect(map_field_.get(), MAP_DIRTY, 1, 0, true);
+  }
+}
+
+TEST_P(MapFieldStateTest, MutableMap) {
+  map_field_->MutableMap();
+  if (state_ != MAP_DIRTY) {
+    Expect(map_field_.get(), MAP_DIRTY, 1, 1, false);
+  } else {
+    Expect(map_field_.get(), MAP_DIRTY, 1, 0, true);
+  }
+}
+
+TEST_P(MapFieldStateTest, MergeFromClean) {
+  MapFieldType other(default_entry_);
+  AddOneStillClean(&other);
+
+  map_field_->MergeFrom(other);
+
+  if (state_ != MAP_DIRTY) {
+    Expect(map_field_.get(), MAP_DIRTY, 1, 1, false);
+  } else {
+    Expect(map_field_.get(), MAP_DIRTY, 1, 0, true);
+  }
+
+  Expect(&other, CLEAN, 1, 1, false);
+}
+
+TEST_P(MapFieldStateTest, MergeFromMapDirty) {
+  MapFieldType other(default_entry_);
+  MakeMapDirty(&other);
+
+  map_field_->MergeFrom(other);
+
+  if (state_ != MAP_DIRTY) {
+    Expect(map_field_.get(), MAP_DIRTY, 1, 1, false);
+  } else {
+    Expect(map_field_.get(), MAP_DIRTY, 1, 0, true);
+  }
+
+  Expect(&other, MAP_DIRTY, 1, 0, true);
+}
+
+TEST_P(MapFieldStateTest, MergeFromRepeatedDirty) {
+  MapFieldType other(default_entry_);
+  MakeRepeatedDirty(&other);
+
+  map_field_->MergeFrom(other);
+
+  if (state_ != MAP_DIRTY) {
+    Expect(map_field_.get(), MAP_DIRTY, 1, 1, false);
+  } else {
+    Expect(map_field_.get(), MAP_DIRTY, 1, 0, true);
+  }
+
+  Expect(&other, CLEAN, 1, 1, false);
+}
+
+TEST_P(MapFieldStateTest, SwapClean) {
+  MapFieldType other(default_entry_);
+  AddOneStillClean(&other);
+
+  map_field_->Swap(&other);
+
+  Expect(map_field_.get(), CLEAN, 1, 1, false);
+
+  switch (state_) {
+    case CLEAN:
+      Expect(&other, CLEAN, 1, 1, false);
+      break;
+    case MAP_DIRTY:
+      Expect(&other, MAP_DIRTY, 1, 0, true);
+      break;
+    case REPEATED_DIRTY:
+      Expect(&other, REPEATED_DIRTY, 0, 1, false);
+      break;
+    default:
+      break;
+  }
+}
+
+TEST_P(MapFieldStateTest, SwapMapDirty) {
+  MapFieldType other(default_entry_);
+  MakeMapDirty(&other);
+
+  map_field_->Swap(&other);
+
+  Expect(map_field_.get(), MAP_DIRTY, 1, 0, true);
+
+  switch (state_) {
+    case CLEAN:
+      Expect(&other, CLEAN, 1, 1, false);
+      break;
+    case MAP_DIRTY:
+      Expect(&other, MAP_DIRTY, 1, 0, true);
+      break;
+    case REPEATED_DIRTY:
+      Expect(&other, REPEATED_DIRTY, 0, 1, false);
+      break;
+    default:
+      break;
+  }
+}
+
+TEST_P(MapFieldStateTest, SwapRepeatedDirty) {
+  MapFieldType other(default_entry_);
+  MakeRepeatedDirty(&other);
+
+  map_field_->Swap(&other);
+
+  Expect(map_field_.get(), REPEATED_DIRTY, 0, 1, false);
+
+  switch (state_) {
+    case CLEAN:
+      Expect(&other, CLEAN, 1, 1, false);
+      break;
+    case MAP_DIRTY:
+      Expect(&other, MAP_DIRTY, 1, 0, true);
+      break;
+    case REPEATED_DIRTY:
+      Expect(&other, REPEATED_DIRTY, 0, 1, false);
+      break;
+    default:
+      break;
+  }
+}
+
+TEST_P(MapFieldStateTest, Clear) {
+  map_field_->Clear();
+
+  if (state_ != MAP_DIRTY) {
+    Expect(map_field_.get(), MAP_DIRTY, 0, 1, false);
+  } else {
+    Expect(map_field_.get(), MAP_DIRTY, 0, 0, true);
+  }
+}
+
+TEST_P(MapFieldStateTest, SpaceUsedExcludingSelf) {
+  map_field_base_->SpaceUsedExcludingSelf();
+
+  switch (state_) {
+    case CLEAN:
+      Expect(map_field_.get(), CLEAN, 1, 1, false);
+      break;
+    case MAP_DIRTY:
+      Expect(map_field_.get(), MAP_DIRTY, 1, 0, true);
+      break;
+    case REPEATED_DIRTY:
+      Expect(map_field_.get(), REPEATED_DIRTY, 0, 1, false);
+      break;
+    default:
+      break;
+  }
+}
+
+TEST_P(MapFieldStateTest, GetMapField) {
+  map_field_base_->GetRepeatedField();
+
+  if (state_ != REPEATED_DIRTY) {
+    Expect(map_field_.get(), CLEAN, 1, 1, false);
+  } else {
+    Expect(map_field_.get(), REPEATED_DIRTY, 0, 1, false);
+  }
+}
+
+TEST_P(MapFieldStateTest, MutableMapField) {
+  map_field_base_->MutableRepeatedField();
+
+  if (state_ != REPEATED_DIRTY) {
+    Expect(map_field_.get(), REPEATED_DIRTY, 1, 1, false);
+  } else {
+    Expect(map_field_.get(), REPEATED_DIRTY, 0, 1, false);
+  }
+}
+
+class MapFieldBaseStateStub : public MapFieldBaseStub {
+ public:
+  MapFieldBaseStateStub(Mutex* mutex, int* clean_counter,
+                        int* completed_counter)
+      : mutex_(mutex),
+        clean_counter_(clean_counter),
+        completed_counter_(completed_counter) {}
+  ~MapFieldBaseStateStub() {}
+
+ protected:
+  void SyncRepeatedFieldWithMapNoLock() const { Clean(); }
+  void SyncMapWithRepeatedFieldNoLock() const { Clean(); }
+
+ private:
+  void Clean() const {
+    {
+      MutexLock lock(mutex_);
+      ++(*clean_counter_);
+    }
+    struct timespec tm;
+    tm.tv_sec = 0;
+    tm.tv_nsec = 100000000;  // 100ms
+    nanosleep(&tm, NULL);
+    {
+      MutexLock lock(mutex_);
+      // No other thread should have completed while this one was initializing.
+      EXPECT_EQ(0, *completed_counter_);
+    }
+  }
+  Mutex* mutex_;
+  int* clean_counter_;
+  int* completed_counter_;
+};
+
+
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google

+ 39 - 0
src/google/protobuf/map_lite_unittest.proto

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

+ 68 - 0
src/google/protobuf/map_proto2_unittest.proto

@@ -0,0 +1,68 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto2";
+
+
+// We don't put this in a package within proto2 because we need to make sure
+// that the generated code doesn't depend on being in the proto2 namespace.
+// In map_test_util.h we do "using namespace unittest = protobuf_unittest".
+package protobuf_unittest;
+
+enum Proto2MapEnum {
+  PROTO2_MAP_ENUM_FOO   = 0;
+  PROTO2_MAP_ENUM_BAR   = 1;
+  PROTO2_MAP_ENUM_BAZ   = 2;
+}
+
+enum Proto2MapEnumPlusExtra {
+  E_PROTO2_MAP_ENUM_FOO   = 0;
+  E_PROTO2_MAP_ENUM_BAR   = 1;
+  E_PROTO2_MAP_ENUM_BAZ   = 2;
+  E_PROTO2_MAP_ENUM_EXTRA = 3;
+}
+
+enum Proto2MapEnumStartWithNonZero {
+  PROTO2_NON_ZERO_MAP_ENUM_FOO = 1;
+}
+
+message TestEnumMap {
+  map<int32, Proto2MapEnum> known_map_field = 101;
+  map<int32, Proto2MapEnum> unknown_map_field = 102;
+}
+
+message TestEnumMapPlusExtra {
+  map<int32, Proto2MapEnumPlusExtra> known_map_field = 101;
+  map<int32, Proto2MapEnumPlusExtra> unknown_map_field = 102;
+}
+
+message TestEnumStartWithNonZeroMap {
+  map<int32, Proto2MapEnumStartWithNonZero> map_field = 101;
+}

+ 2143 - 0
src/google/protobuf/map_test.cc

@@ -0,0 +1,2143 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <map>
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+#include <sstream>
+
+#include <google/protobuf/stubs/casts.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/stringprintf.h>
+#include <google/protobuf/testing/file.h>
+#include <google/protobuf/map_lite_unittest.pb.h>
+#include <google/protobuf/map_proto2_unittest.pb.h>
+#include <google/protobuf/map_unittest.pb.h>
+#include <google/protobuf/map_test_util.h>
+#include <google/protobuf/test_util.h>
+#include <google/protobuf/unittest.pb.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/descriptor_database.h>
+#include <google/protobuf/dynamic_message.h>
+#include <google/protobuf/map.h>
+#include <google/protobuf/map_field_inl.h>
+#include <google/protobuf/message.h>
+#include <google/protobuf/reflection.h>
+#include <google/protobuf/reflection_ops.h>
+#include <google/protobuf/text_format.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/wire_format_lite_inl.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/tokenizer.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/substitute.h>
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+
+namespace google {
+
+using google::protobuf::unittest::ForeignMessage;
+using google::protobuf::unittest::TestAllTypes;
+using google::protobuf::unittest::TestMap;
+
+namespace protobuf {
+namespace internal {
+
+// Map API Test =====================================================
+
+class MapImplTest : public ::testing::Test {
+ protected:
+  MapImplTest()
+      : map_ptr_(new Map<int32, int32>),
+        map_(*map_ptr_),
+        const_map_(*map_ptr_) {
+    EXPECT_TRUE(map_.empty());
+    EXPECT_EQ(0, map_.size());
+  }
+  ~MapImplTest() override {}
+
+  void ExpectSingleElement(int32 key, int32 value) {
+    EXPECT_FALSE(map_.empty());
+    EXPECT_EQ(1, map_.size());
+    ExpectElement(key, value);
+  }
+
+  void ExpectElements(const std::map<int32, int32>& map) {
+    EXPECT_FALSE(map_.empty());
+    EXPECT_EQ(map.size(), map_.size());
+    for (std::map<int32, int32>::const_iterator it = map.begin();
+         it != map.end(); ++it) {
+      ExpectElement(it->first, it->second);
+    }
+  }
+
+  void ExpectElement(int32 key, int32 value) {
+    // Test map size is correct.
+    EXPECT_EQ(value, map_[key]);
+    EXPECT_EQ(1, map_.count(key));
+
+    // Check mutable at and find work correctly.
+    EXPECT_EQ(value, map_.at(key));
+    Map<int32, int32>::iterator it = map_.find(key);
+
+    // interator dereferenceable
+    EXPECT_EQ(key,   (*it).first);
+    EXPECT_EQ(value, (*it).second);
+    EXPECT_EQ(key,   it->first);
+    EXPECT_EQ(value, it->second);
+
+    // iterator mutable
+    ((*it).second) = value + 1;
+    EXPECT_EQ(value + 1, map_[key]);
+    ((*it).second) = value;
+    EXPECT_EQ(value, map_[key]);
+
+    it->second = value + 1;
+    EXPECT_EQ(value + 1, map_[key]);
+    it->second = value;
+    EXPECT_EQ(value, map_[key]);
+
+    // copy constructor
+    Map<int32, int32>::iterator it_copy = it;
+    EXPECT_EQ(key, it_copy->first);
+    EXPECT_EQ(value, it_copy->second);
+
+    // Immutable API ================================================
+
+    // Check immutable at and find work correctly.
+    EXPECT_EQ(value, const_map_.at(key));
+    Map<int32, int32>::const_iterator const_it = const_map_.find(key);
+
+    // interator dereferenceable
+    EXPECT_EQ(key, (*const_it).first);
+    EXPECT_EQ(value, (*const_it).second);
+    EXPECT_EQ(key, const_it->first);
+    EXPECT_EQ(value, const_it->second);
+
+    // copy constructor
+    Map<int32, int32>::const_iterator const_it_copy = const_it;
+    EXPECT_EQ(key, const_it_copy->first);
+    EXPECT_EQ(value, const_it_copy->second);
+  }
+
+  google::protobuf::scoped_ptr<Map<int32, int32> > map_ptr_;
+  Map<int32, int32>& map_;
+  const Map<int32, int32>& const_map_;
+};
+
+TEST_F(MapImplTest, OperatorBracket) {
+  int32 key = 0;
+  int32 value1 = 100;
+  int32 value2 = 101;
+
+  EXPECT_EQ(0, map_[key]);
+
+  map_[key] = value1;
+  ExpectSingleElement(key, value1);
+
+  map_[key] = value2;
+  ExpectSingleElement(key, value2);
+}
+
+TEST_F(MapImplTest, OperatorBracketNonExist) {
+  int32 key = 0;
+  int32 default_value = 0;
+
+  EXPECT_EQ(default_value, map_[key]);
+  ExpectSingleElement(key, default_value);
+}
+
+TEST_F(MapImplTest, MutableAt) {
+  int32 key = 0;
+  int32 value1 = 100;
+  int32 value2 = 101;
+
+  map_[key] = value1;
+  ExpectSingleElement(key, value1);
+
+  map_.at(key) = value2;
+  ExpectSingleElement(key, value2);
+}
+
+TEST_F(MapImplTest, MutableAtNonExistDeathTest) {
+  EXPECT_DEATH(map_.at(0), "");
+}
+
+TEST_F(MapImplTest, ImmutableAtNonExistDeathTest) {
+  EXPECT_DEATH(const_map_.at(0), "");
+}
+
+TEST_F(MapImplTest, CountNonExist) {
+  EXPECT_EQ(0, map_.count(0));
+}
+
+TEST_F(MapImplTest, MutableFindNonExist) {
+  EXPECT_TRUE(map_.end() == map_.find(0));
+}
+
+TEST_F(MapImplTest, ImmutableFindNonExist) {
+  EXPECT_TRUE(const_map_.end() == const_map_.find(0));
+}
+
+TEST_F(MapImplTest, ConstEnd) {
+  EXPECT_TRUE(const_map_.end() == const_map_.cend());
+}
+
+TEST_F(MapImplTest, GetReferenceFromIterator) {
+  for (int i = 0; i < 10; i++) {
+    map_[i] = i;
+  }
+
+  for (Map<int32, int32>::const_iterator it = map_.cbegin();
+       it != map_.cend();) {
+    Map<int32, int32>::const_reference entry = *it++;
+    EXPECT_EQ(entry.first, entry.second);
+  }
+
+  for (Map<int32, int32>::const_iterator it = const_map_.begin();
+       it != const_map_.end();) {
+    Map<int32, int32>::const_reference entry = *it++;
+    EXPECT_EQ(entry.first, entry.second);
+  }
+
+  for (Map<int32, int32>::iterator it = map_.begin(); it != map_.end();) {
+    Map<int32, int32>::reference entry = *it++;
+    EXPECT_EQ(entry.first + 1, ++entry.second);
+  }
+}
+
+TEST_F(MapImplTest, InsertSingle) {
+  int32 key = 0;
+  int32 value1 = 100;
+  int32 value2 = 101;
+
+  // Insert a non-existed key.
+  std::pair<Map<int32, int32>::iterator, bool> result1 =
+      map_.insert(Map<int32, int32>::value_type(key, value1));
+  ExpectSingleElement(key, value1);
+
+  Map<int32, int32>::iterator it1 = result1.first;
+  EXPECT_EQ(key, it1->first);
+  EXPECT_EQ(value1, it1->second);
+  EXPECT_TRUE(result1.second);
+
+  // Insert an existed key.
+  std::pair<Map<int32, int32>::iterator, bool> result2 =
+      map_.insert(Map<int32, int32>::value_type(key, value2));
+  ExpectSingleElement(key, value1);
+
+  Map<int32, int32>::iterator it2 = result2.first;
+  EXPECT_TRUE(it1 == it2);
+  EXPECT_FALSE(result2.second);
+}
+
+TEST_F(MapImplTest, InsertByIterator) {
+  int32 key1 = 0;
+  int32 key2 = 1;
+  int32 value1a = 100;
+  int32 value1b = 101;
+  int32 value2a = 200;
+  int32 value2b = 201;
+
+  std::map<int32, int32> map1;
+  map1[key1] = value1a;
+  map1[key2] = value2a;
+
+  map_.insert(map1.begin(), map1.end());
+  ExpectElements(map1);
+
+  std::map<int32, int32> map2;
+  map2[key1] = value1b;
+  map2[key2] = value2b;
+
+  map_.insert(map2.begin(), map2.end());
+  ExpectElements(map1);
+}
+
+TEST_F(MapImplTest, EraseSingleByKey) {
+  int32 key = 0;
+  int32 value = 100;
+
+  map_[key] = value;
+  ExpectSingleElement(key, value);
+
+  // Erase an existing key.
+  EXPECT_EQ(1, map_.erase(key));
+  EXPECT_TRUE(map_.empty());
+  EXPECT_EQ(0, map_.size());
+  EXPECT_TRUE(map_.end() == map_.find(key));
+  EXPECT_TRUE(map_.begin() == map_.end());
+
+  // Erase a non-existing key.
+  EXPECT_EQ(0, map_.erase(key));
+}
+
+TEST_F(MapImplTest, EraseMutipleByKey) {
+  // erase in one specific order to trigger corner cases
+  for (int i = 0; i < 5; i++) {
+    map_[i] = i;
+  }
+
+  map_.erase(0);
+  EXPECT_EQ(4, map_.size());
+  EXPECT_TRUE(map_.end() == map_.find(0));
+
+  map_.erase(1);
+  EXPECT_EQ(3, map_.size());
+  EXPECT_TRUE(map_.end() == map_.find(1));
+
+  map_.erase(3);
+  EXPECT_EQ(2, map_.size());
+  EXPECT_TRUE(map_.end() == map_.find(3));
+
+  map_.erase(4);
+  EXPECT_EQ(1, map_.size());
+  EXPECT_TRUE(map_.end() == map_.find(4));
+
+  map_.erase(2);
+  EXPECT_EQ(0, map_.size());
+  EXPECT_TRUE(map_.end() == map_.find(2));
+}
+
+TEST_F(MapImplTest, EraseSingleByIterator) {
+  int32 key = 0;
+  int32 value = 100;
+
+  map_[key] = value;
+  ExpectSingleElement(key, value);
+
+  Map<int32, int32>::iterator it = map_.find(key);
+  map_.erase(it);
+  EXPECT_TRUE(map_.empty());
+  EXPECT_EQ(0, map_.size());
+  EXPECT_TRUE(map_.end() == map_.find(key));
+  EXPECT_TRUE(map_.begin() == map_.end());
+}
+
+TEST_F(MapImplTest, ValidIteratorAfterErase) {
+  for (int i = 0; i < 10; i++) {
+    map_[i] = i;
+  }
+
+  int count = 0;
+
+  for (Map<int32, int32>::iterator it = map_.begin(); it != map_.end();) {
+    count++;
+    if (it->first % 2 == 1) {
+      map_.erase(it++);
+    } else {
+      ++it;
+    }
+  }
+
+  EXPECT_EQ(10, count);
+  EXPECT_EQ(5, map_.size());
+}
+
+TEST_F(MapImplTest, EraseByIterator) {
+  int32 key1 = 0;
+  int32 key2 = 1;
+  int32 value1 = 100;
+  int32 value2 = 101;
+
+  std::map<int32, int32> map;
+  map[key1] = value1;
+  map[key2] = value2;
+
+  map_.insert(map.begin(), map.end());
+  ExpectElements(map);
+
+  map_.erase(map_.begin(), map_.end());
+  EXPECT_TRUE(map_.empty());
+  EXPECT_EQ(0, map_.size());
+  EXPECT_TRUE(map_.end() == map_.find(key1));
+  EXPECT_TRUE(map_.end() == map_.find(key2));
+  EXPECT_TRUE(map_.begin() == map_.end());
+}
+
+TEST_F(MapImplTest, Clear) {
+  int32 key = 0;
+  int32 value = 100;
+
+  map_[key] = value;
+  ExpectSingleElement(key, value);
+
+  map_.clear();
+
+  EXPECT_TRUE(map_.empty());
+  EXPECT_EQ(0, map_.size());
+  EXPECT_TRUE(map_.end() == map_.find(key));
+  EXPECT_TRUE(map_.begin() == map_.end());
+}
+
+TEST_F(MapImplTest, CopyConstructor) {
+  int32 key1 = 0;
+  int32 key2 = 1;
+  int32 value1 = 100;
+  int32 value2 = 101;
+
+  std::map<int32, int32> map;
+  map[key1] = value1;
+  map[key2] = value2;
+
+  map_.insert(map.begin(), map.end());
+
+  Map<int32, int32> other(map_);
+
+  EXPECT_EQ(2, other.size());
+  EXPECT_EQ(value1, other.at(key1));
+  EXPECT_EQ(value2, other.at(key2));
+}
+
+TEST_F(MapImplTest, Assigner) {
+  int32 key1 = 0;
+  int32 key2 = 1;
+  int32 value1 = 100;
+  int32 value2 = 101;
+
+  std::map<int32, int32> map;
+  map[key1] = value1;
+  map[key2] = value2;
+
+  map_.insert(map.begin(), map.end());
+
+  Map<int32, int32> other;
+  other = map_;
+
+  EXPECT_EQ(2, other.size());
+  EXPECT_EQ(value1, other.at(key1));
+  EXPECT_EQ(value2, other.at(key2));
+}
+
+TEST_F(MapImplTest, Rehash) {
+  const int test_size = 50;
+  std::map<int32, int32> reference_map;
+  for (int i = 0; i < test_size; i++) {
+    reference_map[i] = i;
+  }
+  for (int i = 0; i < test_size; i++) {
+    map_[i] = reference_map[i];
+    EXPECT_EQ(reference_map[i], map_[i]);
+  }
+  for (int i = 0; i < test_size; i++) {
+    map_.erase(i);
+    EXPECT_TRUE(map_.end() == map_.find(i));
+  }
+  EXPECT_TRUE(map_.empty());
+}
+
+// Map Field Reflection Test ========================================
+
+static int Func(int i, int j) {
+  return i * j;
+}
+
+static string StrFunc(int i, int j) {
+  string str;
+  SStringPrintf(&str, "%d", Func(i, j));
+  return str;
+}
+
+static int Int(const string& value) {
+  int result = 0;
+  std::istringstream(value) >> result;
+  return result;
+}
+
+class MapFieldReflectionTest : public testing::Test {
+ protected:
+  typedef FieldDescriptor FD;
+};
+
+TEST_F(MapFieldReflectionTest, RegularFields) {
+  TestMap message;
+  const Reflection* refl = message.GetReflection();
+  const Descriptor* desc = message.GetDescriptor();
+
+  Map<int32, int32>* map_int32_int32 = message.mutable_map_int32_int32();
+  Map<int32, double>* map_int32_double = message.mutable_map_int32_double();
+  Map<string, string>* map_string_string = message.mutable_map_string_string();
+  Map<int32, ForeignMessage>* map_int32_foreign_message =
+      message.mutable_map_int32_foreign_message();
+
+  for (int i = 0; i < 10; ++i) {
+    (*map_int32_int32)[i] = Func(i, 1);
+    (*map_int32_double)[i] = Func(i, 2);
+    (*map_string_string)[StrFunc(i, 1)] = StrFunc(i, 5);
+    (*map_int32_foreign_message)[i].set_c(Func(i, 6));
+  }
+
+  // Get FieldDescriptors for all the fields of interest.
+  const FieldDescriptor* fd_map_int32_int32 =
+      desc->FindFieldByName("map_int32_int32");
+  const FieldDescriptor* fd_map_int32_double =
+      desc->FindFieldByName("map_int32_double");
+  const FieldDescriptor* fd_map_string_string =
+      desc->FindFieldByName("map_string_string");
+  const FieldDescriptor* fd_map_int32_foreign_message =
+      desc->FindFieldByName("map_int32_foreign_message");
+
+  const FieldDescriptor* fd_map_int32_in32_key =
+      fd_map_int32_int32->message_type()->FindFieldByName("key");
+  const FieldDescriptor* fd_map_int32_in32_value =
+      fd_map_int32_int32->message_type()->FindFieldByName("value");
+  const FieldDescriptor* fd_map_int32_double_key =
+      fd_map_int32_double->message_type()->FindFieldByName("key");
+  const FieldDescriptor* fd_map_int32_double_value =
+      fd_map_int32_double->message_type()->FindFieldByName("value");
+  const FieldDescriptor* fd_map_string_string_key =
+      fd_map_string_string->message_type()->FindFieldByName("key");
+  const FieldDescriptor* fd_map_string_string_value =
+      fd_map_string_string->message_type()->FindFieldByName("value");
+  const FieldDescriptor* fd_map_int32_foreign_message_key =
+      fd_map_int32_foreign_message->message_type()->FindFieldByName("key");
+  const FieldDescriptor* fd_map_int32_foreign_message_value =
+      fd_map_int32_foreign_message->message_type()->FindFieldByName("value");
+
+  // Get RepeatedPtrField objects for all fields of interest.
+  const RepeatedPtrField<Message>& mf_int32_int32 =
+      refl->GetRepeatedPtrField<Message>(message, fd_map_int32_int32);
+  const RepeatedPtrField<Message>& mf_int32_double =
+      refl->GetRepeatedPtrField<Message>(message, fd_map_int32_double);
+  const RepeatedPtrField<Message>& mf_string_string =
+      refl->GetRepeatedPtrField<Message>(message, fd_map_string_string);
+  const RepeatedPtrField<Message>&
+      mf_int32_foreign_message =
+          refl->GetRepeatedPtrField<Message>(
+              message, fd_map_int32_foreign_message);
+
+  // Get mutable RepeatedPtrField objects for all fields of interest.
+  RepeatedPtrField<Message>* mmf_int32_int32 =
+      refl->MutableRepeatedPtrField<Message>(&message, fd_map_int32_int32);
+  RepeatedPtrField<Message>* mmf_int32_double =
+      refl->MutableRepeatedPtrField<Message>(&message, fd_map_int32_double);
+  RepeatedPtrField<Message>* mmf_string_string =
+      refl->MutableRepeatedPtrField<Message>(&message, fd_map_string_string);
+  RepeatedPtrField<Message>* mmf_int32_foreign_message =
+      refl->MutableRepeatedPtrField<Message>(
+          &message, fd_map_int32_foreign_message);
+
+  // Make sure we can do gets through the RepeatedPtrField objects.
+  for (int i = 0; i < 10; ++i) {
+    {
+      // Check gets through const objects.
+      const Message& message_int32_int32 = mf_int32_int32.Get(i);
+      int32 key_int32_int32 = message_int32_int32.GetReflection()->GetInt32(
+          message_int32_int32, fd_map_int32_in32_key);
+      int32 value_int32_int32 = message_int32_int32.GetReflection()->GetInt32(
+          message_int32_int32, fd_map_int32_in32_value);
+      EXPECT_EQ(value_int32_int32, Func(key_int32_int32, 1));
+
+      const Message& message_int32_double = mf_int32_double.Get(i);
+      int32 key_int32_double = message_int32_double.GetReflection()->GetInt32(
+          message_int32_double, fd_map_int32_double_key);
+      double value_int32_double =
+          message_int32_double.GetReflection()->GetDouble(
+              message_int32_double, fd_map_int32_double_value);
+      EXPECT_EQ(value_int32_double, Func(key_int32_double, 2));
+
+      const Message& message_string_string = mf_string_string.Get(i);
+      string key_string_string =
+          message_string_string.GetReflection()->GetString(
+              message_string_string, fd_map_string_string_key);
+      string value_string_string =
+          message_string_string.GetReflection()->GetString(
+              message_string_string, fd_map_string_string_value);
+      EXPECT_EQ(value_string_string, StrFunc(Int(key_string_string), 5));
+
+      const Message& message_int32_message = mf_int32_foreign_message.Get(i);
+      int32 key_int32_message = message_int32_message.GetReflection()->GetInt32(
+          message_int32_message, fd_map_int32_foreign_message_key);
+      const ForeignMessage& value_int32_message =
+          down_cast<const ForeignMessage&>(
+              message_int32_message.GetReflection()
+                  ->GetMessage(message_int32_message,
+                               fd_map_int32_foreign_message_value));
+      EXPECT_EQ(value_int32_message.c(), Func(key_int32_message, 6));
+    }
+
+    {
+      // Check gets through mutable objects.
+      const Message& message_int32_int32 = mmf_int32_int32->Get(i);
+      int32 key_int32_int32 = message_int32_int32.GetReflection()->GetInt32(
+          message_int32_int32, fd_map_int32_in32_key);
+      int32 value_int32_int32 = message_int32_int32.GetReflection()->GetInt32(
+          message_int32_int32, fd_map_int32_in32_value);
+      EXPECT_EQ(value_int32_int32, Func(key_int32_int32, 1));
+
+      const Message& message_int32_double = mmf_int32_double->Get(i);
+      int32 key_int32_double = message_int32_double.GetReflection()->GetInt32(
+          message_int32_double, fd_map_int32_double_key);
+      double value_int32_double =
+          message_int32_double.GetReflection()->GetDouble(
+              message_int32_double, fd_map_int32_double_value);
+      EXPECT_EQ(value_int32_double, Func(key_int32_double, 2));
+
+      const Message& message_string_string = mmf_string_string->Get(i);
+      string key_string_string =
+          message_string_string.GetReflection()->GetString(
+              message_string_string, fd_map_string_string_key);
+      string value_string_string =
+          message_string_string.GetReflection()->GetString(
+              message_string_string, fd_map_string_string_value);
+      EXPECT_EQ(value_string_string, StrFunc(Int(key_string_string), 5));
+
+      const Message& message_int32_message = mmf_int32_foreign_message->Get(i);
+      int32 key_int32_message = message_int32_message.GetReflection()->GetInt32(
+          message_int32_message, fd_map_int32_foreign_message_key);
+      const ForeignMessage& value_int32_message =
+          down_cast<const ForeignMessage&>(
+              message_int32_message.GetReflection()
+                  ->GetMessage(message_int32_message,
+                               fd_map_int32_foreign_message_value));
+      EXPECT_EQ(value_int32_message.c(), Func(key_int32_message, 6));
+    }
+  }
+
+  // Do sets through the RepeatedPtrField objects.
+  for (int i = 0; i < 10; i++) {
+    {
+      Message* message_int32_int32 = mmf_int32_int32->Mutable(i);
+      int32 key_int32_int32 = message_int32_int32->GetReflection()->GetInt32(
+          *message_int32_int32, fd_map_int32_in32_key);
+      message_int32_int32->GetReflection()->SetInt32(message_int32_int32,
+                                                     fd_map_int32_in32_value,
+                                                     Func(key_int32_int32, -1));
+
+      Message* message_int32_double = mmf_int32_double->Mutable(i);
+      int32 key_int32_double = message_int32_double->GetReflection()->GetInt32(
+          *message_int32_double, fd_map_int32_double_key);
+      message_int32_double->GetReflection()->SetDouble(
+          message_int32_double, fd_map_int32_double_value,
+          Func(key_int32_double, -2));
+
+      Message* message_string_string = mmf_string_string->Mutable(i);
+      string key_string_string =
+          message_string_string->GetReflection()->GetString(
+              *message_string_string, fd_map_string_string_key);
+      message_string_string->GetReflection()->SetString(
+          message_string_string, fd_map_string_string_value,
+          StrFunc(Int(key_string_string), -5));
+
+      Message* message_int32_message = mmf_int32_foreign_message->Mutable(i);
+      int32 key_int32_message =
+          message_int32_message->GetReflection()->GetInt32(
+              *message_int32_message, fd_map_int32_foreign_message_key);
+      ForeignMessage* value_int32_message = down_cast<ForeignMessage*>(
+          message_int32_message->GetReflection()
+              ->MutableMessage(message_int32_message,
+                               fd_map_int32_foreign_message_value));
+      value_int32_message->set_c(Func(key_int32_message, -6));
+    }
+  }
+
+  // Check gets through mutable objects.
+  for (int i = 0; i < 10; i++) {
+    EXPECT_EQ(Func(i, -1), message.map_int32_int32().at(i));
+    EXPECT_EQ(Func(i, -2), message.map_int32_double().at(i));
+    EXPECT_EQ(StrFunc(i, -5), message.map_string_string().at(StrFunc(i, 1)));
+    EXPECT_EQ(Func(i, -6), message.map_int32_foreign_message().at(i).c());
+  }
+}
+
+TEST_F(MapFieldReflectionTest, RepeatedFieldRefForRegularFields) {
+  TestMap message;
+  const Reflection* refl = message.GetReflection();
+  const Descriptor* desc = message.GetDescriptor();
+
+  Map<int32, int32>* map_int32_int32 = message.mutable_map_int32_int32();
+  Map<int32, double>* map_int32_double = message.mutable_map_int32_double();
+  Map<string, string>* map_string_string = message.mutable_map_string_string();
+  Map<int32, ForeignMessage>* map_int32_foreign_message =
+      message.mutable_map_int32_foreign_message();
+
+  for (int i = 0; i < 10; ++i) {
+    (*map_int32_int32)[i] = Func(i, 1);
+    (*map_int32_double)[i] = Func(i, 2);
+    (*map_string_string)[StrFunc(i, 1)] = StrFunc(i, 5);
+    (*map_int32_foreign_message)[i].set_c(Func(i, 6));
+  }
+
+  // Get FieldDescriptors for all the fields of interest.
+  const FieldDescriptor* fd_map_int32_int32 =
+      desc->FindFieldByName("map_int32_int32");
+  const FieldDescriptor* fd_map_int32_double =
+      desc->FindFieldByName("map_int32_double");
+  const FieldDescriptor* fd_map_string_string =
+      desc->FindFieldByName("map_string_string");
+  const FieldDescriptor* fd_map_int32_foreign_message =
+      desc->FindFieldByName("map_int32_foreign_message");
+
+  const FieldDescriptor* fd_map_int32_in32_key =
+      fd_map_int32_int32->message_type()->FindFieldByName("key");
+  const FieldDescriptor* fd_map_int32_in32_value =
+      fd_map_int32_int32->message_type()->FindFieldByName("value");
+  const FieldDescriptor* fd_map_int32_double_key =
+      fd_map_int32_double->message_type()->FindFieldByName("key");
+  const FieldDescriptor* fd_map_int32_double_value =
+      fd_map_int32_double->message_type()->FindFieldByName("value");
+  const FieldDescriptor* fd_map_string_string_key =
+      fd_map_string_string->message_type()->FindFieldByName("key");
+  const FieldDescriptor* fd_map_string_string_value =
+      fd_map_string_string->message_type()->FindFieldByName("value");
+  const FieldDescriptor* fd_map_int32_foreign_message_key =
+      fd_map_int32_foreign_message->message_type()->FindFieldByName("key");
+  const FieldDescriptor* fd_map_int32_foreign_message_value =
+      fd_map_int32_foreign_message->message_type()->FindFieldByName("value");
+
+  // Get RepeatedFieldRef objects for all fields of interest.
+  const RepeatedFieldRef<Message> mf_int32_int32 =
+      refl->GetRepeatedFieldRef<Message>(message, fd_map_int32_int32);
+  const RepeatedFieldRef<Message> mf_int32_double =
+      refl->GetRepeatedFieldRef<Message>(message, fd_map_int32_double);
+  const RepeatedFieldRef<Message> mf_string_string =
+      refl->GetRepeatedFieldRef<Message>(message, fd_map_string_string);
+  const RepeatedFieldRef<Message> mf_int32_foreign_message =
+      refl->GetRepeatedFieldRef<Message>(message, fd_map_int32_foreign_message);
+
+  // Get mutable RepeatedFieldRef objects for all fields of interest.
+  const MutableRepeatedFieldRef<Message> mmf_int32_int32 =
+      refl->GetMutableRepeatedFieldRef<Message>(&message, fd_map_int32_int32);
+  const MutableRepeatedFieldRef<Message> mmf_int32_double =
+      refl->GetMutableRepeatedFieldRef<Message>(&message, fd_map_int32_double);
+  const MutableRepeatedFieldRef<Message> mmf_string_string =
+      refl->GetMutableRepeatedFieldRef<Message>(&message, fd_map_string_string);
+  const MutableRepeatedFieldRef<Message>
+      mmf_int32_foreign_message =
+          refl->GetMutableRepeatedFieldRef<Message>(
+              &message, fd_map_int32_foreign_message);
+
+  // Get entry default instances
+  google::protobuf::scoped_ptr<Message> entry_int32_int32(
+      MessageFactory::generated_factory()
+          ->GetPrototype(fd_map_int32_int32->message_type())
+          ->New());
+  google::protobuf::scoped_ptr<Message> entry_int32_double(
+      MessageFactory::generated_factory()
+          ->GetPrototype(fd_map_int32_double->message_type())
+          ->New());
+  google::protobuf::scoped_ptr<Message> entry_string_string(
+      MessageFactory::generated_factory()
+          ->GetPrototype(fd_map_string_string->message_type())
+          ->New());
+  google::protobuf::scoped_ptr<Message> entry_int32_foreign_message(
+      MessageFactory::generated_factory()
+          ->GetPrototype(fd_map_int32_foreign_message->message_type())
+          ->New());
+
+  EXPECT_EQ(10, mf_int32_int32.size());
+  EXPECT_EQ(10, mmf_int32_int32.size());
+  EXPECT_EQ(10, mf_int32_double.size());
+  EXPECT_EQ(10, mmf_int32_double.size());
+  EXPECT_EQ(10, mf_string_string.size());
+  EXPECT_EQ(10, mmf_string_string.size());
+  EXPECT_EQ(10, mf_int32_foreign_message.size());
+  EXPECT_EQ(10, mmf_int32_foreign_message.size());
+
+  EXPECT_FALSE(mf_int32_int32.empty());
+  EXPECT_FALSE(mmf_int32_int32.empty());
+  EXPECT_FALSE(mf_int32_double.empty());
+  EXPECT_FALSE(mmf_int32_double.empty());
+  EXPECT_FALSE(mf_string_string.empty());
+  EXPECT_FALSE(mmf_string_string.empty());
+  EXPECT_FALSE(mf_int32_foreign_message.empty());
+  EXPECT_FALSE(mmf_int32_foreign_message.empty());
+
+  // Make sure we can do gets through the RepeatedFieldRef objects.
+  for (int i = 0; i < 10; ++i) {
+    {
+      // Check gets through const objects.
+      const Message& message_int32_int32 =
+          mf_int32_int32.Get(i, entry_int32_int32.get());
+      int32 key_int32_int32 = message_int32_int32.GetReflection()->GetInt32(
+          message_int32_int32, fd_map_int32_in32_key);
+      int32 value_int32_int32 = message_int32_int32.GetReflection()->GetInt32(
+          message_int32_int32, fd_map_int32_in32_value);
+      EXPECT_EQ(value_int32_int32, Func(key_int32_int32, 1));
+
+      const Message& message_int32_double =
+          mf_int32_double.Get(i, entry_int32_double.get());
+      int32 key_int32_double = message_int32_double.GetReflection()->GetInt32(
+          message_int32_double, fd_map_int32_double_key);
+      double value_int32_double =
+          message_int32_double.GetReflection()->GetDouble(
+              message_int32_double, fd_map_int32_double_value);
+      EXPECT_EQ(value_int32_double, Func(key_int32_double, 2));
+
+      const Message& message_string_string =
+          mf_string_string.Get(i, entry_string_string.get());
+      string key_string_string =
+          message_string_string.GetReflection()->GetString(
+              message_string_string, fd_map_string_string_key);
+      string value_string_string =
+          message_string_string.GetReflection()->GetString(
+              message_string_string, fd_map_string_string_value);
+      EXPECT_EQ(value_string_string, StrFunc(Int(key_string_string), 5));
+
+      const Message& message_int32_message =
+          mf_int32_foreign_message.Get(i, entry_int32_foreign_message.get());
+      int32 key_int32_message = message_int32_message.GetReflection()->GetInt32(
+          message_int32_message, fd_map_int32_foreign_message_key);
+      const ForeignMessage& value_int32_message =
+          down_cast<const ForeignMessage&>(
+              message_int32_message.GetReflection()
+                  ->GetMessage(message_int32_message,
+                               fd_map_int32_foreign_message_value));
+      EXPECT_EQ(value_int32_message.c(), Func(key_int32_message, 6));
+    }
+
+    {
+      // Check gets through mutable objects.
+      const Message& message_int32_int32 =
+          mmf_int32_int32.Get(i, entry_int32_int32.get());
+      int32 key_int32_int32 = message_int32_int32.GetReflection()->GetInt32(
+          message_int32_int32, fd_map_int32_in32_key);
+      int32 value_int32_int32 = message_int32_int32.GetReflection()->GetInt32(
+          message_int32_int32, fd_map_int32_in32_value);
+      EXPECT_EQ(value_int32_int32, Func(key_int32_int32, 1));
+
+      const Message& message_int32_double =
+          mmf_int32_double.Get(i, entry_int32_double.get());
+      int32 key_int32_double = message_int32_double.GetReflection()->GetInt32(
+          message_int32_double, fd_map_int32_double_key);
+      double value_int32_double =
+          message_int32_double.GetReflection()->GetDouble(
+              message_int32_double, fd_map_int32_double_value);
+      EXPECT_EQ(value_int32_double, Func(key_int32_double, 2));
+
+      const Message& message_string_string =
+          mmf_string_string.Get(i, entry_string_string.get());
+      string key_string_string =
+          message_string_string.GetReflection()->GetString(
+              message_string_string, fd_map_string_string_key);
+      string value_string_string =
+          message_string_string.GetReflection()->GetString(
+              message_string_string, fd_map_string_string_value);
+      EXPECT_EQ(value_string_string, StrFunc(Int(key_string_string), 5));
+
+      const Message& message_int32_message =
+          mmf_int32_foreign_message.Get(i, entry_int32_foreign_message.get());
+      int32 key_int32_message = message_int32_message.GetReflection()->GetInt32(
+          message_int32_message, fd_map_int32_foreign_message_key);
+      const ForeignMessage& value_int32_message =
+          down_cast<const ForeignMessage&>(
+              message_int32_message.GetReflection()
+                  ->GetMessage(message_int32_message,
+                               fd_map_int32_foreign_message_value));
+      EXPECT_EQ(value_int32_message.c(), Func(key_int32_message, 6));
+    }
+  }
+
+  // Make sure we can do sets through the RepeatedFieldRef objects.
+  for (int i = 0; i < 10; i++) {
+    const Message& message_int32_int32 =
+        mmf_int32_int32.Get(i, entry_int32_int32.get());
+    int key = message_int32_int32.GetReflection()->GetInt32(
+        message_int32_int32, fd_map_int32_in32_key);
+
+    entry_int32_int32->GetReflection()->SetInt32(
+        entry_int32_int32.get(), fd_map_int32_int32->message_type()->field(0),
+        key);
+    entry_int32_int32->GetReflection()->SetInt32(
+        entry_int32_int32.get(), fd_map_int32_int32->message_type()->field(1),
+        Func(key, -1));
+    entry_int32_double->GetReflection()->SetInt32(
+        entry_int32_double.get(), fd_map_int32_double->message_type()->field(0),
+        key);
+    entry_int32_double->GetReflection()->SetDouble(
+        entry_int32_double.get(), fd_map_int32_double->message_type()->field(1),
+        Func(key, -2));
+    entry_string_string->GetReflection()->SetString(
+        entry_string_string.get(), fd_map_string_string->message_type()->field(0),
+        StrFunc(key, 1));
+    entry_string_string->GetReflection()->SetString(
+        entry_string_string.get(), fd_map_string_string->message_type()->field(1),
+        StrFunc(key, -5));
+    entry_int32_foreign_message->GetReflection()->SetInt32(
+        entry_int32_foreign_message.get(),
+        fd_map_int32_foreign_message->message_type()->field(0),
+        key);
+    Message* value_message =
+        entry_int32_foreign_message->GetReflection()->MutableMessage(
+            entry_int32_foreign_message.get(),
+            fd_map_int32_foreign_message->message_type()->field(1));
+    value_message->GetReflection()->SetInt32(
+        value_message, value_message->GetDescriptor()->FindFieldByName("c"),
+        Func(key, -6));
+
+    mmf_int32_int32.Set(i, *entry_int32_int32.get());
+    mmf_int32_double.Set(i, *entry_int32_double.get());
+    mmf_string_string.Set(i, *entry_string_string.get());
+    mmf_int32_foreign_message.Set(i, *entry_int32_foreign_message.get());
+  }
+
+  for (int i = 0; i < 10; i++) {
+    EXPECT_EQ(Func(i, -1), message.map_int32_int32().at(i));
+    EXPECT_EQ(Func(i, -2), message.map_int32_double().at(i));
+    EXPECT_EQ(StrFunc(i, -5), message.map_string_string().at(StrFunc(i, 1)));
+    EXPECT_EQ(Func(i, -6), message.map_int32_foreign_message().at(i).c());
+  }
+
+  // Test iterators.
+  {
+    int index = 0;
+    hash_map<int32, int32> result;
+    for (RepeatedFieldRef<Message>::iterator it = mf_int32_int32.begin();
+         it != mf_int32_int32.end(); ++it) {
+      const Message& message = *it;
+      int32 key =
+          message.GetReflection()->GetInt32(message, fd_map_int32_in32_key);
+      int32 value =
+          message.GetReflection()->GetInt32(message, fd_map_int32_in32_value);
+      result[key] = value;
+      ++index;
+    }
+    EXPECT_EQ(10, index);
+    for (hash_map<int32, int32>::const_iterator it = result.begin();
+         it != result.end(); ++it) {
+      EXPECT_EQ(message.map_int32_int32().at(it->first), it->second);
+    }
+  }
+
+  {
+    int index = 0;
+    hash_map<int32, double> result;
+    for (RepeatedFieldRef<Message>::iterator it = mf_int32_double.begin();
+         it != mf_int32_double.end(); ++it) {
+      const Message& message = *it;
+      int32 key =
+          message.GetReflection()->GetInt32(message, fd_map_int32_double_key);
+      double value = message.GetReflection()->GetDouble(
+          message, fd_map_int32_double_value);
+      result[key] = value;
+      ++index;
+    }
+    EXPECT_EQ(10, index);
+    for (hash_map<int32, double>::const_iterator it = result.begin();
+         it != result.end(); ++it) {
+      EXPECT_EQ(message.map_int32_double().at(it->first), it->second);
+    }
+  }
+
+  {
+    int index = 0;
+    hash_map<string, string> result;
+    for (RepeatedFieldRef<Message>::iterator it = mf_string_string.begin();
+         it != mf_string_string.end(); ++it) {
+      const Message& message = *it;
+      string key =
+          message.GetReflection()->GetString(message, fd_map_string_string_key);
+      string value = message.GetReflection()->GetString(
+          message, fd_map_string_string_value);
+      result[key] = value;
+      ++index;
+    }
+    EXPECT_EQ(10, index);
+    for (hash_map<string, string>::const_iterator it = result.begin();
+         it != result.end(); ++it) {
+      EXPECT_EQ(message.map_string_string().at(it->first), it->second);
+    }
+  }
+
+  {
+    int index = 0;
+    std::map<int32, ForeignMessage> result;
+    for (RepeatedFieldRef<Message>::iterator it =
+             mf_int32_foreign_message.begin();
+         it != mf_int32_foreign_message.end(); ++it) {
+      const Message& message = *it;
+      int32 key = message.GetReflection()->GetInt32(
+          message, fd_map_int32_foreign_message_key);
+      const ForeignMessage& sub_message = down_cast<const ForeignMessage&>(
+          message.GetReflection()
+              ->GetMessage(message, fd_map_int32_foreign_message_value));
+      result[key].MergeFrom(sub_message);
+      ++index;
+    }
+    EXPECT_EQ(10, index);
+    for (std::map<int32, ForeignMessage>::const_iterator it = result.begin();
+         it != result.end(); ++it) {
+      EXPECT_EQ(message.map_int32_foreign_message().at(it->first).c(),
+                it->second.c());
+    }
+  }
+
+  // Test MutableRepeatedFieldRef::Add()
+  entry_int32_int32->GetReflection()->SetInt32(
+      entry_int32_int32.get(), fd_map_int32_int32->message_type()->field(0),
+      4321);
+  entry_int32_int32->GetReflection()->SetInt32(
+      entry_int32_int32.get(), fd_map_int32_int32->message_type()->field(1),
+      1234);
+  mmf_int32_int32.Add(*entry_int32_int32);
+  EXPECT_EQ(1234, message.map_int32_int32().at(4321));
+
+  entry_int32_double->GetReflection()->SetInt32(
+      entry_int32_double.get(), fd_map_int32_double->message_type()->field(0),
+      4321);
+  entry_int32_double->GetReflection()->SetDouble(
+      entry_int32_double.get(), fd_map_int32_double->message_type()->field(1),
+      1234.0);
+  mmf_int32_double.Add(*entry_int32_double);
+  EXPECT_EQ(1234.0, message.map_int32_double().at(4321));
+
+  entry_string_string->GetReflection()->SetString(
+      entry_string_string.get(),
+      fd_map_string_string->message_type()->field(0), "4321");
+  entry_string_string->GetReflection()->SetString(
+      entry_string_string.get(), fd_map_string_string->message_type()->field(1),
+      "1234");
+  mmf_string_string.Add(*entry_string_string);
+  EXPECT_EQ("1234", message.map_string_string().at("4321"));
+
+  entry_int32_foreign_message->GetReflection()->SetInt32(
+      entry_int32_foreign_message.get(),
+      fd_map_int32_foreign_message->message_type()->field(0), 4321);
+  Message* value_message =
+      entry_int32_foreign_message->GetReflection()->MutableMessage(
+          entry_int32_foreign_message.get(),
+          fd_map_int32_foreign_message->message_type()->field(1));
+  ForeignMessage foreign_message;
+  foreign_message.set_c(1234);
+  value_message->CopyFrom(foreign_message);
+
+  mmf_int32_foreign_message.Add(*entry_int32_foreign_message);
+  EXPECT_EQ(1234, message.map_int32_foreign_message().at(4321).c());
+
+  // Test MutableRepeatedFieldRef::RemoveLast()
+  mmf_int32_int32.RemoveLast();
+  mmf_int32_double.RemoveLast();
+  mmf_string_string.RemoveLast();
+  mmf_int32_foreign_message.RemoveLast();
+  EXPECT_EQ(10, message.map_int32_int32().size());
+  EXPECT_EQ(10, message.map_int32_double().size());
+  EXPECT_EQ(10, message.map_string_string().size());
+  EXPECT_EQ(10, message.map_int32_foreign_message().size());
+
+  // Test MutableRepeatedFieldRef::SwapElements()
+  {
+    const Message& message0a = mmf_int32_int32.Get(0, entry_int32_int32.get());
+    int32 int32_value0a =
+        message0a.GetReflection()->GetInt32(message0a, fd_map_int32_in32_value);
+    const Message& message9a = mmf_int32_int32.Get(9, entry_int32_int32.get());
+    int32 int32_value9a =
+        message9a.GetReflection()->GetInt32(message9a, fd_map_int32_in32_value);
+
+    mmf_int32_int32.SwapElements(0, 9);
+
+    const Message& message0b = mmf_int32_int32.Get(0, entry_int32_int32.get());
+    int32 int32_value0b =
+        message0b.GetReflection()->GetInt32(message0b, fd_map_int32_in32_value);
+    const Message& message9b = mmf_int32_int32.Get(9, entry_int32_int32.get());
+    int32 int32_value9b =
+        message9b.GetReflection()->GetInt32(message9b, fd_map_int32_in32_value);
+
+    EXPECT_EQ(int32_value9a, int32_value0b);
+    EXPECT_EQ(int32_value0a, int32_value9b);
+  }
+
+  {
+    const Message& message0a =
+        mmf_int32_double.Get(0, entry_int32_double.get());
+    double double_value0a = message0a.GetReflection()->GetDouble(
+        message0a, fd_map_int32_double_value);
+    const Message& message9a =
+        mmf_int32_double.Get(9, entry_int32_double.get());
+    double double_value9a = message9a.GetReflection()->GetDouble(
+        message9a, fd_map_int32_double_value);
+
+    mmf_int32_double.SwapElements(0, 9);
+
+    const Message& message0b =
+        mmf_int32_double.Get(0, entry_int32_double.get());
+    double double_value0b = message0b.GetReflection()->GetDouble(
+        message0b, fd_map_int32_double_value);
+    const Message& message9b =
+        mmf_int32_double.Get(9, entry_int32_double.get());
+    double double_value9b = message9b.GetReflection()->GetDouble(
+        message9b, fd_map_int32_double_value);
+
+    EXPECT_EQ(double_value9a, double_value0b);
+    EXPECT_EQ(double_value0a, double_value9b);
+  }
+
+  {
+    const Message& message0a =
+        mmf_string_string.Get(0, entry_string_string.get());
+    string string_value0a = message0a.GetReflection()->GetString(
+        message0a, fd_map_string_string_value);
+    const Message& message9a =
+        mmf_string_string.Get(9, entry_string_string.get());
+    string string_value9a = message9a.GetReflection()->GetString(
+        message9a, fd_map_string_string_value);
+
+    mmf_string_string.SwapElements(0, 9);
+
+    const Message& message0b =
+        mmf_string_string.Get(0, entry_string_string.get());
+    string string_value0b = message0b.GetReflection()->GetString(
+        message0b, fd_map_string_string_value);
+    const Message& message9b =
+        mmf_string_string.Get(9, entry_string_string.get());
+    string string_value9b = message9b.GetReflection()->GetString(
+        message9b, fd_map_string_string_value);
+
+    EXPECT_EQ(string_value9a, string_value0b);
+    EXPECT_EQ(string_value0a, string_value9b);
+  }
+
+  {
+    const Message& message0a =
+        mmf_int32_foreign_message.Get(0, entry_int32_foreign_message.get());
+    const ForeignMessage& sub_message0a = down_cast<const ForeignMessage&>(
+        message0a.GetReflection()
+            ->GetMessage(message0a, fd_map_int32_foreign_message_value));
+    int32 int32_value0a = sub_message0a.c();
+    const Message& message9a =
+        mmf_int32_foreign_message.Get(9, entry_int32_foreign_message.get());
+    const ForeignMessage& sub_message9a = down_cast<const ForeignMessage&>(
+        message9a.GetReflection()
+            ->GetMessage(message9a, fd_map_int32_foreign_message_value));
+    int32 int32_value9a = sub_message9a.c();
+
+    mmf_int32_foreign_message.SwapElements(0, 9);
+
+    const Message& message0b =
+        mmf_int32_foreign_message.Get(0, entry_int32_foreign_message.get());
+    const ForeignMessage& sub_message0b = down_cast<const ForeignMessage&>(
+        message0b.GetReflection()
+            ->GetMessage(message0b, fd_map_int32_foreign_message_value));
+    int32 int32_value0b = sub_message0b.c();
+    const Message& message9b =
+        mmf_int32_foreign_message.Get(9, entry_int32_foreign_message.get());
+    const ForeignMessage& sub_message9b = down_cast<const ForeignMessage&>(
+        message9b.GetReflection()
+            ->GetMessage(message9b, fd_map_int32_foreign_message_value));
+    int32 int32_value9b = sub_message9b.c();
+
+    EXPECT_EQ(int32_value9a, int32_value0b);
+    EXPECT_EQ(int32_value0a, int32_value9b);
+  }
+}
+
+TEST_F(MapFieldReflectionTest, RepeatedFieldRefMergeFromAndSwap) {
+  // Set-up message content.
+  TestMap m0, m1, m2;
+  for (int i = 0; i < 10; ++i) {
+    (*m0.mutable_map_int32_int32())[i] = Func(i, 1);
+    (*m0.mutable_map_int32_double())[i] = Func(i, 2);
+    (*m0.mutable_map_string_string())[StrFunc(i, 1)] = StrFunc(i, 5);
+    (*m0.mutable_map_int32_foreign_message())[i].set_c(Func(i, 6));
+    (*m1.mutable_map_int32_int32())[i + 10] = Func(i, 11);
+    (*m1.mutable_map_int32_double())[i + 10] = Func(i, 12);
+    (*m1.mutable_map_string_string())[StrFunc(i + 10, 1)] = StrFunc(i, 15);
+    (*m1.mutable_map_int32_foreign_message())[i + 10].set_c(Func(i, 16));
+    (*m2.mutable_map_int32_int32())[i + 20] = Func(i, 21);
+    (*m2.mutable_map_int32_double())[i + 20] = Func(i, 22);
+    (*m2.mutable_map_string_string())[StrFunc(i + 20, 1)] = StrFunc(i, 25);
+    (*m2.mutable_map_int32_foreign_message())[i + 20].set_c(Func(i, 26));
+  }
+
+  const Reflection* refl = m0.GetReflection();
+  const Descriptor* desc = m0.GetDescriptor();
+
+  // Get FieldDescriptors for all the fields of interest.
+  const FieldDescriptor* fd_map_int32_int32 =
+      desc->FindFieldByName("map_int32_int32");
+  const FieldDescriptor* fd_map_int32_double =
+      desc->FindFieldByName("map_int32_double");
+  const FieldDescriptor* fd_map_string_string =
+      desc->FindFieldByName("map_string_string");
+  const FieldDescriptor* fd_map_int32_foreign_message =
+      desc->FindFieldByName("map_int32_foreign_message");
+
+    // Get MutableRepeatedFieldRef objects for all fields of interest.
+  const MutableRepeatedFieldRef<Message> mmf_int32_int32 =
+      refl->GetMutableRepeatedFieldRef<Message>(
+          &m0, fd_map_int32_int32);
+  const MutableRepeatedFieldRef<Message> mmf_int32_double =
+      refl->GetMutableRepeatedFieldRef<Message>(
+          &m0, fd_map_int32_double);
+  const MutableRepeatedFieldRef<Message> mmf_string_string =
+      refl->GetMutableRepeatedFieldRef<Message>(
+          &m0, fd_map_string_string);
+  const MutableRepeatedFieldRef<Message>
+      mmf_int32_foreign_message =
+          refl->GetMutableRepeatedFieldRef<Message>(
+              &m0, fd_map_int32_foreign_message);
+
+  // Test MutableRepeatedRef::CopyFrom
+  mmf_int32_int32.CopyFrom(
+      refl->GetRepeatedFieldRef<Message>(
+          m1, fd_map_int32_int32));
+  mmf_int32_double.CopyFrom(
+      refl->GetRepeatedFieldRef<Message>(
+          m1, fd_map_int32_double));
+  mmf_string_string.CopyFrom(
+      refl->GetRepeatedFieldRef<Message>(
+          m1, fd_map_string_string));
+  mmf_int32_foreign_message.CopyFrom(
+      refl->GetRepeatedFieldRef<Message>(
+          m1, fd_map_int32_foreign_message));
+
+  for (int i = 0; i < 10; ++i) {
+    EXPECT_EQ(Func(i, 11), m0.map_int32_int32().at(i + 10));
+    EXPECT_EQ(Func(i, 12), m0.map_int32_double().at(i + 10));
+    EXPECT_EQ(StrFunc(i, 15), m0.map_string_string().at(StrFunc(i + 10, 1)));
+    EXPECT_EQ(Func(i, 16), m0.map_int32_foreign_message().at(i + 10).c());
+  }
+
+  // Test MutableRepeatedRef::MergeFrom
+  mmf_int32_int32.MergeFrom(
+      refl->GetRepeatedFieldRef<Message>(
+          m2, fd_map_int32_int32));
+  mmf_int32_double.MergeFrom(
+      refl->GetRepeatedFieldRef<Message>(
+          m2, fd_map_int32_double));
+  mmf_string_string.MergeFrom(
+      refl->GetRepeatedFieldRef<Message>(
+          m2, fd_map_string_string));
+  mmf_int32_foreign_message.MergeFrom(
+      refl->GetRepeatedFieldRef<Message>(
+          m2, fd_map_int32_foreign_message));
+  for (int i = 0; i < 10; ++i) {
+    EXPECT_EQ(Func(i, 21), m0.map_int32_int32().at(i + 20));
+    EXPECT_EQ(Func(i, 22), m0.map_int32_double().at(i + 20));
+    EXPECT_EQ(StrFunc(i, 25), m0.map_string_string().at(StrFunc(i + 20, 1)));
+    EXPECT_EQ(Func(i, 26), m0.map_int32_foreign_message().at(i + 20).c());
+  }
+
+  // Test MutableRepeatedRef::Swap
+  // Swap between m0 and m2.
+  mmf_int32_int32.Swap(
+      refl->GetMutableRepeatedFieldRef<Message>(
+          &m2, fd_map_int32_int32));
+  mmf_int32_double.Swap(
+      refl->GetMutableRepeatedFieldRef<Message>(
+          &m2, fd_map_int32_double));
+  mmf_string_string.Swap(
+      refl->GetMutableRepeatedFieldRef<Message>(
+          &m2, fd_map_string_string));
+  mmf_int32_foreign_message.Swap(
+      refl->GetMutableRepeatedFieldRef<Message>(
+          &m2, fd_map_int32_foreign_message));
+  for (int i = 0; i < 10; ++i) {
+    // Check the content of m0.
+    EXPECT_EQ(Func(i, 21), m0.map_int32_int32().at(i + 20));
+    EXPECT_EQ(Func(i, 22), m0.map_int32_double().at(i + 20));
+    EXPECT_EQ(StrFunc(i, 25), m0.map_string_string().at(StrFunc(i + 20, 1)));
+    EXPECT_EQ(Func(i, 26), m0.map_int32_foreign_message().at(i + 20).c());
+
+    // Check the content of m2.
+    EXPECT_EQ(Func(i, 11), m2.map_int32_int32().at(i + 10));
+    EXPECT_EQ(Func(i, 12), m2.map_int32_double().at(i + 10));
+    EXPECT_EQ(StrFunc(i, 15), m2.map_string_string().at(StrFunc(i + 10, 1)));
+    EXPECT_EQ(Func(i, 16), m2.map_int32_foreign_message().at(i + 10).c());
+    EXPECT_EQ(Func(i, 21), m2.map_int32_int32().at(i + 20));
+    EXPECT_EQ(Func(i, 22), m2.map_int32_double().at(i + 20));
+    EXPECT_EQ(StrFunc(i, 25), m2.map_string_string().at(StrFunc(i + 20, 1)));
+    EXPECT_EQ(Func(i, 26), m2.map_int32_foreign_message().at(i + 20).c());
+  }
+
+  // TODO(teboring): add test for duplicated key
+}
+
+// Generated Message Test ===========================================
+
+TEST(GeneratedMapFieldTest, Accessors) {
+  unittest::TestMap message;
+
+  MapTestUtil::SetMapFields(&message);
+  MapTestUtil::ExpectMapFieldsSet(message);
+
+  MapTestUtil::ModifyMapFields(&message);
+  MapTestUtil::ExpectMapFieldsModified(message);
+}
+
+TEST(GeneratedMapFieldTest, SetMapFieldsInitialized) {
+  unittest::TestMap message;
+
+  MapTestUtil::SetMapFieldsInitialized(&message);
+  MapTestUtil::ExpectMapFieldsSetInitialized(message);
+}
+
+TEST(GeneratedMapFieldTest, Proto2SetMapFieldsInitialized) {
+  unittest::TestEnumStartWithNonZeroMap message;
+  EXPECT_EQ(unittest::PROTO2_NON_ZERO_MAP_ENUM_FOO,
+            (*message.mutable_map_field())[0]);
+}
+
+TEST(GeneratedMapFieldTest, Clear) {
+  unittest::TestMap message;
+
+  MapTestUtil::SetMapFields(&message);
+  message.Clear();
+  MapTestUtil::ExpectClear(message);
+}
+
+TEST(GeneratedMapFieldTest, ClearMessageMap) {
+  unittest::TestMessageMap message;
+
+  // Creates a TestAllTypes with default value
+  TestUtil::ExpectClear((*message.mutable_map_int32_message())[0]);
+}
+
+TEST(GeneratedMapFieldTest, CopyFrom) {
+  unittest::TestMap message1, message2;
+
+  MapTestUtil::SetMapFields(&message1);
+  message2.CopyFrom(message1);
+  MapTestUtil::ExpectMapFieldsSet(message2);
+
+  // Copying from self should be a no-op.
+  message2.CopyFrom(message2);
+  MapTestUtil::ExpectMapFieldsSet(message2);
+}
+
+TEST(GeneratedMapFieldTest, CopyFromMessageMap) {
+  unittest::TestMessageMap message1, message2;
+
+  (*message1.mutable_map_int32_message())[0].add_repeated_int32(100);
+  (*message2.mutable_map_int32_message())[0].add_repeated_int32(101);
+
+  message1.CopyFrom(message2);
+
+  // Checks repeated field is overwritten.
+  EXPECT_EQ(1, message1.map_int32_message().at(0).repeated_int32_size());
+  EXPECT_EQ(101, message1.map_int32_message().at(0).repeated_int32(0));
+}
+
+TEST(GeneratedMapFieldTest, SwapWithEmpty) {
+  unittest::TestMap message1, message2;
+
+  MapTestUtil::SetMapFields(&message1);
+  MapTestUtil::ExpectMapFieldsSet(message1);
+  MapTestUtil::ExpectClear(message2);
+
+  message1.Swap(&message2);
+  MapTestUtil::ExpectMapFieldsSet(message2);
+  MapTestUtil::ExpectClear(message1);
+}
+
+TEST(GeneratedMapFieldTest, SwapWithSelf) {
+  unittest::TestMap message;
+
+  MapTestUtil::SetMapFields(&message);
+  MapTestUtil::ExpectMapFieldsSet(message);
+
+  message.Swap(&message);
+  MapTestUtil::ExpectMapFieldsSet(message);
+}
+
+TEST(GeneratedMapFieldTest, SwapWithOther) {
+  unittest::TestMap message1, message2;
+
+  MapTestUtil::SetMapFields(&message1);
+  MapTestUtil::SetMapFields(&message2);
+  MapTestUtil::ModifyMapFields(&message2);
+
+  message1.Swap(&message2);
+  MapTestUtil::ExpectMapFieldsModified(message1);
+  MapTestUtil::ExpectMapFieldsSet(message2);
+}
+
+TEST(GeneratedMapFieldTest, CopyConstructor) {
+  unittest::TestMap message1;
+  MapTestUtil::SetMapFields(&message1);
+
+  unittest::TestMap message2(message1);
+  MapTestUtil::ExpectMapFieldsSet(message2);
+}
+
+TEST(GeneratedMapFieldTest, CopyAssignmentOperator) {
+  unittest::TestMap message1;
+  MapTestUtil::SetMapFields(&message1);
+
+  unittest::TestMap message2;
+  message2 = message1;
+  MapTestUtil::ExpectMapFieldsSet(message2);
+
+  // Make sure that self-assignment does something sane.
+  message2.operator=(message2);
+  MapTestUtil::ExpectMapFieldsSet(message2);
+}
+
+#if !defined(PROTOBUF_TEST_NO_DESCRIPTORS) || \
+        !defined(GOOGLE_PROTOBUF_NO_RTTI)
+TEST(GeneratedMapFieldTest, UpcastCopyFrom) {
+  // Test the CopyFrom method that takes in the generic const Message&
+  // parameter.
+  unittest::TestMap message1, message2;
+
+  MapTestUtil::SetMapFields(&message1);
+
+  const Message* source = implicit_cast<const Message*>(&message1);
+  message2.CopyFrom(*source);
+
+  MapTestUtil::ExpectMapFieldsSet(message2);
+}
+#endif
+
+#ifndef PROTOBUF_TEST_NO_DESCRIPTORS
+
+TEST(GeneratedMapFieldTest, CopyFromDynamicMessage) {
+  // Test copying from a DynamicMessage, which must fall back to using
+  // reflection.
+  unittest::TestMap message2;
+
+  // Construct a new version of the dynamic message via the factory.
+  DynamicMessageFactory factory;
+  google::protobuf::scoped_ptr<Message> message1;
+  message1.reset(
+      factory.GetPrototype(unittest::TestMap::descriptor())->New());
+
+  MapTestUtil::MapReflectionTester reflection_tester(
+      unittest::TestMap::descriptor());
+  reflection_tester.SetMapFieldsViaReflection(message1.get());
+  reflection_tester.ExpectMapFieldsSetViaReflection(*message1);
+
+  message2.CopyFrom(*message1);
+  MapTestUtil::ExpectMapFieldsSet(message2);
+}
+
+TEST(GeneratedMapFieldTest, DynamicMessageCopyFrom) {
+  // Test copying to a DynamicMessage, which must fall back to using reflection.
+  unittest::TestMap message2;
+  MapTestUtil::SetMapFields(&message2);
+
+  // Construct a new version of the dynamic message via the factory.
+  DynamicMessageFactory factory;
+  google::protobuf::scoped_ptr<Message> message1;
+  message1.reset(
+      factory.GetPrototype(unittest::TestMap::descriptor())->New());
+
+  MapTestUtil::MapReflectionTester reflection_tester(
+      unittest::TestMap::descriptor());
+  message1->MergeFrom(message2);
+  reflection_tester.ExpectMapFieldsSetViaReflection(*message1);
+}
+
+#endif  // !PROTOBUF_TEST_NO_DESCRIPTORS
+
+TEST(GeneratedMapFieldTest, NonEmptyMergeFrom) {
+  unittest::TestMap message1, message2;
+
+  MapTestUtil::SetMapFields(&message1);
+
+  // This field will test merging into an empty spot.
+  (*message2.mutable_map_int32_int32())[1] = 1;
+  message1.mutable_map_int32_int32()->erase(1);
+
+  // This tests overwriting.
+  (*message2.mutable_map_int32_double())[1] = 1;
+  (*message1.mutable_map_int32_double())[1] = 2;
+
+  message1.MergeFrom(message2);
+  MapTestUtil::ExpectMapFieldsSet(message1);
+}
+
+TEST(GeneratedMapFieldTest, MergeFromMessageMap) {
+  unittest::TestMessageMap message1, message2;
+
+  (*message1.mutable_map_int32_message())[0].add_repeated_int32(100);
+  (*message2.mutable_map_int32_message())[0].add_repeated_int32(101);
+
+  message1.MergeFrom(message2);
+
+  // Checks repeated field is overwritten.
+  EXPECT_EQ(1, message1.map_int32_message().at(0).repeated_int32_size());
+  EXPECT_EQ(101, message1.map_int32_message().at(0).repeated_int32(0));
+}
+
+// Test the generated SerializeWithCachedSizesToArray()
+TEST(GeneratedMapFieldTest, SerializationToArray) {
+  unittest::TestMap message1, message2;
+  string data;
+  MapTestUtil::SetMapFields(&message1);
+  int size = message1.ByteSize();
+  data.resize(size);
+  uint8* start = reinterpret_cast<uint8*>(string_as_array(&data));
+  uint8* end = message1.SerializeWithCachedSizesToArray(start);
+  EXPECT_EQ(size, end - start);
+  EXPECT_TRUE(message2.ParseFromString(data));
+  MapTestUtil::ExpectMapFieldsSet(message2);
+}
+
+// Test the generated SerializeWithCachedSizes()
+TEST(GeneratedMapFieldTest, SerializationToStream) {
+  unittest::TestMap message1, message2;
+  MapTestUtil::SetMapFields(&message1);
+  int size = message1.ByteSize();
+  string data;
+  data.resize(size);
+  {
+    // Allow the output stream to buffer only one byte at a time.
+    io::ArrayOutputStream array_stream(string_as_array(&data), size, 1);
+    io::CodedOutputStream output_stream(&array_stream);
+    message1.SerializeWithCachedSizes(&output_stream);
+    EXPECT_FALSE(output_stream.HadError());
+    EXPECT_EQ(size, output_stream.ByteCount());
+  }
+  EXPECT_TRUE(message2.ParseFromString(data));
+  MapTestUtil::ExpectMapFieldsSet(message2);
+}
+
+
+TEST(GeneratedMapFieldTest, SameTypeMaps) {
+  const Descriptor* map1 = unittest::TestSameTypeMap::descriptor()
+                               ->FindFieldByName("map1")
+                               ->message_type();
+  const Descriptor* map2 = unittest::TestSameTypeMap::descriptor()
+                               ->FindFieldByName("map2")
+                               ->message_type();
+
+  const Message* map1_entry =
+      MessageFactory::generated_factory()->GetPrototype(map1);
+  const Message* map2_entry =
+      MessageFactory::generated_factory()->GetPrototype(map2);
+
+  EXPECT_EQ(map1, map1_entry->GetDescriptor());
+  EXPECT_EQ(map2, map2_entry->GetDescriptor());
+}
+
+TEST(GeneratedMapFieldTest, Proto2UnknownEnum) {
+  unittest::TestEnumMapPlusExtra from;
+  (*from.mutable_known_map_field())[0] = unittest::E_PROTO2_MAP_ENUM_FOO;
+  (*from.mutable_unknown_map_field())[0] = unittest::E_PROTO2_MAP_ENUM_EXTRA;
+  string data;
+  from.SerializeToString(&data);
+
+  unittest::TestEnumMap to;
+  EXPECT_TRUE(to.ParseFromString(data));
+  EXPECT_EQ(0, to.unknown_map_field().size());
+  const UnknownFieldSet& unknown_field_set =
+      to.GetReflection()->GetUnknownFields(to);
+  EXPECT_EQ(1, unknown_field_set.field_count());
+  EXPECT_EQ(1, to.known_map_field().size());
+  EXPECT_EQ(unittest::PROTO2_MAP_ENUM_FOO, to.known_map_field().at(0));
+
+  data.clear();
+  from.Clear();
+  to.SerializeToString(&data);
+  EXPECT_TRUE(from.ParseFromString(data));
+  EXPECT_EQ(0, from.GetReflection()->GetUnknownFields(from).field_count());
+  EXPECT_EQ(1, from.known_map_field().size());
+  EXPECT_EQ(unittest::E_PROTO2_MAP_ENUM_FOO, from.known_map_field().at(0));
+  EXPECT_EQ(1, from.unknown_map_field().size());
+  EXPECT_EQ(unittest::E_PROTO2_MAP_ENUM_EXTRA, from.unknown_map_field().at(0));
+}
+
+TEST(GeneratedMapFieldTest, StandardWireFormat) {
+  unittest::TestMap message;
+  string data = "\x0A\x04\x08\x01\x10\x01";
+
+  EXPECT_TRUE(message.ParseFromString(data));
+  EXPECT_EQ(1, message.map_int32_int32().size());
+  EXPECT_EQ(1, message.map_int32_int32().at(1));
+}
+
+TEST(GeneratedMapFieldTest, UnorderedWireFormat) {
+  unittest::TestMap message;
+
+  // put value before key in wire format
+  string data = "\x0A\x04\x10\x01\x08\x02";
+
+  EXPECT_TRUE(message.ParseFromString(data));
+  EXPECT_EQ(1, message.map_int32_int32().size());
+  EXPECT_EQ(1, message.map_int32_int32().at(2));
+}
+
+TEST(GeneratedMapFieldTest, DuplicatedKeyWireFormat) {
+  unittest::TestMap message;
+
+  // Two key fields in wire format
+  string data = "\x0A\x06\x08\x01\x08\x02\x10\x01";
+
+  EXPECT_TRUE(message.ParseFromString(data));
+  EXPECT_EQ(1, message.map_int32_int32().size());
+  EXPECT_EQ(1, message.map_int32_int32().at(2));
+}
+
+TEST(GeneratedMapFieldTest, DuplicatedValueWireFormat) {
+  unittest::TestMap message;
+
+  // Two value fields in wire format
+  string data = "\x0A\x06\x08\x01\x10\x01\x10\x02";
+
+  EXPECT_TRUE(message.ParseFromString(data));
+  EXPECT_EQ(1, message.map_int32_int32().size());
+  EXPECT_EQ(2, message.map_int32_int32().at(1));
+}
+
+TEST(GeneratedMapFieldTest, MissedKeyWireFormat) {
+  unittest::TestMap message;
+
+  // No key field in wire format
+  string data = "\x0A\x02\x10\x01";
+
+  EXPECT_TRUE(message.ParseFromString(data));
+  EXPECT_EQ(1, message.map_int32_int32().size());
+  EXPECT_EQ(1, message.map_int32_int32().at(0));
+}
+
+TEST(GeneratedMapFieldTest, MissedValueWireFormat) {
+  unittest::TestMap message;
+
+  // No value field in wire format
+  string data = "\x0A\x02\x08\x01";
+
+  EXPECT_TRUE(message.ParseFromString(data));
+  EXPECT_EQ(1, message.map_int32_int32().size());
+  EXPECT_EQ(0, message.map_int32_int32().at(1));
+}
+
+TEST(GeneratedMapFieldTest, UnknownFieldWireFormat) {
+  unittest::TestMap message;
+
+  // Unknown field in wire format
+  string data = "\x0A\x06\x08\x02\x10\x03\x18\x01";
+
+  EXPECT_TRUE(message.ParseFromString(data));
+  EXPECT_EQ(1, message.map_int32_int32().size());
+  EXPECT_EQ(3, message.map_int32_int32().at(2));
+}
+
+TEST(GeneratedMapFieldTest, CorruptedWireFormat) {
+  unittest::TestMap message;
+
+  // corrupted data in wire format
+  string data = "\x0A\x06\x08\x02\x11\x03";
+
+  EXPECT_FALSE(message.ParseFromString(data));
+}
+
+TEST(GeneratedMapFieldTest, MessageLiteMap) {
+  unittest::MapLite from, to;
+  (*from.mutable_map_field())[1] = 1;
+
+  string data;
+  from.SerializeToString(&data);
+  to.ParseFromString(data);
+
+  EXPECT_EQ(1, to.map_field().size());
+  EXPECT_EQ(1, to.map_field().at(1));
+}
+
+// Generated Message Reflection Test ================================
+
+TEST(GeneratedMapFieldReflectionTest, SpaceUsed) {
+  unittest::TestMap message;
+  MapTestUtil::MapReflectionTester reflection_tester(
+    unittest::TestMap::descriptor());
+  reflection_tester.SetMapFieldsViaReflection(&message);
+
+  EXPECT_LT(0, message.GetReflection()->SpaceUsed(message));
+}
+
+TEST(GeneratedMapFieldReflectionTest, Accessors) {
+  // Set every field to a unique value then go back and check all those
+  // values.
+  unittest::TestMap message;
+  MapTestUtil::MapReflectionTester reflection_tester(
+    unittest::TestMap::descriptor());
+  reflection_tester.SetMapFieldsViaReflection(&message);
+  MapTestUtil::ExpectMapFieldsSet(message);
+  reflection_tester.ExpectMapFieldsSetViaReflection(message);
+
+  reflection_tester.ModifyMapFieldsViaReflection(&message);
+  MapTestUtil::ExpectMapFieldsModified(message);
+}
+
+TEST(GeneratedMapFieldReflectionTest, Swap) {
+  unittest::TestMap message1;
+  unittest::TestMap message2;
+
+  MapTestUtil::SetMapFields(&message1);
+
+  const Reflection* reflection = message1.GetReflection();
+  reflection->Swap(&message1, &message2);
+
+  MapTestUtil::ExpectClear(message1);
+  MapTestUtil::ExpectMapFieldsSet(message2);
+}
+
+TEST(GeneratedMapFieldReflectionTest, SwapWithBothSet) {
+  unittest::TestMap message1;
+  unittest::TestMap message2;
+
+  MapTestUtil::SetMapFields(&message1);
+  MapTestUtil::SetMapFields(&message2);
+  MapTestUtil::ModifyMapFields(&message2);
+
+  const Reflection* reflection = message1.GetReflection();
+  reflection->Swap(&message1, &message2);
+
+  MapTestUtil::ExpectMapFieldsModified(message1);
+  MapTestUtil::ExpectMapFieldsSet(message2);
+}
+
+TEST(GeneratedMapFieldReflectionTest, SwapFields) {
+  unittest::TestMap message1;
+  unittest::TestMap message2;
+
+  MapTestUtil::SetMapFields(&message2);
+
+  vector<const FieldDescriptor*> fields;
+  const Reflection* reflection = message1.GetReflection();
+  reflection->ListFields(message2, &fields);
+  reflection->SwapFields(&message1, &message2, fields);
+
+  MapTestUtil::ExpectMapFieldsSet(message1);
+  MapTestUtil::ExpectClear(message2);
+}
+
+TEST(GeneratedMapFieldReflectionTest, ClearField) {
+  unittest::TestMap message;
+  MapTestUtil::SetMapFields(&message);
+  MapTestUtil::ExpectMapFieldsSet(message);
+
+  MapTestUtil::MapReflectionTester reflection_tester(
+      unittest::TestMap::descriptor());
+  reflection_tester.ClearMapFieldsViaReflection(&message);
+  MapTestUtil::ExpectClear(message);
+}
+
+TEST(GeneratedMapFieldReflectionTest, RemoveLast) {
+  unittest::TestMap message;
+  MapTestUtil::MapReflectionTester reflection_tester(
+      unittest::TestMap::descriptor());
+
+  MapTestUtil::SetMapFields(&message);
+  MapTestUtil::ExpectMapsSize(message, 2);
+  std::vector<const Message*> expected_entries =
+      MapTestUtil::GetMapEntries(message, 0);
+
+  reflection_tester.RemoveLastMapsViaReflection(&message);
+
+  MapTestUtil::ExpectMapsSize(message, 1);
+  std::vector<const Message*> remained_entries =
+      MapTestUtil::GetMapEntries(message, 0);
+  EXPECT_TRUE(expected_entries == remained_entries);
+}
+
+TEST(GeneratedMapFieldReflectionTest, ReleaseLast) {
+  unittest::TestMap message;
+  const Descriptor* descriptor = message.GetDescriptor();
+  MapTestUtil::MapReflectionTester reflection_tester(descriptor);
+
+  MapTestUtil::SetMapFields(&message);
+
+  MapTestUtil::ExpectMapsSize(message, 2);
+
+  reflection_tester.ReleaseLastMapsViaReflection(&message);
+
+  MapTestUtil::ExpectMapsSize(message, 1);
+
+  // Now test that we actually release the right message.
+  message.Clear();
+  MapTestUtil::SetMapFields(&message);
+
+  MapTestUtil::ExpectMapsSize(message, 2);
+  std::vector<const Message*> expect_last =
+      MapTestUtil::GetMapEntries(message, 1);
+  std::vector<const Message*> release_last =
+      MapTestUtil::GetMapEntriesFromRelease(&message);
+  MapTestUtil::ExpectMapsSize(message, 1);
+  EXPECT_TRUE(expect_last == release_last);
+  for (std::vector<const Message*>::iterator it = release_last.begin();
+       it != release_last.end(); ++it) {
+    delete *it;
+  }
+}
+
+TEST(GeneratedMapFieldReflectionTest, SwapElements) {
+  unittest::TestMap message;
+  MapTestUtil::MapReflectionTester reflection_tester(
+    unittest::TestMap::descriptor());
+
+  MapTestUtil::SetMapFields(&message);
+
+  // Get pointers of map entries at their original position
+  std::vector<const Message*> entries0 = MapTestUtil::GetMapEntries(message, 0);
+  std::vector<const Message*> entries1 = MapTestUtil::GetMapEntries(message, 1);
+
+  // Swap the first time.
+  reflection_tester.SwapMapsViaReflection(&message);
+
+  // Get pointer of map entry after swap once.
+  std::vector<const Message*> entries0_once =
+      MapTestUtil::GetMapEntries(message, 0);
+  std::vector<const Message*> entries1_once =
+      MapTestUtil::GetMapEntries(message, 1);
+
+  // Test map entries are swapped.
+  MapTestUtil::ExpectMapsSize(message, 2);
+  EXPECT_TRUE(entries0 == entries1_once);
+  EXPECT_TRUE(entries1 == entries0_once);
+
+  // Swap the second time.
+  reflection_tester.SwapMapsViaReflection(&message);
+
+  // Get pointer of map entry after swap once.
+  std::vector<const Message*> entries0_twice =
+      MapTestUtil::GetMapEntries(message, 0);
+  std::vector<const Message*> entries1_twice =
+      MapTestUtil::GetMapEntries(message, 1);
+
+  // Test map entries are swapped back.
+  MapTestUtil::ExpectMapsSize(message, 2);
+  EXPECT_TRUE(entries0 == entries0_twice);
+  EXPECT_TRUE(entries1 == entries1_twice);
+}
+
+TEST(GeneratedMapFieldReflectionTest, MutableUnknownFields) {
+  unittest::TestMap message;
+  MapTestUtil::MapReflectionTester reflection_tester(
+    unittest::TestMap::descriptor());
+  reflection_tester.MutableUnknownFieldsOfMapFieldsViaReflection(&message);
+}
+
+TEST(GeneratedMapFieldReflectionTest, EmbedProto2Message) {
+  unittest::TestMessageMap message;
+
+  const FieldDescriptor* map_field =
+      unittest::TestMessageMap::descriptor()->FindFieldByName(
+          "map_int32_message");
+  const FieldDescriptor* value =
+      map_field->message_type()->FindFieldByName("value");
+
+  Message* entry_message =
+      message.GetReflection()->AddMessage(&message, map_field);
+  EXPECT_EQ(
+      &entry_message->GetReflection()->GetMessage(*entry_message, value),
+      reinterpret_cast<const Message*>(&TestAllTypes::default_instance()));
+
+  Message* proto2_message =
+      entry_message->GetReflection()->MutableMessage(entry_message, value);
+  EXPECT_EQ(unittest::TestAllTypes::descriptor(),
+            proto2_message->GetDescriptor());
+  ASSERT_EQ(1, message.map_int32_message().size());
+}
+
+TEST(GeneratedMapFieldReflectionTest, MergeFromClearMapEntry) {
+  unittest::TestMap message;
+  const FieldDescriptor* map_field =
+      unittest::TestMap::descriptor()->FindFieldByName("map_int32_int32");
+  const FieldDescriptor* key =
+      map_field->message_type()->FindFieldByName("key");
+  const FieldDescriptor* value =
+      map_field->message_type()->FindFieldByName("value");
+
+  Message* entry_message1 =
+      message.GetReflection()->AddMessage(&message, map_field);
+  EXPECT_FALSE(entry_message1->GetReflection()->HasField(*entry_message1, key));
+  EXPECT_FALSE(
+      entry_message1->GetReflection()->HasField(*entry_message1, value));
+
+  Message* entry_message2 =
+      message.GetReflection()->AddMessage(&message, map_field);
+  EXPECT_FALSE(entry_message2->GetReflection()->HasField(*entry_message2, key));
+  EXPECT_FALSE(
+      entry_message2->GetReflection()->HasField(*entry_message2, value));
+
+  entry_message1->MergeFrom(*entry_message2);
+  EXPECT_FALSE(entry_message1->GetReflection()->HasField(*entry_message1, key));
+  EXPECT_FALSE(
+      entry_message1->GetReflection()->HasField(*entry_message1, value));
+}
+
+TEST(GeneratedMapFieldReflectionTest, MapEntryClear) {
+  unittest::TestMap message;
+  MapTestUtil::MapReflectionTester reflection_tester(
+    unittest::TestMap::descriptor());
+  reflection_tester.MutableUnknownFieldsOfMapFieldsViaReflection(&message);
+}
+
+TEST(GeneratedMapFieldReflectionTest, Proto2MapEntryClear) {
+  unittest::TestEnumStartWithNonZeroMap message;
+  const Descriptor* descriptor = message.GetDescriptor();
+  const FieldDescriptor* field_descriptor =
+      descriptor->FindFieldByName("map_field");
+  const FieldDescriptor* value_descriptor =
+      field_descriptor->message_type()->FindFieldByName("value");
+  Message* sub_message =
+      message.GetReflection()->AddMessage(&message, field_descriptor);
+  EXPECT_EQ(1, sub_message->GetReflection()->GetEnumValue(*sub_message,
+                                                          value_descriptor));
+}
+
+// Dynamic Message Test =============================================
+
+class MapFieldInDynamicMessageTest : public testing::Test {
+ protected:
+  const DescriptorPool* pool_;
+  DynamicMessageFactory factory_;
+  const Descriptor* map_descriptor_;
+  const Message* map_prototype_;
+
+  MapFieldInDynamicMessageTest()
+      : pool_(DescriptorPool::generated_pool()), factory_(pool_) {}
+
+  virtual void SetUp() {
+    map_descriptor_ =
+      pool_->FindMessageTypeByName("protobuf_unittest.TestMap");
+    ASSERT_TRUE(map_descriptor_ != NULL);
+    map_prototype_ = factory_.GetPrototype(map_descriptor_);
+  }
+};
+
+TEST_F(MapFieldInDynamicMessageTest, MapIndependentOffsets) {
+  // Check that all fields have independent offsets by setting each
+  // one to a unique value then checking that they all still have those
+  // unique values (i.e. they don't stomp each other).
+  scoped_ptr<Message> message(map_prototype_->New());
+  MapTestUtil::MapReflectionTester reflection_tester(map_descriptor_);
+
+  reflection_tester.SetMapFieldsViaReflection(message.get());
+  reflection_tester.ExpectMapFieldsSetViaReflection(*message);
+}
+
+TEST_F(MapFieldInDynamicMessageTest, Map) {
+  // Check that map fields work properly.
+  scoped_ptr<Message> message(map_prototype_->New());
+
+  // Check set functions.
+  MapTestUtil::MapReflectionTester reflection_tester(map_descriptor_);
+  reflection_tester.SetMapFieldsViaReflection(message.get());
+  reflection_tester.ExpectMapFieldsSetViaReflection(*message);
+}
+
+TEST_F(MapFieldInDynamicMessageTest, MapSpaceUsed) {
+  // Test that SpaceUsed() works properly
+
+  // Since we share the implementation with generated messages, we don't need
+  // to test very much here.  Just make sure it appears to be working.
+
+  scoped_ptr<Message> message(map_prototype_->New());
+  MapTestUtil::MapReflectionTester reflection_tester(map_descriptor_);
+
+  int initial_space_used = message->SpaceUsed();
+
+  reflection_tester.SetMapFieldsViaReflection(message.get());
+  EXPECT_LT(initial_space_used, message->SpaceUsed());
+}
+
+// ReflectionOps Test ===============================================
+
+TEST(ReflectionOpsForMapFieldTest, MapSanityCheck) {
+  unittest::TestMap message;
+
+  MapTestUtil::SetMapFields(&message);
+  MapTestUtil::ExpectMapFieldsSet(message);
+}
+
+TEST(ReflectionOpsForMapFieldTest, MapCopy) {
+  unittest::TestMap message, message2;
+
+  MapTestUtil::SetMapFields(&message);
+
+  ReflectionOps::Copy(message, &message2);
+
+  MapTestUtil::ExpectMapFieldsSet(message2);
+
+  // Copying from self should be a no-op.
+  ReflectionOps::Copy(message2, &message2);
+  MapTestUtil::ExpectMapFieldsSet(message2);
+}
+
+TEST(ReflectionOpsForMapFieldTest, MergeMap) {
+  // Note:  Copy is implemented in terms of Merge() so technically the Copy
+  //   test already tested most of this.
+
+  unittest::TestMap message, message2;
+
+  MapTestUtil::SetMapFields(&message);
+
+  ReflectionOps::Merge(message2, &message);
+
+  MapTestUtil::ExpectMapFieldsSet(message);
+}
+
+TEST(ReflectionOpsForMapFieldTest, ClearMap) {
+  unittest::TestMap message;
+
+  MapTestUtil::SetMapFields(&message);
+
+  ReflectionOps::Clear(&message);
+
+  MapTestUtil::ExpectClear(message);
+}
+
+TEST(ReflectionOpsForMapFieldTest, MapDiscardUnknownFields) {
+  unittest::TestMap message;
+  MapTestUtil::SetMapFields(&message);
+
+  // Set some unknown fields in message.
+  message.GetReflection()->MutableUnknownFields(&message)->
+      AddVarint(123456, 654321);
+
+  // Discard them.
+  ReflectionOps::DiscardUnknownFields(&message);
+  MapTestUtil::ExpectMapFieldsSet(message);
+
+  EXPECT_EQ(0, message.GetReflection()->
+      GetUnknownFields(message).field_count());
+}
+
+// Wire Format Test =================================================
+
+TEST(WireFormatForMapFieldTest, ParseMap) {
+  unittest::TestMap source, dest;
+  string data;
+
+  // Serialize using the generated code.
+  MapTestUtil::SetMapFields(&source);
+  source.SerializeToString(&data);
+
+  // Parse using WireFormat.
+  io::ArrayInputStream raw_input(data.data(), data.size());
+  io::CodedInputStream input(&raw_input);
+  WireFormat::ParseAndMergePartial(&input, &dest);
+
+  // Check.
+  MapTestUtil::ExpectMapFieldsSet(dest);
+}
+
+TEST(WireFormatForMapFieldTest, MapByteSize) {
+  unittest::TestMap message;
+  MapTestUtil::SetMapFields(&message);
+
+  EXPECT_EQ(message.ByteSize(), WireFormat::ByteSize(message));
+  message.Clear();
+  EXPECT_EQ(0, message.ByteSize());
+  EXPECT_EQ(0, WireFormat::ByteSize(message));
+}
+
+TEST(WireFormatForMapFieldTest, SerializeMap) {
+  unittest::TestMap message;
+  string generated_data;
+  string dynamic_data;
+
+  MapTestUtil::SetMapFields(&message);
+
+  // Serialize using the generated code.
+  {
+    message.ByteSize();
+    io::StringOutputStream raw_output(&generated_data);
+    io::CodedOutputStream output(&raw_output);
+    message.SerializeWithCachedSizes(&output);
+    ASSERT_FALSE(output.HadError());
+  }
+
+  // Serialize using WireFormat.
+  {
+    io::StringOutputStream raw_output(&dynamic_data);
+    io::CodedOutputStream output(&raw_output);
+    int size = WireFormat::ByteSize(message);
+    WireFormat::SerializeWithCachedSizes(message, size, &output);
+    ASSERT_FALSE(output.HadError());
+  }
+
+  // Should be the same.
+  // Don't use EXPECT_EQ here because we're comparing raw binary data and
+  // we really don't want it dumped to stdout on failure.
+  EXPECT_TRUE(dynamic_data == generated_data);
+}
+
+TEST(WireFormatForMapFieldTest, MapParseHelpers) {
+  string data;
+
+  {
+    // Set up.
+    protobuf_unittest::TestMap message;
+    MapTestUtil::SetMapFields(&message);
+    message.SerializeToString(&data);
+  }
+
+  {
+    // Test ParseFromString.
+    protobuf_unittest::TestMap message;
+    EXPECT_TRUE(message.ParseFromString(data));
+    MapTestUtil::ExpectMapFieldsSet(message);
+  }
+
+  {
+    // Test ParseFromIstream.
+    protobuf_unittest::TestMap message;
+    stringstream stream(data);
+    EXPECT_TRUE(message.ParseFromIstream(&stream));
+    EXPECT_TRUE(stream.eof());
+    MapTestUtil::ExpectMapFieldsSet(message);
+  }
+
+  {
+    // Test ParseFromBoundedZeroCopyStream.
+    string data_with_junk(data);
+    data_with_junk.append("some junk on the end");
+    io::ArrayInputStream stream(data_with_junk.data(), data_with_junk.size());
+    protobuf_unittest::TestMap message;
+    EXPECT_TRUE(message.ParseFromBoundedZeroCopyStream(&stream, data.size()));
+    MapTestUtil::ExpectMapFieldsSet(message);
+  }
+
+  {
+    // Test that ParseFromBoundedZeroCopyStream fails (but doesn't crash) if
+    // EOF is reached before the expected number of bytes.
+    io::ArrayInputStream stream(data.data(), data.size());
+    protobuf_unittest::TestAllTypes message;
+    EXPECT_FALSE(
+      message.ParseFromBoundedZeroCopyStream(&stream, data.size() + 1));
+  }
+}
+
+// Text Format Test =================================================
+
+TEST(TextFormatMapTest, SerializeAndParse) {
+  unittest::TestMap source;
+  unittest::TestMap dest;
+  MapTestUtil::SetMapFields(&source);
+  string output;
+
+  // Test compact ASCII
+  TextFormat::Printer printer;
+  printer.PrintToString(source, &output);
+  TextFormat::Parser parser;
+  EXPECT_TRUE(parser.ParseFromString(output, &dest));
+  MapTestUtil::ExpectMapFieldsSet(dest);
+}
+
+
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google

+ 1479 - 0
src/google/protobuf/map_test_util.cc

@@ -0,0 +1,1479 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <google/protobuf/map_test_util.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/message.h>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+
+void MapTestUtil::SetMapFields(unittest::TestMap* message) {
+  // Add first element.
+  (*message->mutable_map_int32_int32())[0] = 0;
+  (*message->mutable_map_int64_int64())[0] = 0;
+  (*message->mutable_map_uint32_uint32())[0] = 0;
+  (*message->mutable_map_uint64_uint64())[0] = 0;
+  (*message->mutable_map_sint32_sint32())[0] = 0;
+  (*message->mutable_map_sint64_sint64())[0] = 0;
+  (*message->mutable_map_fixed32_fixed32())[0] = 0;
+  (*message->mutable_map_fixed64_fixed64())[0] = 0;
+  (*message->mutable_map_sfixed32_sfixed32())[0] = 0;
+  (*message->mutable_map_sfixed64_sfixed64())[0] = 0;
+  (*message->mutable_map_int32_float())[0] = 0.0;
+  (*message->mutable_map_int32_double())[0] = 0.0;
+  (*message->mutable_map_bool_bool())[0] = false;
+  (*message->mutable_map_string_string())["0"] = "0";
+  (*message->mutable_map_int32_bytes())[0] = "0";
+  (*message->mutable_map_int32_enum())[0] =
+      unittest::MAP_ENUM_BAR;
+  (*message->mutable_map_int32_foreign_message())[0].set_c(0);
+
+  // Add second element
+  (*message->mutable_map_int32_int32())[1] = 1;
+  (*message->mutable_map_int64_int64())[1] = 1;
+  (*message->mutable_map_uint32_uint32())[1] = 1;
+  (*message->mutable_map_uint64_uint64())[1] = 1;
+  (*message->mutable_map_sint32_sint32())[1] = 1;
+  (*message->mutable_map_sint64_sint64())[1] = 1;
+  (*message->mutable_map_fixed32_fixed32())[1] = 1;
+  (*message->mutable_map_fixed64_fixed64())[1] = 1;
+  (*message->mutable_map_sfixed32_sfixed32())[1] = 1;
+  (*message->mutable_map_sfixed64_sfixed64())[1] = 1;
+  (*message->mutable_map_int32_float())[1] = 1.0;
+  (*message->mutable_map_int32_double())[1] = 1.0;
+  (*message->mutable_map_bool_bool())[1] = true;
+  (*message->mutable_map_string_string())["1"] = "1";
+  (*message->mutable_map_int32_bytes())[1] = "1";
+  (*message->mutable_map_int32_enum())[1] =
+      unittest::MAP_ENUM_BAZ;
+  (*message->mutable_map_int32_foreign_message())[1].set_c(1);
+}
+
+void MapTestUtil::SetMapFieldsInitialized(unittest::TestMap* message) {
+  // Add first element using bracket operator, which should assign default
+  // value automatically.
+  (*message->mutable_map_int32_int32())[0];
+  (*message->mutable_map_int64_int64())[0];
+  (*message->mutable_map_uint32_uint32())[0];
+  (*message->mutable_map_uint64_uint64())[0];
+  (*message->mutable_map_sint32_sint32())[0];
+  (*message->mutable_map_sint64_sint64())[0];
+  (*message->mutable_map_fixed32_fixed32())[0];
+  (*message->mutable_map_fixed64_fixed64())[0];
+  (*message->mutable_map_sfixed32_sfixed32())[0];
+  (*message->mutable_map_sfixed64_sfixed64())[0];
+  (*message->mutable_map_int32_float())[0];
+  (*message->mutable_map_int32_double())[0];
+  (*message->mutable_map_bool_bool())[0];
+  (*message->mutable_map_string_string())["0"];
+  (*message->mutable_map_int32_bytes())[0];
+  (*message->mutable_map_int32_enum())[0];
+  (*message->mutable_map_int32_foreign_message())[0];
+}
+
+void MapTestUtil::ModifyMapFields(unittest::TestMap* message) {
+  (*message->mutable_map_int32_int32())[1] = 2;
+  (*message->mutable_map_int64_int64())[1] = 2;
+  (*message->mutable_map_uint32_uint32())[1] = 2;
+  (*message->mutable_map_uint64_uint64())[1] = 2;
+  (*message->mutable_map_sint32_sint32())[1] = 2;
+  (*message->mutable_map_sint64_sint64())[1] = 2;
+  (*message->mutable_map_fixed32_fixed32())[1] = 2;
+  (*message->mutable_map_fixed64_fixed64())[1] = 2;
+  (*message->mutable_map_sfixed32_sfixed32())[1] = 2;
+  (*message->mutable_map_sfixed64_sfixed64())[1] = 2;
+  (*message->mutable_map_int32_float())[1] = 2.0;
+  (*message->mutable_map_int32_double())[1] = 2.0;
+  (*message->mutable_map_bool_bool())[1] = false;
+  (*message->mutable_map_string_string())["1"] = "2";
+  (*message->mutable_map_int32_bytes())[1] = "2";
+  (*message->mutable_map_int32_enum())[1] =
+      unittest::MAP_ENUM_FOO;
+  (*message->mutable_map_int32_foreign_message())[1].set_c(2);
+}
+
+void MapTestUtil::ExpectClear(const unittest::TestMap& message) {
+  EXPECT_EQ(0, message.map_int32_int32().size());
+  EXPECT_EQ(0, message.map_int64_int64().size());
+  EXPECT_EQ(0, message.map_uint32_uint32().size());
+  EXPECT_EQ(0, message.map_uint64_uint64().size());
+  EXPECT_EQ(0, message.map_sint32_sint32().size());
+  EXPECT_EQ(0, message.map_sint64_sint64().size());
+  EXPECT_EQ(0, message.map_fixed32_fixed32().size());
+  EXPECT_EQ(0, message.map_fixed64_fixed64().size());
+  EXPECT_EQ(0, message.map_sfixed32_sfixed32().size());
+  EXPECT_EQ(0, message.map_sfixed64_sfixed64().size());
+  EXPECT_EQ(0, message.map_int32_float().size());
+  EXPECT_EQ(0, message.map_int32_double().size());
+  EXPECT_EQ(0, message.map_bool_bool().size());
+  EXPECT_EQ(0, message.map_string_string().size());
+  EXPECT_EQ(0, message.map_int32_bytes().size());
+  EXPECT_EQ(0, message.map_int32_enum().size());
+  EXPECT_EQ(0, message.map_int32_foreign_message().size());
+}
+
+void MapTestUtil::ExpectMapFieldsSet(const unittest::TestMap& message) {
+  EXPECT_EQ(2, message.map_int32_int32().size());
+  EXPECT_EQ(2, message.map_int64_int64().size());
+  EXPECT_EQ(2, message.map_uint32_uint32().size());
+  EXPECT_EQ(2, message.map_uint64_uint64().size());
+  EXPECT_EQ(2, message.map_sint32_sint32().size());
+  EXPECT_EQ(2, message.map_sint64_sint64().size());
+  EXPECT_EQ(2, message.map_fixed32_fixed32().size());
+  EXPECT_EQ(2, message.map_fixed64_fixed64().size());
+  EXPECT_EQ(2, message.map_sfixed32_sfixed32().size());
+  EXPECT_EQ(2, message.map_sfixed64_sfixed64().size());
+  EXPECT_EQ(2, message.map_int32_float().size());
+  EXPECT_EQ(2, message.map_int32_double().size());
+  EXPECT_EQ(2, message.map_bool_bool().size());
+  EXPECT_EQ(2, message.map_string_string().size());
+  EXPECT_EQ(2, message.map_int32_bytes().size());
+  EXPECT_EQ(2, message.map_int32_enum().size());
+  EXPECT_EQ(2, message.map_int32_foreign_message().size());
+
+  EXPECT_EQ(0, message.map_int32_int32().at(0));
+  EXPECT_EQ(0, message.map_int64_int64().at(0));
+  EXPECT_EQ(0, message.map_uint32_uint32().at(0));
+  EXPECT_EQ(0, message.map_uint64_uint64().at(0));
+  EXPECT_EQ(0, message.map_sint32_sint32().at(0));
+  EXPECT_EQ(0, message.map_sint64_sint64().at(0));
+  EXPECT_EQ(0, message.map_fixed32_fixed32().at(0));
+  EXPECT_EQ(0, message.map_fixed64_fixed64().at(0));
+  EXPECT_EQ(0, message.map_sfixed32_sfixed32().at(0));
+  EXPECT_EQ(0, message.map_sfixed64_sfixed64().at(0));
+  EXPECT_EQ(0, message.map_int32_float().at(0));
+  EXPECT_EQ(0, message.map_int32_double().at(0));
+  EXPECT_EQ(false, message.map_bool_bool().at(0));
+  EXPECT_EQ("0", message.map_string_string().at("0"));
+  EXPECT_EQ("0", message.map_int32_bytes().at(0));
+  EXPECT_EQ(unittest::MAP_ENUM_BAR, message.map_int32_enum().at(0));
+  EXPECT_EQ(0, message.map_int32_foreign_message().at(0).c());
+
+  EXPECT_EQ(1, message.map_int32_int32().at(1));
+  EXPECT_EQ(1, message.map_int64_int64().at(1));
+  EXPECT_EQ(1, message.map_uint32_uint32().at(1));
+  EXPECT_EQ(1, message.map_uint64_uint64().at(1));
+  EXPECT_EQ(1, message.map_sint32_sint32().at(1));
+  EXPECT_EQ(1, message.map_sint64_sint64().at(1));
+  EXPECT_EQ(1, message.map_fixed32_fixed32().at(1));
+  EXPECT_EQ(1, message.map_fixed64_fixed64().at(1));
+  EXPECT_EQ(1, message.map_sfixed32_sfixed32().at(1));
+  EXPECT_EQ(1, message.map_sfixed64_sfixed64().at(1));
+  EXPECT_EQ(1, message.map_int32_float().at(1));
+  EXPECT_EQ(1, message.map_int32_double().at(1));
+  EXPECT_EQ(true, message.map_bool_bool().at(1));
+  EXPECT_EQ("1", message.map_string_string().at("1"));
+  EXPECT_EQ("1", message.map_int32_bytes().at(1));
+  EXPECT_EQ(unittest::MAP_ENUM_BAZ, message.map_int32_enum().at(1));
+  EXPECT_EQ(1, message.map_int32_foreign_message().at(1).c());
+}
+
+void MapTestUtil::ExpectMapFieldsSetInitialized(
+    const unittest::TestMap& message) {
+  EXPECT_EQ(1, message.map_int32_int32().size());
+  EXPECT_EQ(1, message.map_int64_int64().size());
+  EXPECT_EQ(1, message.map_uint32_uint32().size());
+  EXPECT_EQ(1, message.map_uint64_uint64().size());
+  EXPECT_EQ(1, message.map_sint32_sint32().size());
+  EXPECT_EQ(1, message.map_sint64_sint64().size());
+  EXPECT_EQ(1, message.map_fixed32_fixed32().size());
+  EXPECT_EQ(1, message.map_fixed64_fixed64().size());
+  EXPECT_EQ(1, message.map_sfixed32_sfixed32().size());
+  EXPECT_EQ(1, message.map_sfixed64_sfixed64().size());
+  EXPECT_EQ(1, message.map_int32_float().size());
+  EXPECT_EQ(1, message.map_int32_double().size());
+  EXPECT_EQ(1, message.map_bool_bool().size());
+  EXPECT_EQ(1, message.map_string_string().size());
+  EXPECT_EQ(1, message.map_int32_bytes().size());
+  EXPECT_EQ(1, message.map_int32_enum().size());
+  EXPECT_EQ(1, message.map_int32_foreign_message().size());
+
+  EXPECT_EQ(0, message.map_int32_int32().at(0));
+  EXPECT_EQ(0, message.map_int64_int64().at(0));
+  EXPECT_EQ(0, message.map_uint32_uint32().at(0));
+  EXPECT_EQ(0, message.map_uint64_uint64().at(0));
+  EXPECT_EQ(0, message.map_sint32_sint32().at(0));
+  EXPECT_EQ(0, message.map_sint64_sint64().at(0));
+  EXPECT_EQ(0, message.map_fixed32_fixed32().at(0));
+  EXPECT_EQ(0, message.map_fixed64_fixed64().at(0));
+  EXPECT_EQ(0, message.map_sfixed32_sfixed32().at(0));
+  EXPECT_EQ(0, message.map_sfixed64_sfixed64().at(0));
+  EXPECT_EQ(0, message.map_int32_float().at(0));
+  EXPECT_EQ(0, message.map_int32_double().at(0));
+  EXPECT_EQ(false, message.map_bool_bool().at(0));
+  EXPECT_EQ("", message.map_string_string().at("0"));
+  EXPECT_EQ("", message.map_int32_bytes().at(0));
+  EXPECT_EQ(unittest::MAP_ENUM_FOO, message.map_int32_enum().at(0));
+  EXPECT_EQ(0, message.map_int32_foreign_message().at(0).ByteSize());
+}
+
+void MapTestUtil::ExpectMapFieldsModified(
+    const unittest::TestMap& message) {
+  // ModifyMapFields only sets the second element of each field.  In addition to
+  // verifying this, we also verify that the first element and size were *not*
+  // modified.
+  EXPECT_EQ(2, message.map_int32_int32().size());
+  EXPECT_EQ(2, message.map_int64_int64().size());
+  EXPECT_EQ(2, message.map_uint32_uint32().size());
+  EXPECT_EQ(2, message.map_uint64_uint64().size());
+  EXPECT_EQ(2, message.map_sint32_sint32().size());
+  EXPECT_EQ(2, message.map_sint64_sint64().size());
+  EXPECT_EQ(2, message.map_fixed32_fixed32().size());
+  EXPECT_EQ(2, message.map_fixed64_fixed64().size());
+  EXPECT_EQ(2, message.map_sfixed32_sfixed32().size());
+  EXPECT_EQ(2, message.map_sfixed64_sfixed64().size());
+  EXPECT_EQ(2, message.map_int32_float().size());
+  EXPECT_EQ(2, message.map_int32_double().size());
+  EXPECT_EQ(2, message.map_bool_bool().size());
+  EXPECT_EQ(2, message.map_string_string().size());
+  EXPECT_EQ(2, message.map_int32_bytes().size());
+  EXPECT_EQ(2, message.map_int32_enum().size());
+  EXPECT_EQ(2, message.map_int32_foreign_message().size());
+
+  EXPECT_EQ(0, message.map_int32_int32().at(0));
+  EXPECT_EQ(0, message.map_int64_int64().at(0));
+  EXPECT_EQ(0, message.map_uint32_uint32().at(0));
+  EXPECT_EQ(0, message.map_uint64_uint64().at(0));
+  EXPECT_EQ(0, message.map_sint32_sint32().at(0));
+  EXPECT_EQ(0, message.map_sint64_sint64().at(0));
+  EXPECT_EQ(0, message.map_fixed32_fixed32().at(0));
+  EXPECT_EQ(0, message.map_fixed64_fixed64().at(0));
+  EXPECT_EQ(0, message.map_sfixed32_sfixed32().at(0));
+  EXPECT_EQ(0, message.map_sfixed64_sfixed64().at(0));
+  EXPECT_EQ(0, message.map_int32_float().at(0));
+  EXPECT_EQ(0, message.map_int32_double().at(0));
+  EXPECT_EQ(false, message.map_bool_bool().at(0));
+  EXPECT_EQ("0", message.map_string_string().at("0"));
+  EXPECT_EQ("0", message.map_int32_bytes().at(0));
+  EXPECT_EQ(unittest::MAP_ENUM_BAR, message.map_int32_enum().at(0));
+  EXPECT_EQ(0, message.map_int32_foreign_message().at(0).c());
+
+  // Actually verify the second (modified) elements now.
+  EXPECT_EQ(2, message.map_int32_int32().at(1));
+  EXPECT_EQ(2, message.map_int64_int64().at(1));
+  EXPECT_EQ(2, message.map_uint32_uint32().at(1));
+  EXPECT_EQ(2, message.map_uint64_uint64().at(1));
+  EXPECT_EQ(2, message.map_sint32_sint32().at(1));
+  EXPECT_EQ(2, message.map_sint64_sint64().at(1));
+  EXPECT_EQ(2, message.map_fixed32_fixed32().at(1));
+  EXPECT_EQ(2, message.map_fixed64_fixed64().at(1));
+  EXPECT_EQ(2, message.map_sfixed32_sfixed32().at(1));
+  EXPECT_EQ(2, message.map_sfixed64_sfixed64().at(1));
+  EXPECT_EQ(2, message.map_int32_float().at(1));
+  EXPECT_EQ(2, message.map_int32_double().at(1));
+  EXPECT_EQ(false, message.map_bool_bool().at(1));
+  EXPECT_EQ("2", message.map_string_string().at("1"));
+  EXPECT_EQ("2", message.map_int32_bytes().at(1));
+  EXPECT_EQ(unittest::MAP_ENUM_FOO, message.map_int32_enum().at(1));
+  EXPECT_EQ(2, message.map_int32_foreign_message().at(1).c());
+}
+
+void MapTestUtil::ExpectMapsSize(
+    const unittest::TestMap& message, int size) {
+  const Descriptor* descriptor = message.GetDescriptor();
+
+  EXPECT_EQ(size, message.GetReflection()->FieldSize(
+    message, descriptor->FindFieldByName("map_int32_int32")));
+  EXPECT_EQ(size, message.GetReflection()->FieldSize(
+    message, descriptor->FindFieldByName("map_int64_int64")));
+  EXPECT_EQ(size, message.GetReflection()->FieldSize(
+    message, descriptor->FindFieldByName("map_uint32_uint32")));
+  EXPECT_EQ(size, message.GetReflection()->FieldSize(
+    message, descriptor->FindFieldByName("map_uint64_uint64")));
+  EXPECT_EQ(size, message.GetReflection()->FieldSize(
+    message, descriptor->FindFieldByName("map_sint32_sint32")));
+  EXPECT_EQ(size, message.GetReflection()->FieldSize(
+    message, descriptor->FindFieldByName("map_sint64_sint64")));
+  EXPECT_EQ(size, message.GetReflection()->FieldSize(
+    message, descriptor->FindFieldByName("map_fixed32_fixed32")));
+  EXPECT_EQ(size, message.GetReflection()->FieldSize(
+    message, descriptor->FindFieldByName("map_fixed64_fixed64")));
+  EXPECT_EQ(size, message.GetReflection()->FieldSize(
+    message, descriptor->FindFieldByName("map_sfixed32_sfixed32")));
+  EXPECT_EQ(size, message.GetReflection()->FieldSize(
+    message, descriptor->FindFieldByName("map_sfixed64_sfixed64")));
+  EXPECT_EQ(size, message.GetReflection()->FieldSize(
+    message, descriptor->FindFieldByName("map_int32_float")));
+  EXPECT_EQ(size, message.GetReflection()->FieldSize(
+    message, descriptor->FindFieldByName("map_int32_double")));
+  EXPECT_EQ(size, message.GetReflection()->FieldSize(
+    message, descriptor->FindFieldByName("map_bool_bool")));
+  EXPECT_EQ(size, message.GetReflection()->FieldSize(
+    message, descriptor->FindFieldByName("map_string_string")));
+  EXPECT_EQ(size, message.GetReflection()->FieldSize(
+    message, descriptor->FindFieldByName("map_int32_bytes")));
+  EXPECT_EQ(size, message.GetReflection()->FieldSize(
+    message, descriptor->FindFieldByName("map_int32_foreign_message")));
+}
+
+std::vector<const Message*> MapTestUtil::GetMapEntries(
+    const unittest::TestMap& message, int index) {
+  const Descriptor* descriptor = message.GetDescriptor();
+  std::vector<const Message*> result;
+
+  result.push_back(&message.GetReflection()->GetRepeatedMessage(
+    message, descriptor->FindFieldByName("map_int32_int32"), index));
+  result.push_back(&message.GetReflection()->GetRepeatedMessage(
+    message, descriptor->FindFieldByName("map_int64_int64"), index));
+  result.push_back(&message.GetReflection()->GetRepeatedMessage(
+    message, descriptor->FindFieldByName("map_uint32_uint32"), index));
+  result.push_back(&message.GetReflection()->GetRepeatedMessage(
+    message, descriptor->FindFieldByName("map_uint64_uint64"), index));
+  result.push_back(&message.GetReflection()->GetRepeatedMessage(
+    message, descriptor->FindFieldByName("map_sint32_sint32"), index));
+  result.push_back(&message.GetReflection()->GetRepeatedMessage(
+    message, descriptor->FindFieldByName("map_sint64_sint64"), index));
+  result.push_back(&message.GetReflection()->GetRepeatedMessage(
+    message, descriptor->FindFieldByName("map_fixed32_fixed32"), index));
+  result.push_back(&message.GetReflection()->GetRepeatedMessage(
+    message, descriptor->FindFieldByName("map_fixed64_fixed64"), index));
+  result.push_back(&message.GetReflection()->GetRepeatedMessage(
+    message, descriptor->FindFieldByName("map_sfixed32_sfixed32"), index));
+  result.push_back(&message.GetReflection()->GetRepeatedMessage(
+    message, descriptor->FindFieldByName("map_sfixed64_sfixed64"), index));
+  result.push_back(&message.GetReflection()->GetRepeatedMessage(
+    message, descriptor->FindFieldByName("map_int32_float"), index));
+  result.push_back(&message.GetReflection()->GetRepeatedMessage(
+    message, descriptor->FindFieldByName("map_int32_double"), index));
+  result.push_back(&message.GetReflection()->GetRepeatedMessage(
+    message, descriptor->FindFieldByName("map_bool_bool"), index));
+  result.push_back(&message.GetReflection()->GetRepeatedMessage(
+    message, descriptor->FindFieldByName("map_string_string"), index));
+  result.push_back(&message.GetReflection()->GetRepeatedMessage(
+    message, descriptor->FindFieldByName("map_int32_bytes"), index));
+  result.push_back(&message.GetReflection()->GetRepeatedMessage(
+    message, descriptor->FindFieldByName("map_int32_enum"), index));
+  result.push_back(&message.GetReflection()->GetRepeatedMessage(
+    message, descriptor->FindFieldByName("map_int32_foreign_message"), index));
+
+  return result;
+}
+
+std::vector<const Message*> MapTestUtil::GetMapEntriesFromRelease(
+    unittest::TestMap* message) {
+  const Descriptor* descriptor = message->GetDescriptor();
+  std::vector<const Message*> result;
+
+  result.push_back(message->GetReflection()->ReleaseLast(
+    message, descriptor->FindFieldByName("map_int32_int32")));
+  result.push_back(message->GetReflection()->ReleaseLast(
+    message, descriptor->FindFieldByName("map_int64_int64")));
+  result.push_back(message->GetReflection()->ReleaseLast(
+    message, descriptor->FindFieldByName("map_uint32_uint32")));
+  result.push_back(message->GetReflection()->ReleaseLast(
+    message, descriptor->FindFieldByName("map_uint64_uint64")));
+  result.push_back(message->GetReflection()->ReleaseLast(
+    message, descriptor->FindFieldByName("map_sint32_sint32")));
+  result.push_back(message->GetReflection()->ReleaseLast(
+    message, descriptor->FindFieldByName("map_sint64_sint64")));
+  result.push_back(message->GetReflection()->ReleaseLast(
+    message, descriptor->FindFieldByName("map_fixed32_fixed32")));
+  result.push_back(message->GetReflection()->ReleaseLast(
+    message, descriptor->FindFieldByName("map_fixed64_fixed64")));
+  result.push_back(message->GetReflection()->ReleaseLast(
+    message, descriptor->FindFieldByName("map_sfixed32_sfixed32")));
+  result.push_back(message->GetReflection()->ReleaseLast(
+    message, descriptor->FindFieldByName("map_sfixed64_sfixed64")));
+  result.push_back(message->GetReflection()->ReleaseLast(
+    message, descriptor->FindFieldByName("map_int32_float")));
+  result.push_back(message->GetReflection()->ReleaseLast(
+    message, descriptor->FindFieldByName("map_int32_double")));
+  result.push_back(message->GetReflection()->ReleaseLast(
+    message, descriptor->FindFieldByName("map_bool_bool")));
+  result.push_back(message->GetReflection()->ReleaseLast(
+    message, descriptor->FindFieldByName("map_string_string")));
+  result.push_back(message->GetReflection()->ReleaseLast(
+    message, descriptor->FindFieldByName("map_int32_bytes")));
+  result.push_back(message->GetReflection()->ReleaseLast(
+    message, descriptor->FindFieldByName("map_int32_enum")));
+  result.push_back(message->GetReflection()->ReleaseLast(
+    message, descriptor->FindFieldByName("map_int32_foreign_message")));
+
+  return result;
+}
+
+MapTestUtil::MapReflectionTester::MapReflectionTester(
+    const Descriptor* base_descriptor)
+  : base_descriptor_(base_descriptor) {
+  const DescriptorPool* pool = base_descriptor->file()->pool();
+
+  map_enum_foo_ = pool->FindEnumValueByName("protobuf_unittest.MAP_ENUM_FOO");
+  map_enum_bar_ = pool->FindEnumValueByName("protobuf_unittest.MAP_ENUM_BAR");
+  map_enum_baz_ = pool->FindEnumValueByName("protobuf_unittest.MAP_ENUM_BAZ");
+
+  foreign_c_ = pool->FindFieldByName(
+      "protobuf_unittest.ForeignMessage.c");
+  map_int32_int32_key_ = pool->FindFieldByName(
+      "protobuf_unittest.TestMap.MapInt32Int32Entry.key");
+  map_int32_int32_val_ = pool->FindFieldByName(
+      "protobuf_unittest.TestMap.MapInt32Int32Entry.value");
+  map_int64_int64_key_ = pool->FindFieldByName(
+      "protobuf_unittest.TestMap.MapInt64Int64Entry.key");
+  map_int64_int64_val_ = pool->FindFieldByName(
+      "protobuf_unittest.TestMap.MapInt64Int64Entry.value");
+  map_uint32_uint32_key_ = pool->FindFieldByName(
+      "protobuf_unittest.TestMap.MapUint32Uint32Entry.key");
+  map_uint32_uint32_val_ = pool->FindFieldByName(
+      "protobuf_unittest.TestMap.MapUint32Uint32Entry.value");
+  map_uint64_uint64_key_ = pool->FindFieldByName(
+      "protobuf_unittest.TestMap.MapUint64Uint64Entry.key");
+  map_uint64_uint64_val_ = pool->FindFieldByName(
+      "protobuf_unittest.TestMap.MapUint64Uint64Entry.value");
+  map_sint32_sint32_key_ = pool->FindFieldByName(
+      "protobuf_unittest.TestMap.MapSint32Sint32Entry.key");
+  map_sint32_sint32_val_ = pool->FindFieldByName(
+      "protobuf_unittest.TestMap.MapSint32Sint32Entry.value");
+  map_sint64_sint64_key_ = pool->FindFieldByName(
+      "protobuf_unittest.TestMap.MapSint64Sint64Entry.key");
+  map_sint64_sint64_val_ = pool->FindFieldByName(
+      "protobuf_unittest.TestMap.MapSint64Sint64Entry.value");
+  map_fixed32_fixed32_key_ = pool->FindFieldByName(
+      "protobuf_unittest.TestMap.MapFixed32Fixed32Entry.key");
+  map_fixed32_fixed32_val_ = pool->FindFieldByName(
+      "protobuf_unittest.TestMap.MapFixed32Fixed32Entry.value");
+  map_fixed64_fixed64_key_ = pool->FindFieldByName(
+      "protobuf_unittest.TestMap.MapFixed64Fixed64Entry.key");
+  map_fixed64_fixed64_val_ = pool->FindFieldByName(
+      "protobuf_unittest.TestMap.MapFixed64Fixed64Entry.value");
+  map_sfixed32_sfixed32_key_ = pool->FindFieldByName(
+      "protobuf_unittest.TestMap.MapSfixed32Sfixed32Entry.key");
+  map_sfixed32_sfixed32_val_ = pool->FindFieldByName(
+      "protobuf_unittest.TestMap.MapSfixed32Sfixed32Entry.value");
+  map_sfixed64_sfixed64_key_ = pool->FindFieldByName(
+      "protobuf_unittest.TestMap.MapSfixed64Sfixed64Entry.key");
+  map_sfixed64_sfixed64_val_ = pool->FindFieldByName(
+      "protobuf_unittest.TestMap.MapSfixed64Sfixed64Entry.value");
+  map_int32_float_key_ = pool->FindFieldByName(
+      "protobuf_unittest.TestMap.MapInt32FloatEntry.key");
+  map_int32_float_val_ = pool->FindFieldByName(
+      "protobuf_unittest.TestMap.MapInt32FloatEntry.value");
+  map_int32_double_key_ = pool->FindFieldByName(
+      "protobuf_unittest.TestMap.MapInt32DoubleEntry.key");
+  map_int32_double_val_ = pool->FindFieldByName(
+      "protobuf_unittest.TestMap.MapInt32DoubleEntry.value");
+  map_bool_bool_key_ = pool->FindFieldByName(
+      "protobuf_unittest.TestMap.MapBoolBoolEntry.key");
+  map_bool_bool_val_ = pool->FindFieldByName(
+      "protobuf_unittest.TestMap.MapBoolBoolEntry.value");
+  map_string_string_key_ = pool->FindFieldByName(
+      "protobuf_unittest.TestMap.MapStringStringEntry.key");
+  map_string_string_val_ = pool->FindFieldByName(
+      "protobuf_unittest.TestMap.MapStringStringEntry.value");
+  map_int32_bytes_key_ = pool->FindFieldByName(
+      "protobuf_unittest.TestMap.MapInt32BytesEntry.key");
+  map_int32_bytes_val_ = pool->FindFieldByName(
+      "protobuf_unittest.TestMap.MapInt32BytesEntry.value");
+  map_int32_enum_key_ = pool->FindFieldByName(
+      "protobuf_unittest.TestMap.MapInt32EnumEntry.key");
+  map_int32_enum_val_ = pool->FindFieldByName(
+      "protobuf_unittest.TestMap.MapInt32EnumEntry.value");
+  map_int32_foreign_message_key_ = pool->FindFieldByName(
+      "protobuf_unittest.TestMap.MapInt32ForeignMessageEntry.key");
+  map_int32_foreign_message_val_ = pool->FindFieldByName(
+      "protobuf_unittest.TestMap.MapInt32ForeignMessageEntry.value");
+
+  EXPECT_FALSE(map_enum_foo_ == NULL);
+  EXPECT_FALSE(map_enum_bar_ == NULL);
+  EXPECT_FALSE(map_enum_baz_ == NULL);
+  EXPECT_FALSE(map_int32_int32_key_ == NULL);
+  EXPECT_FALSE(map_int32_int32_val_ == NULL);
+  EXPECT_FALSE(map_int64_int64_key_ == NULL);
+  EXPECT_FALSE(map_int64_int64_val_ == NULL);
+  EXPECT_FALSE(map_uint32_uint32_key_ == NULL);
+  EXPECT_FALSE(map_uint32_uint32_val_ == NULL);
+  EXPECT_FALSE(map_uint64_uint64_key_ == NULL);
+  EXPECT_FALSE(map_uint64_uint64_val_ == NULL);
+  EXPECT_FALSE(map_sint32_sint32_key_ == NULL);
+  EXPECT_FALSE(map_sint32_sint32_val_ == NULL);
+  EXPECT_FALSE(map_sint64_sint64_key_ == NULL);
+  EXPECT_FALSE(map_sint64_sint64_val_ == NULL);
+  EXPECT_FALSE(map_fixed32_fixed32_key_ == NULL);
+  EXPECT_FALSE(map_fixed32_fixed32_val_ == NULL);
+  EXPECT_FALSE(map_fixed64_fixed64_key_ == NULL);
+  EXPECT_FALSE(map_fixed64_fixed64_val_ == NULL);
+  EXPECT_FALSE(map_sfixed32_sfixed32_key_ == NULL);
+  EXPECT_FALSE(map_sfixed32_sfixed32_val_ == NULL);
+  EXPECT_FALSE(map_sfixed64_sfixed64_key_ == NULL);
+  EXPECT_FALSE(map_sfixed64_sfixed64_val_ == NULL);
+  EXPECT_FALSE(map_int32_float_key_ == NULL);
+  EXPECT_FALSE(map_int32_float_val_ == NULL);
+  EXPECT_FALSE(map_int32_double_key_ == NULL);
+  EXPECT_FALSE(map_int32_double_val_ == NULL);
+  EXPECT_FALSE(map_bool_bool_key_ == NULL);
+  EXPECT_FALSE(map_bool_bool_val_ == NULL);
+  EXPECT_FALSE(map_string_string_key_ == NULL);
+  EXPECT_FALSE(map_string_string_val_ == NULL);
+  EXPECT_FALSE(map_int32_bytes_key_ == NULL);
+  EXPECT_FALSE(map_int32_bytes_val_ == NULL);
+  EXPECT_FALSE(map_int32_enum_key_ == NULL);
+  EXPECT_FALSE(map_int32_enum_val_ == NULL);
+  EXPECT_FALSE(map_int32_foreign_message_key_ == NULL);
+  EXPECT_FALSE(map_int32_foreign_message_val_ == NULL);
+}
+
+// Shorthand to get a FieldDescriptor for a field of unittest::TestMap.
+const FieldDescriptor* MapTestUtil::MapReflectionTester::F(const string& name) {
+  const FieldDescriptor* result = NULL;
+  result = base_descriptor_->FindFieldByName(name);
+  GOOGLE_CHECK(result != NULL);
+  return result;
+}
+
+void MapTestUtil::MapReflectionTester::SetMapFieldsViaReflection(
+    Message* message) {
+  const Reflection* reflection = message->GetReflection();
+  Message* sub_message = NULL;
+  Message* sub_foreign_message = NULL;
+
+  // Add first element.
+  sub_message = reflection->AddMessage(message, F("map_int32_int32"));
+  sub_message->GetReflection()
+      ->SetInt32(sub_message, map_int32_int32_key_, 0);
+  sub_message->GetReflection()
+      ->SetInt32(sub_message, map_int32_int32_val_, 0);
+
+  sub_message = reflection->AddMessage(message, F("map_int64_int64"));
+  sub_message->GetReflection()
+      ->SetInt64(sub_message, map_int64_int64_key_, 0);
+  sub_message->GetReflection()
+      ->SetInt64(sub_message, map_int64_int64_val_, 0);
+
+  sub_message = reflection->AddMessage(message, F("map_uint32_uint32"));
+  sub_message->GetReflection()
+      ->SetUInt32(sub_message, map_uint32_uint32_key_, 0);
+  sub_message->GetReflection()
+      ->SetUInt32(sub_message, map_uint32_uint32_val_, 0);
+
+  sub_message = reflection->AddMessage(message, F("map_uint64_uint64"));
+  sub_message->GetReflection()
+      ->SetUInt64(sub_message, map_uint64_uint64_key_, 0);
+  sub_message->GetReflection()
+      ->SetUInt64(sub_message, map_uint64_uint64_val_, 0);
+
+  sub_message = reflection->AddMessage(message, F("map_sint32_sint32"));
+  sub_message->GetReflection()
+      ->SetInt32(sub_message, map_sint32_sint32_key_, 0);
+  sub_message->GetReflection()
+      ->SetInt32(sub_message, map_sint32_sint32_val_, 0);
+
+  sub_message = reflection->AddMessage(message, F("map_sint64_sint64"));
+  sub_message->GetReflection()
+      ->SetInt64(sub_message, map_sint64_sint64_key_, 0);
+  sub_message->GetReflection()
+      ->SetInt64(sub_message, map_sint64_sint64_val_, 0);
+
+  sub_message = reflection->AddMessage(message, F("map_fixed32_fixed32"));
+  sub_message->GetReflection()
+      ->SetUInt32(sub_message, map_fixed32_fixed32_key_, 0);
+  sub_message->GetReflection()
+      ->SetUInt32(sub_message, map_fixed32_fixed32_val_, 0);
+
+  sub_message = reflection->AddMessage(message, F("map_fixed64_fixed64"));
+  sub_message->GetReflection()
+      ->SetUInt64(sub_message, map_fixed64_fixed64_key_, 0);
+  sub_message->GetReflection()
+      ->SetUInt64(sub_message, map_fixed64_fixed64_val_, 0);
+
+  sub_message = reflection->AddMessage(message, F("map_sfixed32_sfixed32"));
+  sub_message->GetReflection()
+      ->SetInt32(sub_message, map_sfixed32_sfixed32_key_, 0);
+  sub_message->GetReflection()
+      ->SetInt32(sub_message, map_sfixed32_sfixed32_val_, 0);
+
+  sub_message = reflection->AddMessage(message, F("map_sfixed64_sfixed64"));
+  sub_message->GetReflection()
+      ->SetInt64(sub_message, map_sfixed64_sfixed64_key_, 0);
+  sub_message->GetReflection()
+      ->SetInt64(sub_message, map_sfixed64_sfixed64_val_, 0);
+
+  sub_message = reflection->AddMessage(message, F("map_int32_float"));
+  sub_message->GetReflection()
+      ->SetInt32(sub_message, map_int32_float_key_, 0);
+  sub_message->GetReflection()
+      ->SetFloat(sub_message, map_int32_float_val_, 0.0);
+
+  sub_message = reflection->AddMessage(message, F("map_int32_double"));
+  sub_message->GetReflection()
+      ->SetInt32(sub_message, map_int32_double_key_, 0);
+  sub_message->GetReflection()
+      ->SetDouble(sub_message, map_int32_double_val_, 0.0);
+
+  sub_message = reflection->AddMessage(message, F("map_bool_bool"));
+  sub_message->GetReflection()
+      ->SetBool(sub_message, map_bool_bool_key_, false);
+  sub_message->GetReflection()
+      ->SetBool(sub_message, map_bool_bool_val_, false);
+
+  sub_message = reflection->AddMessage(message, F("map_string_string"));
+  sub_message->GetReflection()
+      ->SetString(sub_message, map_string_string_key_, "0");
+  sub_message->GetReflection()
+      ->SetString(sub_message, map_string_string_val_, "0");
+
+  sub_message = reflection->AddMessage(message, F("map_int32_bytes"));
+  sub_message->GetReflection()
+      ->SetInt32(sub_message, map_int32_bytes_key_, 0);
+  sub_message->GetReflection()
+      ->SetString(sub_message, map_int32_bytes_val_, "0");
+
+  sub_message = reflection->AddMessage(message, F("map_int32_enum"));
+  sub_message->GetReflection()
+      ->SetInt32(sub_message, map_int32_enum_key_, 0);
+  sub_message->GetReflection()
+      ->SetEnum(sub_message, map_int32_enum_val_, map_enum_bar_);
+
+  sub_message = reflection
+      ->AddMessage(message, F("map_int32_foreign_message"));
+  sub_message->GetReflection()
+      ->SetInt32(sub_message, map_int32_foreign_message_key_, 0);
+  sub_foreign_message = sub_message->GetReflection()->
+      MutableMessage(sub_message, map_int32_foreign_message_val_, NULL);
+  sub_foreign_message->GetReflection()->
+      SetInt32(sub_foreign_message, foreign_c_, 0);
+
+  // Add second element
+  sub_message = reflection->AddMessage(message, F("map_int32_int32"));
+  sub_message->GetReflection()
+      ->SetInt32(sub_message, map_int32_int32_key_, 1);
+  sub_message->GetReflection()
+      ->SetInt32(sub_message, map_int32_int32_val_, 1);
+
+  sub_message = reflection->AddMessage(message, F("map_int64_int64"));
+  sub_message->GetReflection()
+      ->SetInt64(sub_message, map_int64_int64_key_, 1);
+  sub_message->GetReflection()
+      ->SetInt64(sub_message, map_int64_int64_val_, 1);
+
+  sub_message = reflection->AddMessage(message, F("map_uint32_uint32"));
+  sub_message->GetReflection()
+      ->SetUInt32(sub_message, map_uint32_uint32_key_, 1);
+  sub_message->GetReflection()
+      ->SetUInt32(sub_message, map_uint32_uint32_val_, 1);
+
+  sub_message = reflection->AddMessage(message, F("map_uint64_uint64"));
+  sub_message->GetReflection()
+      ->SetUInt64(sub_message, map_uint64_uint64_key_, 1);
+  sub_message->GetReflection()
+      ->SetUInt64(sub_message, map_uint64_uint64_val_, 1);
+
+  sub_message = reflection->AddMessage(message, F("map_sint32_sint32"));
+  sub_message->GetReflection()
+      ->SetInt32(sub_message, map_sint32_sint32_key_, 1);
+  sub_message->GetReflection()
+      ->SetInt32(sub_message, map_sint32_sint32_val_, 1);
+
+  sub_message = reflection->AddMessage(message, F("map_sint64_sint64"));
+  sub_message->GetReflection()
+      ->SetInt64(sub_message, map_sint64_sint64_key_, 1);
+  sub_message->GetReflection()
+      ->SetInt64(sub_message, map_sint64_sint64_val_, 1);
+
+  sub_message = reflection->AddMessage(message, F("map_fixed32_fixed32"));
+  sub_message->GetReflection()
+      ->SetUInt32(sub_message, map_fixed32_fixed32_key_, 1);
+  sub_message->GetReflection()
+      ->SetUInt32(sub_message, map_fixed32_fixed32_val_, 1);
+
+  sub_message = reflection->AddMessage(message, F("map_fixed64_fixed64"));
+  sub_message->GetReflection()
+      ->SetUInt64(sub_message, map_fixed64_fixed64_key_, 1);
+  sub_message->GetReflection()
+      ->SetUInt64(sub_message, map_fixed64_fixed64_val_, 1);
+
+  sub_message = reflection->AddMessage(message, F("map_sfixed32_sfixed32"));
+  sub_message->GetReflection()
+      ->SetInt32(sub_message, map_sfixed32_sfixed32_key_, 1);
+  sub_message->GetReflection()
+      ->SetInt32(sub_message, map_sfixed32_sfixed32_val_, 1);
+
+  sub_message = reflection->AddMessage(message, F("map_sfixed64_sfixed64"));
+  sub_message->GetReflection()
+      ->SetInt64(sub_message, map_sfixed64_sfixed64_key_, 1);
+  sub_message->GetReflection()
+      ->SetInt64(sub_message, map_sfixed64_sfixed64_val_, 1);
+
+  sub_message = reflection->AddMessage(message, F("map_int32_float"));
+  sub_message->GetReflection()
+      ->SetInt32(sub_message, map_int32_float_key_, 1);
+  sub_message->GetReflection()
+      ->SetFloat(sub_message, map_int32_float_val_, 1.0);
+
+  sub_message = reflection->AddMessage(message, F("map_int32_double"));
+  sub_message->GetReflection()
+      ->SetInt32(sub_message, map_int32_double_key_, 1);
+  sub_message->GetReflection()
+      ->SetDouble(sub_message, map_int32_double_val_, 1.0);
+
+  sub_message = reflection->AddMessage(message, F("map_bool_bool"));
+  sub_message->GetReflection()
+      ->SetBool(sub_message, map_bool_bool_key_, true);
+  sub_message->GetReflection()
+      ->SetBool(sub_message, map_bool_bool_val_, true);
+
+  sub_message = reflection->AddMessage(message, F("map_string_string"));
+  sub_message->GetReflection()
+      ->SetString(sub_message, map_string_string_key_, "1");
+  sub_message->GetReflection()
+      ->SetString(sub_message, map_string_string_val_, "1");
+
+  sub_message = reflection->AddMessage(message, F("map_int32_bytes"));
+  sub_message->GetReflection()
+      ->SetInt32(sub_message, map_int32_bytes_key_, 1);
+  sub_message->GetReflection()
+      ->SetString(sub_message, map_int32_bytes_val_, "1");
+
+  sub_message = reflection->AddMessage(message, F("map_int32_enum"));
+  sub_message->GetReflection()
+      ->SetInt32(sub_message, map_int32_enum_key_, 1);
+  sub_message->GetReflection()
+      ->SetEnum(sub_message, map_int32_enum_val_, map_enum_baz_);
+
+  sub_message = reflection
+      ->AddMessage(message, F("map_int32_foreign_message"));
+  sub_message->GetReflection()
+      ->SetInt32(sub_message, map_int32_foreign_message_key_, 1);
+  sub_foreign_message = sub_message->GetReflection()->
+      MutableMessage(sub_message, map_int32_foreign_message_val_, NULL);
+  sub_foreign_message->GetReflection()->
+      SetInt32(sub_foreign_message, foreign_c_, 1);
+}
+
+void MapTestUtil::MapReflectionTester::ClearMapFieldsViaReflection(
+    Message* message) {
+  const Reflection* reflection = message->GetReflection();
+
+  reflection->ClearField(message, F("map_int32_int32"));
+  reflection->ClearField(message, F("map_int64_int64"));
+  reflection->ClearField(message, F("map_uint32_uint32"));
+  reflection->ClearField(message, F("map_uint64_uint64"));
+  reflection->ClearField(message, F("map_sint32_sint32"));
+  reflection->ClearField(message, F("map_sint64_sint64"));
+  reflection->ClearField(message, F("map_fixed32_fixed32"));
+  reflection->ClearField(message, F("map_fixed64_fixed64"));
+  reflection->ClearField(message, F("map_sfixed32_sfixed32"));
+  reflection->ClearField(message, F("map_sfixed64_sfixed64"));
+  reflection->ClearField(message, F("map_int32_float"));
+  reflection->ClearField(message, F("map_int32_double"));
+  reflection->ClearField(message, F("map_bool_bool"));
+  reflection->ClearField(message, F("map_string_string"));
+  reflection->ClearField(message, F("map_int32_bytes"));
+  reflection->ClearField(message, F("map_int32_enum"));
+  reflection->ClearField(message, F("map_int32_foreign_message"));
+}
+
+void MapTestUtil::MapReflectionTester::ModifyMapFieldsViaReflection(
+    Message* message) {
+  const Reflection* reflection = message->GetReflection();
+  Message* sub_message;
+  Message* sub_foreign_message;
+
+  // Find out which one's key is 0.
+  int size = reflection->FieldSize(*message, F("map_int32_int32"));
+  int target = 0;
+  for (int i = 0; i < size; i++) {
+    const Message& temp_message = reflection
+      ->GetRepeatedMessage(*message, F("map_int32_int32"), i);
+    if (temp_message.GetReflection()
+          ->GetInt32(temp_message, map_int32_int32_key_) == 1) {
+      target = i;
+    }
+  }
+
+  sub_message = reflection
+      ->MutableRepeatedMessage(message, F("map_int32_int32"), target);
+  sub_message->GetReflection()
+      ->SetInt32(sub_message, map_int32_int32_val_, 2);
+  sub_message = reflection
+      ->MutableRepeatedMessage(message, F("map_int64_int64"), target);
+  sub_message->GetReflection()
+      ->SetInt64(sub_message, map_int64_int64_val_, 2);
+  sub_message = reflection
+      ->MutableRepeatedMessage(message, F("map_uint32_uint32"), target);
+  sub_message->GetReflection()
+      ->SetUInt32(sub_message, map_uint32_uint32_val_, 2);
+  sub_message = reflection
+      ->MutableRepeatedMessage(message, F("map_uint64_uint64"), target);
+  sub_message->GetReflection()
+      ->SetUInt64(sub_message, map_uint64_uint64_val_, 2);
+  sub_message = reflection
+      ->MutableRepeatedMessage(message, F("map_sint32_sint32"), target);
+  sub_message->GetReflection()
+      ->SetInt32(sub_message, map_sint32_sint32_val_, 2);
+  sub_message = reflection
+      ->MutableRepeatedMessage(message, F("map_sint64_sint64"), target);
+  sub_message->GetReflection()
+      ->SetInt64(sub_message, map_sint64_sint64_val_, 2);
+  sub_message = reflection
+      ->MutableRepeatedMessage(message, F("map_fixed32_fixed32"), target);
+  sub_message->GetReflection()
+      ->SetUInt32(sub_message, map_fixed32_fixed32_val_, 2);
+  sub_message = reflection
+      ->MutableRepeatedMessage(message, F("map_fixed64_fixed64"), target);
+  sub_message->GetReflection()
+      ->SetUInt64(sub_message, map_fixed64_fixed64_val_, 2);
+  sub_message = reflection
+      ->MutableRepeatedMessage(message, F("map_sfixed32_sfixed32"), target);
+  sub_message->GetReflection()
+      ->SetInt32(sub_message, map_sfixed32_sfixed32_val_, 2);
+  sub_message = reflection
+      ->MutableRepeatedMessage(message, F("map_sfixed64_sfixed64"), target);
+  sub_message->GetReflection()
+      ->SetInt64(sub_message, map_sfixed64_sfixed64_val_, 2);
+  sub_message = reflection
+      ->MutableRepeatedMessage(message, F("map_int32_float"), target);
+  sub_message->GetReflection()
+      ->SetFloat(sub_message, map_int32_float_val_, 2.0);
+  sub_message = reflection
+      ->MutableRepeatedMessage(message, F("map_int32_double"), target);
+  sub_message->GetReflection()
+      ->SetDouble(sub_message, map_int32_double_val_, 2.0);
+  sub_message = reflection
+      ->MutableRepeatedMessage(message, F("map_bool_bool"), target);
+  sub_message->GetReflection()
+      ->SetBool(sub_message, map_bool_bool_val_, false);
+  sub_message = reflection
+      ->MutableRepeatedMessage(message, F("map_string_string"), target);
+  sub_message->GetReflection()
+      ->SetString(sub_message, map_string_string_val_, "2");
+  sub_message = reflection
+      ->MutableRepeatedMessage(message, F("map_int32_bytes"), target);
+  sub_message->GetReflection()
+      ->SetString(sub_message, map_int32_bytes_val_, "2");
+  sub_message = reflection
+      ->MutableRepeatedMessage(message, F("map_int32_enum"), target);
+  sub_message->GetReflection()
+      ->SetEnum(sub_message, map_int32_enum_val_, map_enum_foo_);
+  sub_message = reflection
+      ->MutableRepeatedMessage(message, F("map_int32_foreign_message"), target);
+  sub_foreign_message = sub_message->GetReflection()->
+      MutableMessage(sub_message, map_int32_foreign_message_val_, NULL);
+  sub_foreign_message->GetReflection()->
+      SetInt32(sub_foreign_message, foreign_c_, 2);
+}
+
+void MapTestUtil::MapReflectionTester::RemoveLastMapsViaReflection(
+    Message* message) {
+  const Reflection* reflection = message->GetReflection();
+
+  vector<const FieldDescriptor*> output;
+  reflection->ListFields(*message, &output);
+  for (int i = 0; i < output.size(); ++i) {
+    const FieldDescriptor* field = output[i];
+    if (!field->is_repeated()) continue;
+    reflection->RemoveLast(message, field);
+  }
+}
+
+void MapTestUtil::MapReflectionTester::ReleaseLastMapsViaReflection(
+    Message* message) {
+  const Reflection* reflection = message->GetReflection();
+
+  vector<const FieldDescriptor*> output;
+  reflection->ListFields(*message, &output);
+  for (int i = 0; i < output.size(); ++i) {
+    const FieldDescriptor* field = output[i];
+    if (!field->is_repeated()) continue;
+    if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) continue;
+
+    Message* released = reflection->ReleaseLast(message, field);
+    ASSERT_TRUE(released != NULL) << "ReleaseLast returned NULL for: "
+                                  << field->name();
+    delete released;
+  }
+}
+
+void MapTestUtil::MapReflectionTester::SwapMapsViaReflection(Message* message) {
+  const Reflection* reflection = message->GetReflection();
+  vector<const FieldDescriptor*> output;
+  reflection->ListFields(*message, &output);
+  for (int i = 0; i < output.size(); ++i) {
+    const FieldDescriptor* field = output[i];
+    if (!field->is_repeated()) continue;
+    reflection->SwapElements(message, field, 0, 1);
+  }
+}
+
+void MapTestUtil::MapReflectionTester::
+    MutableUnknownFieldsOfMapFieldsViaReflection(Message* message) {
+  const Reflection* reflection = message->GetReflection();
+  Message* sub_message = NULL;
+
+  sub_message = reflection->AddMessage(message, F("map_int32_int32"));
+  EXPECT_TRUE(sub_message->GetReflection()->MutableUnknownFields(sub_message) !=
+              NULL);
+  sub_message = reflection->AddMessage(message, F("map_int64_int64"));
+  EXPECT_TRUE(sub_message->GetReflection()->MutableUnknownFields(sub_message) !=
+              NULL);
+  sub_message = reflection->AddMessage(message, F("map_uint32_uint32"));
+  EXPECT_TRUE(sub_message->GetReflection()->MutableUnknownFields(sub_message) !=
+              NULL);
+  sub_message = reflection->AddMessage(message, F("map_uint64_uint64"));
+  EXPECT_TRUE(sub_message->GetReflection()->MutableUnknownFields(sub_message) !=
+              NULL);
+  sub_message = reflection->AddMessage(message, F("map_sint32_sint32"));
+  EXPECT_TRUE(sub_message->GetReflection()->MutableUnknownFields(sub_message) !=
+              NULL);
+  sub_message = reflection->AddMessage(message, F("map_sint64_sint64"));
+  EXPECT_TRUE(sub_message->GetReflection()->MutableUnknownFields(sub_message) !=
+              NULL);
+  sub_message = reflection->AddMessage(message, F("map_fixed32_fixed32"));
+  EXPECT_TRUE(sub_message->GetReflection()->MutableUnknownFields(sub_message) !=
+              NULL);
+  sub_message = reflection->AddMessage(message, F("map_fixed64_fixed64"));
+  EXPECT_TRUE(sub_message->GetReflection()->MutableUnknownFields(sub_message) !=
+              NULL);
+  sub_message = reflection->AddMessage(message, F("map_sfixed32_sfixed32"));
+  EXPECT_TRUE(sub_message->GetReflection()->MutableUnknownFields(sub_message) !=
+              NULL);
+  sub_message = reflection->AddMessage(message, F("map_sfixed64_sfixed64"));
+  EXPECT_TRUE(sub_message->GetReflection()->MutableUnknownFields(sub_message) !=
+              NULL);
+  sub_message = reflection->AddMessage(message, F("map_int32_float"));
+  EXPECT_TRUE(sub_message->GetReflection()->MutableUnknownFields(sub_message) !=
+              NULL);
+  sub_message = reflection->AddMessage(message, F("map_int32_double"));
+  EXPECT_TRUE(sub_message->GetReflection()->MutableUnknownFields(sub_message) !=
+              NULL);
+  sub_message = reflection->AddMessage(message, F("map_bool_bool"));
+  EXPECT_TRUE(sub_message->GetReflection()->MutableUnknownFields(sub_message) !=
+              NULL);
+  sub_message = reflection->AddMessage(message, F("map_string_string"));
+  EXPECT_TRUE(sub_message->GetReflection()->MutableUnknownFields(sub_message) !=
+              NULL);
+  sub_message = reflection->AddMessage(message, F("map_int32_bytes"));
+  EXPECT_TRUE(sub_message->GetReflection()->MutableUnknownFields(sub_message) !=
+              NULL);
+  sub_message = reflection->AddMessage(message, F("map_int32_enum"));
+  EXPECT_TRUE(sub_message->GetReflection()->MutableUnknownFields(sub_message) !=
+              NULL);
+  sub_message = reflection->AddMessage(message, F("map_int32_foreign_message"));
+  EXPECT_TRUE(sub_message->GetReflection()->MutableUnknownFields(sub_message) !=
+              NULL);
+}
+
+void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection(
+    const Message& message) {
+  string scratch;
+  const Reflection* reflection = message.GetReflection();
+  const Message* sub_message;
+
+  // -----------------------------------------------------------------
+
+  ASSERT_EQ(2, reflection->FieldSize(message, F("map_int32_int32")));
+  ASSERT_EQ(2, reflection->FieldSize(message, F("map_int64_int64")));
+  ASSERT_EQ(2, reflection->FieldSize(message, F("map_uint32_uint32")));
+  ASSERT_EQ(2, reflection->FieldSize(message, F("map_uint64_uint64")));
+  ASSERT_EQ(2, reflection->FieldSize(message, F("map_sint32_sint32")));
+  ASSERT_EQ(2, reflection->FieldSize(message, F("map_sint64_sint64")));
+  ASSERT_EQ(2, reflection->FieldSize(message, F("map_fixed32_fixed32")));
+  ASSERT_EQ(2, reflection->FieldSize(message, F("map_fixed64_fixed64")));
+  ASSERT_EQ(2, reflection->FieldSize(message, F("map_sfixed32_sfixed32")));
+  ASSERT_EQ(2, reflection->FieldSize(message, F("map_sfixed64_sfixed64")));
+  ASSERT_EQ(2, reflection->FieldSize(message, F("map_int32_float")));
+  ASSERT_EQ(2, reflection->FieldSize(message, F("map_int32_double")));
+  ASSERT_EQ(2, reflection->FieldSize(message, F("map_bool_bool")));
+  ASSERT_EQ(2, reflection->FieldSize(message, F("map_string_string")));
+  ASSERT_EQ(2, reflection->FieldSize(message, F("map_int32_bytes")));
+  ASSERT_EQ(2, reflection->FieldSize(message, F("map_int32_enum")));
+  ASSERT_EQ(2, reflection->FieldSize(message, F("map_int32_foreign_message")));
+
+  {
+    std::map<int32, int32> map;
+    map[0] = 0;
+    map[1] = 1;
+    for (int i = 0; i < 2; i++) {
+      sub_message =
+          &reflection->GetRepeatedMessage(message, F("map_int32_int32"), i);
+      int32 key = sub_message->GetReflection()->GetInt32(
+          *sub_message, map_int32_int32_key_);
+      int32 val = sub_message->GetReflection()->GetInt32(
+          *sub_message, map_int32_int32_val_);
+      EXPECT_EQ(map.at(key), val);
+    }
+  }
+  {
+    std::map<int64, int64> map;
+    map[0] = 0;
+    map[1] = 1;
+    for (int i = 0; i < 2; i++) {
+      sub_message =
+          &reflection->GetRepeatedMessage(message, F("map_int64_int64"), i);
+      int64 key = sub_message->GetReflection()->GetInt64(
+          *sub_message, map_int64_int64_key_);
+      int64 val = sub_message->GetReflection()->GetInt64(
+          *sub_message, map_int64_int64_val_);
+      EXPECT_EQ(map.at(key), val);
+    }
+  }
+  {
+    std::map<uint32, uint32> map;
+    map[0] = 0;
+    map[1] = 1;
+    for (int i = 0; i < 2; i++) {
+      sub_message =
+          &reflection->GetRepeatedMessage(message, F("map_uint32_uint32"), i);
+      uint32 key = sub_message->GetReflection()->GetUInt32(
+          *sub_message, map_uint32_uint32_key_);
+      uint32 val = sub_message->GetReflection()->GetUInt32(
+          *sub_message, map_uint32_uint32_val_);
+      EXPECT_EQ(map.at(key), val);
+    }
+  }
+  {
+    std::map<uint64, uint64> map;
+    map[0] = 0;
+    map[1] = 1;
+    for (int i = 0; i < 2; i++) {
+      sub_message =
+          &reflection->GetRepeatedMessage(message, F("map_uint64_uint64"), i);
+      uint64 key = sub_message->GetReflection()->GetUInt64(
+          *sub_message, map_uint64_uint64_key_);
+      uint64 val = sub_message->GetReflection()->GetUInt64(
+          *sub_message, map_uint64_uint64_val_);
+      EXPECT_EQ(map.at(key), val);
+    }
+  }
+  {
+    std::map<int32, int32> map;
+    map[0] = 0;
+    map[1] = 1;
+    for (int i = 0; i < 2; i++) {
+      sub_message =
+          &reflection->GetRepeatedMessage(message, F("map_sint32_sint32"), i);
+      int32 key = sub_message->GetReflection()->GetInt32(
+          *sub_message, map_sint32_sint32_key_);
+      int32 val = sub_message->GetReflection()->GetInt32(
+          *sub_message, map_sint32_sint32_val_);
+      EXPECT_EQ(map.at(key), val);
+    }
+  }
+  {
+    std::map<int64, int64> map;
+    map[0] = 0;
+    map[1] = 1;
+    for (int i = 0; i < 2; i++) {
+      sub_message =
+          &reflection->GetRepeatedMessage(message, F("map_sint64_sint64"), i);
+      int64 key = sub_message->GetReflection()->GetInt64(
+          *sub_message, map_sint64_sint64_key_);
+      int64 val = sub_message->GetReflection()->GetInt64(
+          *sub_message, map_sint64_sint64_val_);
+      EXPECT_EQ(map.at(key), val);
+    }
+  }
+  {
+    std::map<uint32, uint32> map;
+    map[0] = 0;
+    map[1] = 1;
+    for (int i = 0; i < 2; i++) {
+      sub_message =
+          &reflection->GetRepeatedMessage(message, F("map_fixed32_fixed32"), i);
+      uint32 key = sub_message->GetReflection()->GetUInt32(
+          *sub_message, map_fixed32_fixed32_key_);
+      uint32 val = sub_message->GetReflection()->GetUInt32(
+          *sub_message, map_fixed32_fixed32_val_);
+      EXPECT_EQ(map.at(key), val);
+    }
+  }
+  {
+    std::map<uint64, uint64> map;
+    map[0] = 0;
+    map[1] = 1;
+    for (int i = 0; i < 2; i++) {
+      sub_message =
+          &reflection->GetRepeatedMessage(message, F("map_fixed64_fixed64"), i);
+      uint64 key = sub_message->GetReflection()->GetUInt64(
+          *sub_message, map_fixed64_fixed64_key_);
+      uint64 val = sub_message->GetReflection()->GetUInt64(
+          *sub_message, map_fixed64_fixed64_val_);
+      EXPECT_EQ(map.at(key), val);
+    }
+  }
+  {
+    std::map<int32, int32> map;
+    map[0] = 0;
+    map[1] = 1;
+    for (int i = 0; i < 2; i++) {
+      sub_message = &reflection->GetRepeatedMessage(
+          message, F("map_sfixed32_sfixed32"), i);
+      int32 key = sub_message->GetReflection()->GetInt32(
+          *sub_message, map_sfixed32_sfixed32_key_);
+      int32 val = sub_message->GetReflection()->GetInt32(
+          *sub_message, map_sfixed32_sfixed32_val_);
+      EXPECT_EQ(map.at(key), val);
+    }
+  }
+  {
+    std::map<int64, int64> map;
+    map[0] = 0;
+    map[1] = 1;
+    for (int i = 0; i < 2; i++) {
+      sub_message = &reflection->GetRepeatedMessage(
+          message, F("map_sfixed64_sfixed64"), i);
+      int64 key = sub_message->GetReflection()->GetInt64(
+          *sub_message, map_sfixed64_sfixed64_key_);
+      int64 val = sub_message->GetReflection()->GetInt64(
+          *sub_message, map_sfixed64_sfixed64_val_);
+      EXPECT_EQ(map.at(key), val);
+    }
+  }
+  {
+    std::map<int32, float> map;
+    map[0] = 0.0;
+    map[1] = 1.0;
+    for (int i = 0; i < 2; i++) {
+      sub_message =
+          &reflection->GetRepeatedMessage(message, F("map_int32_float"), i);
+      int32  key = sub_message->GetReflection()->GetInt32(
+          *sub_message, map_int32_float_key_);
+      float val = sub_message->GetReflection()->GetFloat(
+          *sub_message, map_int32_float_val_);
+      EXPECT_EQ(map.at(key), val);
+    }
+  }
+  {
+    std::map<int32, double> map;
+    map[0] = 0.0;
+    map[1] = 1.0;
+    for (int i = 0; i < 2; i++) {
+      sub_message =
+          &reflection->GetRepeatedMessage(message, F("map_int32_double"), i);
+      int32  key = sub_message->GetReflection()->GetInt32(
+          *sub_message, map_int32_double_key_);
+      double val = sub_message->GetReflection()->GetDouble(
+          *sub_message, map_int32_double_val_);
+      EXPECT_EQ(map.at(key), val);
+    }
+  }
+  {
+    std::map<bool, bool> map;
+    map[false] = false;
+    map[true] = true;
+    for (int i = 0; i < 2; i++) {
+      sub_message =
+          &reflection->GetRepeatedMessage(message, F("map_bool_bool"), i);
+      bool key = sub_message->GetReflection()->GetBool(
+          *sub_message, map_bool_bool_key_);
+      bool val = sub_message->GetReflection()->GetBool(
+          *sub_message, map_bool_bool_val_);
+      EXPECT_EQ(map.at(key), val);
+    }
+  }
+  {
+    std::map<string, string> map;
+    map["0"] = "0";
+    map["1"] = "1";
+    for (int i = 0; i < 2; i++) {
+      sub_message =
+          &reflection->GetRepeatedMessage(message, F("map_string_string"), i);
+      string  key = sub_message->GetReflection()->GetString(
+          *sub_message, map_string_string_key_);
+      string val = sub_message->GetReflection()->GetString(
+          *sub_message, map_string_string_val_);
+      EXPECT_EQ(map.at(key), val);
+    }
+  }
+  {
+    std::map<int32, string> map;
+    map[0] = "0";
+    map[1] = "1";
+    for (int i = 0; i < 2; i++) {
+      sub_message =
+          &reflection->GetRepeatedMessage(message, F("map_int32_bytes"), i);
+      int32  key = sub_message->GetReflection()->GetInt32(
+          *sub_message, map_int32_bytes_key_);
+      string val = sub_message->GetReflection()->GetString(
+          *sub_message, map_int32_bytes_val_);
+      EXPECT_EQ(map.at(key), val);
+    }
+  }
+  {
+    std::map<int32, const EnumValueDescriptor*> map;
+    map[0] = map_enum_bar_;
+    map[1] = map_enum_baz_;
+    for (int i = 0; i < 2; i++) {
+      sub_message = &reflection->GetRepeatedMessage(
+          message, F("map_int32_enum"), i);
+      int32 key = sub_message->GetReflection()->GetInt32(
+          *sub_message, map_int32_enum_key_);
+      const EnumValueDescriptor* val = sub_message->GetReflection()->GetEnum(
+          *sub_message, map_int32_enum_val_);
+      EXPECT_EQ(map.at(key), val);
+    }
+  }
+  {
+    std::map<int32, int32> map;
+    map[0] = 0;
+    map[1] = 1;
+    for (int i = 0; i < 2; i++) {
+      sub_message = &reflection->GetRepeatedMessage(
+          message, F("map_int32_foreign_message"), i);
+      int32  key = sub_message->GetReflection()->GetInt32(
+          *sub_message, map_int32_foreign_message_key_);
+      const Message& foreign_message = sub_message->GetReflection()->GetMessage(
+          *sub_message, map_int32_foreign_message_val_);
+      int32 val = foreign_message.GetReflection()->GetInt32(
+          foreign_message, foreign_c_);
+      EXPECT_EQ(map.at(key), val);
+    }
+  }
+}
+
+void MapTestUtil::MapReflectionTester::ExpectClearViaReflection(
+    const Message& message) {
+  const Reflection* reflection = message.GetReflection();
+  // Map fields are empty.
+  EXPECT_EQ(0, reflection->FieldSize(message, F("map_int32_int32")));
+  EXPECT_EQ(0, reflection->FieldSize(message, F("map_int64_int64")));
+  EXPECT_EQ(0, reflection->FieldSize(message, F("map_uint32_uint32")));
+  EXPECT_EQ(0, reflection->FieldSize(message, F("map_uint64_uint64")));
+  EXPECT_EQ(0, reflection->FieldSize(message, F("map_sint32_sint32")));
+  EXPECT_EQ(0, reflection->FieldSize(message, F("map_sint64_sint64")));
+  EXPECT_EQ(0, reflection->FieldSize(message, F("map_fixed32_fixed32")));
+  EXPECT_EQ(0, reflection->FieldSize(message, F("map_fixed64_fixed64")));
+  EXPECT_EQ(0, reflection->FieldSize(message, F("map_sfixed32_sfixed32")));
+  EXPECT_EQ(0, reflection->FieldSize(message, F("map_sfixed64_sfixed64")));
+  EXPECT_EQ(0, reflection->FieldSize(message, F("map_int32_float")));
+  EXPECT_EQ(0, reflection->FieldSize(message, F("map_int32_double")));
+  EXPECT_EQ(0, reflection->FieldSize(message, F("map_bool_bool")));
+  EXPECT_EQ(0, reflection->FieldSize(message, F("map_string_string")));
+  EXPECT_EQ(0, reflection->FieldSize(message, F("map_int32_bytes")));
+  EXPECT_EQ(0, reflection->FieldSize(message, F("map_int32_enum")));
+  EXPECT_EQ(0, reflection->FieldSize(message, F("map_int32_foreign_message")));
+}
+
+void MapTestUtil::MapReflectionTester::ExpectMapEntryClearViaReflection(
+    Message* message) {
+  const Reflection* reflection = message->GetReflection();
+  const Message* sub_message;
+
+  {
+    const FieldDescriptor* descriptor = F("map_int32_int32");
+    const FieldDescriptor* key_descriptor =
+        descriptor->message_type()->FindFieldByName("key");
+    const FieldDescriptor* value_descriptor =
+        descriptor->message_type()->FindFieldByName("value");
+    sub_message = reflection->AddMessage(message, F("map_int32_int32"));
+    EXPECT_EQ(0, sub_message->GetReflection()->GetInt32(*sub_message,
+                                                        key_descriptor));
+    EXPECT_EQ(0, sub_message->GetReflection()->GetInt32(*sub_message,
+                                                        value_descriptor));
+  }
+  {
+    const FieldDescriptor* descriptor = F("map_int64_int64");
+    const FieldDescriptor* key_descriptor =
+        descriptor->message_type()->FindFieldByName("key");
+    const FieldDescriptor* value_descriptor =
+        descriptor->message_type()->FindFieldByName("value");
+    sub_message = reflection->AddMessage(message, F("map_int64_int64"));
+    EXPECT_EQ(0, sub_message->GetReflection()->GetInt64(*sub_message,
+                                                        key_descriptor));
+    EXPECT_EQ(0, sub_message->GetReflection()->GetInt64(*sub_message,
+                                                        value_descriptor));
+  }
+  {
+    const FieldDescriptor* descriptor = F("map_uint32_uint32");
+    const FieldDescriptor* key_descriptor =
+        descriptor->message_type()->FindFieldByName("key");
+    const FieldDescriptor* value_descriptor =
+        descriptor->message_type()->FindFieldByName("value");
+    sub_message = reflection->AddMessage(message, F("map_uint32_uint32"));
+    EXPECT_EQ(0, sub_message->GetReflection()->GetUInt32(*sub_message,
+                                                         key_descriptor));
+    EXPECT_EQ(0, sub_message->GetReflection()->GetUInt32(*sub_message,
+                                                         value_descriptor));
+  }
+  {
+    const FieldDescriptor* descriptor = F("map_uint64_uint64");
+    const FieldDescriptor* key_descriptor =
+        descriptor->message_type()->FindFieldByName("key");
+    const FieldDescriptor* value_descriptor =
+        descriptor->message_type()->FindFieldByName("value");
+    sub_message = reflection->AddMessage(message, F("map_uint64_uint64"));
+    EXPECT_EQ(0, sub_message->GetReflection()->GetUInt64(*sub_message,
+                                                         key_descriptor));
+    EXPECT_EQ(0, sub_message->GetReflection()->GetUInt64(*sub_message,
+                                                         value_descriptor));
+  }
+  {
+    const FieldDescriptor* descriptor = F("map_sint32_sint32");
+    const FieldDescriptor* key_descriptor =
+        descriptor->message_type()->FindFieldByName("key");
+    const FieldDescriptor* value_descriptor =
+        descriptor->message_type()->FindFieldByName("value");
+    sub_message = reflection->AddMessage(message, F("map_sint32_sint32"));
+    EXPECT_EQ(0, sub_message->GetReflection()->GetInt32(*sub_message,
+                                                        key_descriptor));
+    EXPECT_EQ(0, sub_message->GetReflection()->GetInt32(*sub_message,
+                                                        value_descriptor));
+  }
+  {
+    const FieldDescriptor* descriptor = F("map_sint64_sint64");
+    const FieldDescriptor* key_descriptor =
+        descriptor->message_type()->FindFieldByName("key");
+    const FieldDescriptor* value_descriptor =
+        descriptor->message_type()->FindFieldByName("value");
+    sub_message = reflection->AddMessage(message, F("map_sint64_sint64"));
+    EXPECT_EQ(0, sub_message->GetReflection()->GetInt64(*sub_message,
+                                                        key_descriptor));
+    EXPECT_EQ(0, sub_message->GetReflection()->GetInt64(*sub_message,
+                                                        value_descriptor));
+  }
+  {
+    const FieldDescriptor* descriptor = F("map_fixed32_fixed32");
+    const FieldDescriptor* key_descriptor =
+        descriptor->message_type()->FindFieldByName("key");
+    const FieldDescriptor* value_descriptor =
+        descriptor->message_type()->FindFieldByName("value");
+    sub_message = reflection->AddMessage(message, F("map_fixed32_fixed32"));
+    EXPECT_EQ(0, sub_message->GetReflection()->GetUInt32(*sub_message,
+                                                         key_descriptor));
+    EXPECT_EQ(0, sub_message->GetReflection()->GetUInt32(*sub_message,
+                                                         value_descriptor));
+  }
+  {
+    const FieldDescriptor* descriptor = F("map_fixed64_fixed64");
+    const FieldDescriptor* key_descriptor =
+        descriptor->message_type()->FindFieldByName("key");
+    const FieldDescriptor* value_descriptor =
+        descriptor->message_type()->FindFieldByName("value");
+    sub_message = reflection->AddMessage(message, F("map_fixed64_fixed64"));
+    EXPECT_EQ(0, sub_message->GetReflection()->GetUInt64(*sub_message,
+                                                         key_descriptor));
+    EXPECT_EQ(0, sub_message->GetReflection()->GetUInt64(*sub_message,
+                                                         value_descriptor));
+  }
+  {
+    const FieldDescriptor* descriptor = F("map_sfixed32_sfixed32");
+    const FieldDescriptor* key_descriptor =
+        descriptor->message_type()->FindFieldByName("key");
+    const FieldDescriptor* value_descriptor =
+        descriptor->message_type()->FindFieldByName("value");
+    sub_message = reflection->AddMessage(message, F("map_sfixed32_sfixed32"));
+    EXPECT_EQ(0, sub_message->GetReflection()->GetInt32(*sub_message,
+                                                        key_descriptor));
+    EXPECT_EQ(0, sub_message->GetReflection()->GetInt32(*sub_message,
+                                                        value_descriptor));
+  }
+  {
+    const FieldDescriptor* descriptor = F("map_sfixed64_sfixed64");
+    const FieldDescriptor* key_descriptor =
+        descriptor->message_type()->FindFieldByName("key");
+    const FieldDescriptor* value_descriptor =
+        descriptor->message_type()->FindFieldByName("value");
+    sub_message = reflection->AddMessage(message, F("map_sfixed64_sfixed64"));
+    EXPECT_EQ(0, sub_message->GetReflection()->GetInt64(*sub_message,
+                                                        key_descriptor));
+    EXPECT_EQ(0, sub_message->GetReflection()->GetInt64(*sub_message,
+                                                        value_descriptor));
+  }
+  {
+    const FieldDescriptor* descriptor = F("map_int32_float");
+    const FieldDescriptor* key_descriptor =
+        descriptor->message_type()->FindFieldByName("key");
+    const FieldDescriptor* value_descriptor =
+        descriptor->message_type()->FindFieldByName("value");
+    sub_message = reflection->AddMessage(message, F("map_int32_float"));
+    EXPECT_EQ(0, sub_message->GetReflection()->GetInt32(*sub_message,
+                                                        key_descriptor));
+    EXPECT_EQ(0, sub_message->GetReflection()->GetFloat(*sub_message,
+                                                        value_descriptor));
+  }
+  {
+    const FieldDescriptor* descriptor = F("map_int32_double");
+    const FieldDescriptor* key_descriptor =
+        descriptor->message_type()->FindFieldByName("key");
+    const FieldDescriptor* value_descriptor =
+        descriptor->message_type()->FindFieldByName("value");
+    sub_message = reflection->AddMessage(message, F("map_int32_double"));
+    EXPECT_EQ(0, sub_message->GetReflection()->GetInt32(*sub_message,
+                                                        key_descriptor));
+    EXPECT_EQ(0, sub_message->GetReflection()->GetDouble(*sub_message,
+                                                         value_descriptor));
+  }
+  {
+    const FieldDescriptor* descriptor = F("map_bool_bool");
+    const FieldDescriptor* key_descriptor =
+        descriptor->message_type()->FindFieldByName("key");
+    const FieldDescriptor* value_descriptor =
+        descriptor->message_type()->FindFieldByName("value");
+    sub_message = reflection->AddMessage(message, F("map_bool_bool"));
+    EXPECT_EQ(false, sub_message->GetReflection()->GetBool(*sub_message,
+                                                           key_descriptor));
+    EXPECT_EQ(false, sub_message->GetReflection()->GetBool(*sub_message,
+                                                           value_descriptor));
+  }
+  {
+    const FieldDescriptor* descriptor = F("map_string_string");
+    const FieldDescriptor* key_descriptor =
+        descriptor->message_type()->FindFieldByName("key");
+    const FieldDescriptor* value_descriptor =
+        descriptor->message_type()->FindFieldByName("value");
+    sub_message = reflection->AddMessage(message, F("map_string_string"));
+    EXPECT_EQ("", sub_message->GetReflection()->GetString(*sub_message,
+                                                          key_descriptor));
+    EXPECT_EQ("", sub_message->GetReflection()->GetString(*sub_message,
+                                                          value_descriptor));
+  }
+  {
+    const FieldDescriptor* descriptor = F("map_int32_bytes");
+    const FieldDescriptor* key_descriptor =
+        descriptor->message_type()->FindFieldByName("key");
+    const FieldDescriptor* value_descriptor =
+        descriptor->message_type()->FindFieldByName("value");
+    sub_message = reflection->AddMessage(message, F("map_int32_bytes"));
+    EXPECT_EQ(0, sub_message->GetReflection()->GetInt32(*sub_message,
+                                                        key_descriptor));
+    EXPECT_EQ("", sub_message->GetReflection()->GetString(*sub_message,
+                                                        value_descriptor));
+  }
+  {
+    const FieldDescriptor* descriptor = F("map_int32_enum");
+    const FieldDescriptor* key_descriptor =
+        descriptor->message_type()->FindFieldByName("key");
+    const FieldDescriptor* value_descriptor =
+        descriptor->message_type()->FindFieldByName("value");
+    sub_message = reflection->AddMessage(message, F("map_int32_enum"));
+    EXPECT_EQ(0, sub_message->GetReflection()->GetInt32(*sub_message,
+                                                        key_descriptor));
+    EXPECT_EQ(0, sub_message->GetReflection()->GetEnum(*sub_message,
+                                                        value_descriptor));
+  }
+  // Map using message as value has been tested in other place. Thus, we don't
+  // test it here.
+}
+
+}  // namespace protobuf
+}  // namespace google

+ 149 - 0
src/google/protobuf/map_test_util.h

@@ -0,0 +1,149 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_MAP_TEST_UTIL_H__
+#define GOOGLE_PROTOBUF_MAP_TEST_UTIL_H__
+
+#include <google/protobuf/map_unittest.pb.h>
+
+namespace google {
+namespace protobuf {
+
+namespace unittest = ::protobuf_unittest;
+
+class MapTestUtil {
+ public:
+  // Set every field in the message to a unique value.
+  static void SetMapFields(unittest::TestMap* message);
+
+  // Set every field in the message to a default value.
+  static void SetMapFieldsInitialized(unittest::TestMap* message);
+
+  // Modify all the map fields of the messsage (which should already have been
+  // initialized with SetMapFields()).
+  static void ModifyMapFields(unittest::TestMap* message);
+
+  // Check that all fields have the values that they should have after
+  // SetMapFields() is called.
+  static void ExpectMapFieldsSet(const unittest::TestMap& message);
+
+  // Check that all fields have the values that they should have after
+  // SetMapFieldsInitialized() is called.
+  static void ExpectMapFieldsSetInitialized(
+      const unittest::TestMap& message);
+
+  // Expect that the message is modified as would be expected from
+  // ModifyMapFields().
+  static void ExpectMapFieldsModified(const unittest::TestMap& message);
+
+  // Check that all fields are empty.
+  static void ExpectClear(const unittest::TestMap& message);
+
+  // Check that all map fields have the given size.
+  static void ExpectMapsSize(const unittest::TestMap& message, int size);
+
+  // Get pointers of map entries at given index.
+  static std::vector<const Message*> GetMapEntries(
+      const unittest::TestMap& message, int index);
+
+  // Get pointers of map entries from release.
+  static std::vector<const Message*> GetMapEntriesFromRelease(
+      unittest::TestMap* message);
+
+  // Like above, but use the reflection interface.
+  class MapReflectionTester {
+   public:
+    // base_descriptor must be a descriptor for TestMap, which is used for
+    // MapReflectionTester to fetch the FieldDescriptors needed to use the
+    // reflection interface.
+    explicit MapReflectionTester(const Descriptor* base_descriptor);
+
+    void SetMapFieldsViaReflection(Message* message);
+    void ClearMapFieldsViaReflection(Message* message);
+    void ModifyMapFieldsViaReflection(Message* message);
+    void RemoveLastMapsViaReflection(Message* message);
+    void ReleaseLastMapsViaReflection(Message* message);
+    void SwapMapsViaReflection(Message* message);
+    void MutableUnknownFieldsOfMapFieldsViaReflection(Message* message);
+    void ExpectMapFieldsSetViaReflection(const Message& message);
+    void ExpectClearViaReflection(const Message& message);
+    void ExpectMapEntryClearViaReflection(Message* message);
+
+   private:
+    const FieldDescriptor* F(const string& name);
+
+    const Descriptor* base_descriptor_;
+
+    const EnumValueDescriptor* map_enum_bar_;
+    const EnumValueDescriptor* map_enum_baz_;
+    const EnumValueDescriptor* map_enum_foo_;
+
+    const FieldDescriptor* foreign_c_;
+    const FieldDescriptor* map_int32_int32_key_;
+    const FieldDescriptor* map_int32_int32_val_;
+    const FieldDescriptor* map_int64_int64_key_;
+    const FieldDescriptor* map_int64_int64_val_;
+    const FieldDescriptor* map_uint32_uint32_key_;
+    const FieldDescriptor* map_uint32_uint32_val_;
+    const FieldDescriptor* map_uint64_uint64_key_;
+    const FieldDescriptor* map_uint64_uint64_val_;
+    const FieldDescriptor* map_sint32_sint32_key_;
+    const FieldDescriptor* map_sint32_sint32_val_;
+    const FieldDescriptor* map_sint64_sint64_key_;
+    const FieldDescriptor* map_sint64_sint64_val_;
+    const FieldDescriptor* map_fixed32_fixed32_key_;
+    const FieldDescriptor* map_fixed32_fixed32_val_;
+    const FieldDescriptor* map_fixed64_fixed64_key_;
+    const FieldDescriptor* map_fixed64_fixed64_val_;
+    const FieldDescriptor* map_sfixed32_sfixed32_key_;
+    const FieldDescriptor* map_sfixed32_sfixed32_val_;
+    const FieldDescriptor* map_sfixed64_sfixed64_key_;
+    const FieldDescriptor* map_sfixed64_sfixed64_val_;
+    const FieldDescriptor* map_int32_float_key_;
+    const FieldDescriptor* map_int32_float_val_;
+    const FieldDescriptor* map_int32_double_key_;
+    const FieldDescriptor* map_int32_double_val_;
+    const FieldDescriptor* map_bool_bool_key_;
+    const FieldDescriptor* map_bool_bool_val_;
+    const FieldDescriptor* map_string_string_key_;
+    const FieldDescriptor* map_string_string_val_;
+    const FieldDescriptor* map_int32_bytes_key_;
+    const FieldDescriptor* map_int32_bytes_val_;
+    const FieldDescriptor* map_int32_enum_key_;
+    const FieldDescriptor* map_int32_enum_val_;
+    const FieldDescriptor* map_int32_foreign_message_key_;
+    const FieldDescriptor* map_int32_foreign_message_val_;
+  };
+};
+
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_MAP_TEST_UTIL_H__

+ 486 - 0
src/google/protobuf/map_type_handler.h

@@ -0,0 +1,486 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_TYPE_HANDLER_H__
+#define GOOGLE_PROTOBUF_TYPE_HANDLER_H__
+
+#include <google/protobuf/generated_message_util.h>
+#include <google/protobuf/message.h>
+#include <google/protobuf/wire_format_lite_inl.h>
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+// Used for compile time type selection. MapIf::type will be TrueType if Flag is
+// true and FalseType otherwise.
+template<bool Flag, typename TrueType, typename FalseType>
+struct MapIf;
+
+template<typename TrueType, typename FalseType>
+struct MapIf<true, TrueType, FalseType> {
+  typedef TrueType type;
+};
+
+template<typename TrueType, typename FalseType>
+struct MapIf<false, TrueType, FalseType> {
+  typedef FalseType type;
+};
+
+// In MapField, string and message are stored as pointer while others are stored
+// as object. However, google::protobuf::Map has unified api. Functions in this class
+// convert key/value to type wanted in api regardless how it's stored
+// internally.
+template <typename Type>
+class MapCommonTypeHandler {
+ public:
+  static inline Type& Reference(Type* x) { return *x; }
+  static inline Type& Reference(Type& x) { return x; }
+  static inline const Type& Reference(const Type& x) { return x; }
+  static inline Type* Pointer(Type* x) { return x; }
+  static inline Type* Pointer(Type& x) { return &x; }
+  static inline const Type* Pointer(const Type* x) { return x; }
+  static inline const Type* Pointer(const Type& x) { return &x; }
+};
+
+// In proto2 Map, enum needs to be initialized to given default value, while
+// other types' default value can be inferred from the type.
+template <bool IsEnum, typename Type>
+class MapValueInitializer {
+ public:
+  static inline void Initialize(Type& type, int default_enum_value);
+};
+
+template <typename Type>
+class MapValueInitializer<true, Type> {
+ public:
+  static inline void Initialize(Type& value, int default_enum_value) {
+    value = static_cast<Type>(default_enum_value);
+  }
+};
+
+template <typename Type>
+class MapValueInitializer<false, Type> {
+ public:
+  static inline void Initialize(Type& value, int default_enum_value) {}
+};
+
+// Handlers for key/value stored type in MapField. ==================
+
+// Handler for message
+template <typename Type>
+class MapCppTypeHandler : public MapCommonTypeHandler<Type> {
+ public:
+  static const bool kIsStringOrMessage = true;
+  // SpaceUsedInMapEntry: Return bytes used by value in MapEntry, excluding
+  // those already calculate in sizeof(MapField).
+  static int SpaceUsedInMapEntry(const Type* value) {
+    return value->SpaceUsed();
+  }
+  // Return bytes used by value in Map.
+  static int SpaceUsedInMap(const Type& value) { return value.SpaceUsed(); }
+  static inline void Clear(Type** value) {
+    if (*value != NULL) (*value)->Type::Clear();
+  }
+  static inline void ClearMaybeByDefaultEnum(Type** value,
+                                             int default_enum_value) {
+    if (*value != NULL) (*value)->Type::Clear();
+  }
+  static inline void Merge(const Type& from, Type** to) {
+    (*to)->MergeFrom(from);
+  }
+
+  static void Delete(const Type* ptr) { delete ptr; }
+
+  // Assign default value to given instance.
+  static inline void AssignDefaultValue(Type** value) {
+    *value = const_cast<Type*>(&Type::default_instance());
+  }
+  // Initialize value when constructing MapEntry
+  static inline void Initialize(Type** x) { *x = NULL; }
+  // Same as above, but use default_enum_value to initialize enum type value.
+  static inline void InitializeMaybeByDefaultEnum(
+      Type** x, int default_enum_value) {
+    *x = NULL;
+  }
+  // Initialize value for the first time mutable accessor is called.
+  static inline void EnsureMutable(Type** value) {
+    if (*value == NULL) *value = new Type;
+  }
+  // Return default instance if value is not initialized when calling const
+  // reference accessor.
+  static inline const Type& DefaultIfNotInitialized(Type* value,
+                                                    Type* default_value) {
+    return value != NULL ? *value : *default_value;
+  }
+  // Check if all required fields have values set.
+  static inline bool IsInitialized(Type* value) {
+    return value->IsInitialized();
+  }
+};
+
+// Handler for string.
+template <>
+class MapCppTypeHandler<string> : public MapCommonTypeHandler<string> {
+ public:
+  static const bool kIsStringOrMessage = true;
+  static inline void Merge(const string& from, string** to) { **to = from; }
+  static inline void Clear(string** value) { (*value)->clear(); }
+  static inline void ClearMaybeByDefaultEnum(string** value, int default_enum) {
+    (*value)->clear();
+  }
+  static inline int SpaceUsedInMapEntry(const string* value) {
+    return sizeof(*value) + StringSpaceUsedExcludingSelf(*value);
+  }
+  static inline int SpaceUsedInMap(const string& value) {
+    return sizeof(value) + StringSpaceUsedExcludingSelf(value);
+  }
+  static void Delete(const string* ptr) {
+    if (ptr != &::google::protobuf::internal::GetEmptyString()) delete ptr;
+  }
+  static inline void AssignDefaultValue(string** value) {}
+  static inline void Initialize(string** value) {
+    *value = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
+  }
+  static inline void InitializeMaybeByDefaultEnum(
+      string** value, int default_enum_value) {
+    *value = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
+  }
+  static inline void EnsureMutable(string** value) {
+    if (*value == &::google::protobuf::internal::GetEmptyString()) *value = new string;
+  }
+  static inline const string& DefaultIfNotInitialized(string* value,
+                                                      string* default_value) {
+    return value != default_value ? *value : *default_value;
+  }
+  static inline bool IsInitialized(string* value) { return true; }
+};
+
+// Base class for primitive type handlers.
+template <typename Type>
+class MapPrimitiveTypeHandler : public MapCommonTypeHandler<Type> {
+ public:
+  static const bool kIsStringOrMessage = false;
+  static inline void Delete(const Type& x) {}
+  static inline void Merge(const Type& from, Type* to) { *to = from; }
+  static inline int SpaceUsedInMapEntry(const Type& value) { return 0; }
+  static inline int SpaceUsedInMap(const Type& value) { return sizeof(Type); }
+  static inline void AssignDefaultValue(Type* value) {}
+  static inline const Type& DefaultIfNotInitialized(
+      const Type& value, const Type& default_value) {
+    return value;
+  }
+  static inline bool IsInitialized(const Type& value) { return true; }
+};
+
+// Handlers for primitive types.
+#define PRIMITIVE_HANDLER(CType)                                              \
+  template <>                                                                 \
+  class MapCppTypeHandler<CType> : public MapPrimitiveTypeHandler<CType> {    \
+   public:                                                                    \
+    static inline void Clear(CType* value) { *value = 0; }                    \
+    static inline void ClearMaybeByDefaultEnum(CType* value,                  \
+                                               int default_enum_value) {      \
+      *value = static_cast<CType>(default_enum_value);                        \
+    }                                                                         \
+    static inline void Initialize(CType* value) { *value = 0; }               \
+    static inline void InitializeMaybeByDefaultEnum(CType* value,             \
+                                                    int default_enum_value) { \
+      *value = static_cast<CType>(default_enum_value);                        \
+    }                                                                         \
+    static inline void EnsureMutable(CType* value) {}                         \
+  };
+
+PRIMITIVE_HANDLER(int32 )
+PRIMITIVE_HANDLER(int64 )
+PRIMITIVE_HANDLER(uint32)
+PRIMITIVE_HANDLER(uint64)
+PRIMITIVE_HANDLER(double)
+PRIMITIVE_HANDLER(float )
+PRIMITIVE_HANDLER(bool  )
+
+#undef PRIMITIVE_HANDLER
+
+// Define constants for given proto field type
+template <FieldDescriptor::Type Type>
+class MapFieldTypeTraits {};
+
+#define TYPE_TRAITS(FieldType, CType, WireFormatType, IsMessage, IsEnum) \
+  template <>                                                            \
+  class MapFieldTypeTraits<FieldDescriptor::TYPE_##FieldType> {          \
+   public:                                                               \
+    typedef CType CppType;                                               \
+    static const bool kIsMessage = IsMessage;                            \
+    static const bool kIsEnum = IsEnum;                                  \
+    static const WireFormatLite::WireType kWireType =                    \
+        WireFormatLite::WIRETYPE_##WireFormatType;                       \
+  };
+
+TYPE_TRAITS(MESSAGE , Message,  LENGTH_DELIMITED, true, false)
+TYPE_TRAITS(STRING  , string ,  LENGTH_DELIMITED, false, false)
+TYPE_TRAITS(BYTES   , string ,  LENGTH_DELIMITED, false, false)
+TYPE_TRAITS(INT64   , int64  ,  VARINT , false, false)
+TYPE_TRAITS(UINT64  , uint64 ,  VARINT , false, false)
+TYPE_TRAITS(INT32   , int32  ,  VARINT , false, false)
+TYPE_TRAITS(UINT32  , uint32 ,  VARINT , false, false)
+TYPE_TRAITS(SINT64  , int64  ,  VARINT , false, false)
+TYPE_TRAITS(SINT32  , int32  ,  VARINT , false, false)
+TYPE_TRAITS(ENUM    , int    ,  VARINT , false, true )
+TYPE_TRAITS(DOUBLE  , double ,  FIXED64, false, false)
+TYPE_TRAITS(FLOAT   , float  ,  FIXED32, false, false)
+TYPE_TRAITS(FIXED64 , uint64 ,  FIXED64, false, false)
+TYPE_TRAITS(FIXED32 , uint32 ,  FIXED32, false, false)
+TYPE_TRAITS(SFIXED64, int64  ,  FIXED64, false, false)
+TYPE_TRAITS(SFIXED32, int32  ,  FIXED32, false, false)
+TYPE_TRAITS(BOOL    , bool   ,  VARINT , false, false)
+
+#undef TYPE_TRAITS
+
+// Handler for proto field type. Define types and constants used in compile
+// time. Also define functions used in parsing and serializing.
+template <FieldDescriptor::Type Type>
+class MapProtoTypeHandler {
+ public:
+  // Internal stored type in MapEntry for given proto field type.
+  typedef typename MapFieldTypeTraits<Type>::CppType CppType;
+
+  // Whether given type is a message.
+  static const bool kIsMessage = MapFieldTypeTraits<Type>::kIsMessage;
+
+  // Whether given type is an enum.
+  static const bool kIsEnum = MapFieldTypeTraits<Type>::kIsEnum;
+
+  // The wire type of given proto field type.
+  static const WireFormatLite::WireType kWireType =
+      MapFieldTypeTraits<Type>::kWireType;
+
+  // Functions used in parsing and serialization. ===================
+
+  template <typename ValueType>
+  static inline int ByteSize(const ValueType& value);
+  template <typename ValueType>
+  static inline int GetCachedSize(const ValueType& value);
+  static inline void Write(int field, const CppType& value,
+                           io::CodedOutputStream* output);
+  static inline uint8* WriteToArray(int field, const CppType& value,
+                                    uint8* output);
+  template <typename ValueType>
+  static inline bool Read(io::CodedInputStream* input, ValueType* value);
+};
+
+template <>
+template <typename ValueType>
+inline int MapProtoTypeHandler<FieldDescriptor::TYPE_MESSAGE>::ByteSize(
+    const ValueType& value) {
+  return WireFormatLite::MessageSizeNoVirtual(value);
+}
+
+#define BYTE_SIZE(FieldType, DeclaredType)                                     \
+  template <>                                                                  \
+  template <typename ValueType>                                                \
+  inline int MapProtoTypeHandler<FieldDescriptor::TYPE_##FieldType>::ByteSize( \
+      const ValueType& value) {                                                \
+    return WireFormatLite::DeclaredType##Size(value);                          \
+  }
+
+BYTE_SIZE(STRING, String)
+BYTE_SIZE(BYTES , Bytes)
+BYTE_SIZE(INT64 , Int64)
+BYTE_SIZE(UINT64, UInt64)
+BYTE_SIZE(INT32 , Int32)
+BYTE_SIZE(UINT32, UInt32)
+BYTE_SIZE(SINT64, SInt64)
+BYTE_SIZE(SINT32, SInt32)
+BYTE_SIZE(ENUM  , Enum)
+
+#undef BYTE_SIZE
+
+#define FIXED_BYTE_SIZE(FieldType, DeclaredType)                               \
+  template <>                                                                  \
+  template <typename ValueType>                                                \
+  inline int MapProtoTypeHandler<FieldDescriptor::TYPE_##FieldType>::ByteSize( \
+      const ValueType& value) {                                                \
+    return WireFormatLite::k##DeclaredType##Size;                              \
+  }
+
+FIXED_BYTE_SIZE(DOUBLE  , Double)
+FIXED_BYTE_SIZE(FLOAT   , Float)
+FIXED_BYTE_SIZE(FIXED64 , Fixed64)
+FIXED_BYTE_SIZE(FIXED32 , Fixed32)
+FIXED_BYTE_SIZE(SFIXED64, SFixed64)
+FIXED_BYTE_SIZE(SFIXED32, SFixed32)
+FIXED_BYTE_SIZE(BOOL    , Bool)
+
+#undef FIXED_BYTE_SIZE
+
+template <>
+template <typename ValueType>
+inline int MapProtoTypeHandler<FieldDescriptor::TYPE_MESSAGE>::GetCachedSize(
+    const ValueType& value) {
+  return WireFormatLite::LengthDelimitedSize(value.GetCachedSize());
+}
+
+#define GET_CACHED_SIZE(FieldType, DeclaredType)                         \
+  template <>                                                            \
+  template <typename ValueType>                                          \
+  inline int                                                             \
+  MapProtoTypeHandler<FieldDescriptor::TYPE_##FieldType>::GetCachedSize( \
+      const ValueType& value) {                                          \
+    return WireFormatLite::DeclaredType##Size(value);                    \
+  }
+
+GET_CACHED_SIZE(STRING, String)
+GET_CACHED_SIZE(BYTES , Bytes)
+GET_CACHED_SIZE(INT64 , Int64)
+GET_CACHED_SIZE(UINT64, UInt64)
+GET_CACHED_SIZE(INT32 , Int32)
+GET_CACHED_SIZE(UINT32, UInt32)
+GET_CACHED_SIZE(SINT64, SInt64)
+GET_CACHED_SIZE(SINT32, SInt32)
+GET_CACHED_SIZE(ENUM  , Enum)
+
+#undef GET_CACHED_SIZE
+
+#define GET_FIXED_CACHED_SIZE(FieldType, DeclaredType)                   \
+  template <>                                                            \
+  template <typename ValueType>                                          \
+  inline int                                                             \
+  MapProtoTypeHandler<FieldDescriptor::TYPE_##FieldType>::GetCachedSize( \
+      const ValueType& value) {                                          \
+    return WireFormatLite::k##DeclaredType##Size;                        \
+  }
+
+GET_FIXED_CACHED_SIZE(DOUBLE  , Double)
+GET_FIXED_CACHED_SIZE(FLOAT   , Float)
+GET_FIXED_CACHED_SIZE(FIXED64 , Fixed64)
+GET_FIXED_CACHED_SIZE(FIXED32 , Fixed32)
+GET_FIXED_CACHED_SIZE(SFIXED64, SFixed64)
+GET_FIXED_CACHED_SIZE(SFIXED32, SFixed32)
+GET_FIXED_CACHED_SIZE(BOOL    , Bool)
+
+#undef GET_FIXED_CACHED_SIZE
+
+template <>
+inline void MapProtoTypeHandler<FieldDescriptor::TYPE_MESSAGE>::Write(
+    int field, const Message& value, io::CodedOutputStream* output) {
+  WireFormatLite::WriteMessageMaybeToArray(field, value, output);
+}
+
+template <>
+inline uint8* MapProtoTypeHandler<FieldDescriptor::TYPE_MESSAGE>::WriteToArray(
+    int field, const Message& value, uint8* output) {
+  return WireFormatLite::WriteMessageToArray(field, value, output);
+}
+
+#define WRITE_METHOD(FieldType, DeclaredType)                                  \
+  template <>                                                                  \
+  inline void MapProtoTypeHandler<FieldDescriptor::TYPE_##FieldType>::Write(   \
+      int field, const CppType& value, io::CodedOutputStream* output) {        \
+    return WireFormatLite::Write##DeclaredType(field, value, output);          \
+  }                                                                            \
+  template <>                                                                  \
+  inline uint8*                                                                \
+  MapProtoTypeHandler<FieldDescriptor::TYPE_##FieldType>::WriteToArray(        \
+      int field, const CppType& value, uint8* output) {                        \
+    return WireFormatLite::Write##DeclaredType##ToArray(field, value, output); \
+  }
+
+WRITE_METHOD(STRING  , String)
+WRITE_METHOD(BYTES   , Bytes)
+WRITE_METHOD(INT64   , Int64)
+WRITE_METHOD(UINT64  , UInt64)
+WRITE_METHOD(INT32   , Int32)
+WRITE_METHOD(UINT32  , UInt32)
+WRITE_METHOD(SINT64  , SInt64)
+WRITE_METHOD(SINT32  , SInt32)
+WRITE_METHOD(ENUM    , Enum)
+WRITE_METHOD(DOUBLE  , Double)
+WRITE_METHOD(FLOAT   , Float)
+WRITE_METHOD(FIXED64 , Fixed64)
+WRITE_METHOD(FIXED32 , Fixed32)
+WRITE_METHOD(SFIXED64, SFixed64)
+WRITE_METHOD(SFIXED32, SFixed32)
+WRITE_METHOD(BOOL    , Bool)
+
+#undef WRITE_METHOD
+
+template <>
+template <typename ValueType>
+inline bool MapProtoTypeHandler<FieldDescriptor::TYPE_MESSAGE>::Read(
+    io::CodedInputStream* input, ValueType* value) {
+  return WireFormatLite::ReadMessageNoVirtual(input, value);
+}
+
+template <>
+template <typename ValueType>
+inline bool MapProtoTypeHandler<FieldDescriptor::TYPE_STRING>::Read(
+    io::CodedInputStream* input, ValueType* value) {
+  return WireFormatLite::ReadString(input, value);
+}
+
+template <>
+template <typename ValueType>
+inline bool MapProtoTypeHandler<FieldDescriptor::TYPE_BYTES>::Read(
+    io::CodedInputStream* input, ValueType* value) {
+  return WireFormatLite::ReadBytes(input, value);
+}
+
+#define READ_METHOD(FieldType)                                              \
+  template <>                                                               \
+  template <typename ValueType>                                             \
+  inline bool MapProtoTypeHandler<FieldDescriptor::TYPE_##FieldType>::Read( \
+      io::CodedInputStream* input, ValueType* value) {                      \
+    return WireFormatLite::ReadPrimitive<CppType,                           \
+                                         WireFormatLite::TYPE_##FieldType>( \
+        input, value);                                                      \
+  }
+
+READ_METHOD(INT64)
+READ_METHOD(UINT64)
+READ_METHOD(INT32)
+READ_METHOD(UINT32)
+READ_METHOD(SINT64)
+READ_METHOD(SINT32)
+READ_METHOD(ENUM)
+READ_METHOD(DOUBLE)
+READ_METHOD(FLOAT)
+READ_METHOD(FIXED64)
+READ_METHOD(FIXED32)
+READ_METHOD(SFIXED64)
+READ_METHOD(SFIXED32)
+READ_METHOD(BOOL)
+
+#undef READ_METHOD
+
+}  // namespace internal
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_TYPE_HANDLER_H__

+ 77 - 0
src/google/protobuf/map_unittest.proto

@@ -0,0 +1,77 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto3";
+
+
+import "google/protobuf/unittest.proto";
+
+// We don't put this in a package within proto2 because we need to make sure
+// that the generated code doesn't depend on being in the proto2 namespace.
+// In map_test_util.h we do "using namespace unittest = protobuf_unittest".
+package protobuf_unittest;
+
+// Tests maps.
+message TestMap {
+  map<int32   , int32   > map_int32_int32       = 1;
+  map<int64   , int64   > map_int64_int64       = 2;
+  map<uint32  , uint32  > map_uint32_uint32     = 3;
+  map<uint64  , uint64  > map_uint64_uint64     = 4;
+  map<sint32  , sint32  > map_sint32_sint32     = 5;
+  map<sint64  , sint64  > map_sint64_sint64     = 6;
+  map<fixed32 , fixed32 > map_fixed32_fixed32   = 7;
+  map<fixed64 , fixed64 > map_fixed64_fixed64   = 8;
+  map<sfixed32, sfixed32> map_sfixed32_sfixed32 = 9;
+  map<sfixed64, sfixed64> map_sfixed64_sfixed64 = 10;
+  map<int32   , float   > map_int32_float       = 11;
+  map<int32   , double  > map_int32_double      = 12;
+  map<bool    , bool    > map_bool_bool         = 13;
+  map<string  , string  > map_string_string     = 14;
+  map<int32   , bytes   > map_int32_bytes       = 15;
+  map<int32   , MapEnum > map_int32_enum        = 16;
+  map<int32   , ForeignMessage> map_int32_foreign_message = 17;
+}
+
+message TestMessageMap {
+  map<int32, TestAllTypes> map_int32_message = 1;
+}
+
+// Two map fields share the same entry default instance.
+message TestSameTypeMap {
+  map<int32, int32> map1 = 1;
+  map<int32, int32> map2 = 2;
+}
+
+
+enum MapEnum {
+  MAP_ENUM_FOO = 0;
+  MAP_ENUM_BAR = 1;
+  MAP_ENUM_BAZ = 2;
+}

+ 5 - 1
src/google/protobuf/message.cc

@@ -430,7 +430,11 @@ const internal::RepeatedFieldAccessor* Reflection::RepeatedFieldAccessor(
       }
       }
       break;
       break;
     case FieldDescriptor::CPPTYPE_MESSAGE:
     case FieldDescriptor::CPPTYPE_MESSAGE:
-      return internal::Singleton<internal::RepeatedPtrFieldMessageAccessor>::get();
+      if (field->is_map()) {
+        return internal::Singleton<internal::MapFieldAccessor>::get();
+      } else {
+        return internal::Singleton<internal::RepeatedPtrFieldMessageAccessor>::get();
+      }
   }
   }
   GOOGLE_LOG(FATAL) << "Should not reach here.";
   GOOGLE_LOG(FATAL) << "Should not reach here.";
   return NULL;
   return NULL;

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

@@ -110,7 +110,7 @@ TEST(PreserveUnknownEnumTest, PreserveParseAndSerializeDynamicMessage) {
   string serialized = orig_message.SerializeAsString();
   string serialized = orig_message.SerializeAsString();
 
 
   google::protobuf::DynamicMessageFactory factory;
   google::protobuf::DynamicMessageFactory factory;
-  scoped_ptr<google::protobuf::Message> message(factory.GetPrototype(
+  google::protobuf::scoped_ptr<google::protobuf::Message> message(factory.GetPrototype(
       proto2_preserve_unknown_enum_unittest::MyMessage::descriptor())->New());
       proto2_preserve_unknown_enum_unittest::MyMessage::descriptor())->New());
   EXPECT_EQ(true, message->ParseFromString(serialized));
   EXPECT_EQ(true, message->ParseFromString(serialized));
   message->DiscardUnknownFields();
   message->DiscardUnknownFields();

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

@@ -175,7 +175,7 @@ TEST(ArenaTest, ReleaseMessage) {
   Arena arena;
   Arena arena;
   TestAllTypes* arena_message = Arena::CreateMessage<TestAllTypes>(&arena);
   TestAllTypes* arena_message = Arena::CreateMessage<TestAllTypes>(&arena);
   arena_message->mutable_optional_nested_message()->set_bb(118);
   arena_message->mutable_optional_nested_message()->set_bb(118);
-  scoped_ptr<TestAllTypes::NestedMessage> nested(
+  google::protobuf::scoped_ptr<TestAllTypes::NestedMessage> nested(
       arena_message->release_optional_nested_message());
       arena_message->release_optional_nested_message());
   EXPECT_EQ(118, nested->bb());
   EXPECT_EQ(118, nested->bb());
 }
 }

+ 68 - 0
src/google/protobuf/reflection_internal.h

@@ -31,6 +31,7 @@
 #ifndef GOOGLE_PROTOBUF_REFLECTION_INTERNAL_H__
 #ifndef GOOGLE_PROTOBUF_REFLECTION_INTERNAL_H__
 #define GOOGLE_PROTOBUF_REFLECTION_INTERNAL_H__
 #define GOOGLE_PROTOBUF_REFLECTION_INTERNAL_H__
 
 
+#include <google/protobuf/map_field.h>
 #include <google/protobuf/reflection.h>
 #include <google/protobuf/reflection.h>
 #include <google/protobuf/repeated_field.h>
 #include <google/protobuf/repeated_field.h>
 
 
@@ -199,6 +200,73 @@ class RepeatedPtrFieldWrapper : public RandomAccessRepeatedFieldAccessor {
                                     Value* scratch_space) const = 0;
                                     Value* scratch_space) const = 0;
 };
 };
 
 
+// An implementation of RandomAccessRepeatedFieldAccessor that manipulates
+// MapFieldBase.
+class MapFieldAccessor : public RandomAccessRepeatedFieldAccessor {
+ public:
+  MapFieldAccessor() {}
+  virtual ~MapFieldAccessor() {}
+  virtual bool IsEmpty(const Field* data) const {
+    return GetRepeatedField(data)->empty();
+  }
+  virtual int Size(const Field* data) const {
+    return GetRepeatedField(data)->size();
+  }
+  virtual const Value* Get(const Field* data, int index,
+                           Value* scratch_space) const {
+    return ConvertFromEntry(GetRepeatedField(data)->Get(index), scratch_space);
+  }
+  virtual void Clear(Field* data) const {
+    MutableRepeatedField(data)->Clear();
+  }
+  virtual void Set(Field* data, int index, const Value* value) const {
+    ConvertToEntry(value, MutableRepeatedField(data)->Mutable(index));
+  }
+  virtual void Add(Field* data, const Value* value) const {
+    Message* allocated = New(value);
+    ConvertToEntry(value, allocated);
+    MutableRepeatedField(data)->AddAllocated(allocated);
+  }
+  virtual void RemoveLast(Field* data) const {
+    MutableRepeatedField(data)->RemoveLast();
+  }
+  virtual void SwapElements(Field* data, int index1, int index2) const {
+    MutableRepeatedField(data)->SwapElements(index1, index2);
+  }
+  virtual void Swap(
+      Field* data,
+      const internal::RepeatedFieldAccessor* other_mutator,
+      Field* other_data) const {
+    GOOGLE_CHECK(this == other_mutator);
+    MutableRepeatedField(data)->Swap(MutableRepeatedField(other_data));
+  }
+
+ protected:
+  typedef RepeatedPtrField<Message> RepeatedFieldType;
+  static const RepeatedFieldType* GetRepeatedField(const Field* data) {
+    return reinterpret_cast<const RepeatedFieldType*>(
+        (&reinterpret_cast<const MapFieldBase*>(data)->GetRepeatedField()));
+  }
+  static RepeatedFieldType* MutableRepeatedField(Field* data) {
+    return reinterpret_cast<RepeatedFieldType*>(
+        reinterpret_cast<MapFieldBase*>(data)->MutableRepeatedField());
+  }
+  virtual Message* New(const Value* value) const {
+    return static_cast<const Message*>(value)->New();
+  }
+  // Convert an object received by this accessor to an MapEntry message to be
+  // stored in the underlying MapFieldBase.
+  virtual void ConvertToEntry(const Value* value, Message* result) const {
+    result->CopyFrom(*static_cast<const Message*>(value));
+  }
+  // Convert a MapEntry message stored in the underlying MapFieldBase to an
+  // object that will be returned by this accessor.
+  virtual const Value* ConvertFromEntry(const Message& value,
+                                        Value* scratch_space) const {
+    return static_cast<const Value*>(&value);
+  }
+};
+
 // Default implementations of RepeatedFieldAccessor for primitive types.
 // Default implementations of RepeatedFieldAccessor for primitive types.
 template<typename T>
 template<typename T>
 class RepeatedFieldPrimitiveAccessor : public RepeatedFieldWrapper<T> {
 class RepeatedFieldPrimitiveAccessor : public RepeatedFieldWrapper<T> {

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

@@ -86,7 +86,7 @@ inline int CalculateReserve(Iter begin, Iter end, std::forward_iterator_tag) {
 
 
 template <typename Iter>
 template <typename Iter>
 inline int CalculateReserve(Iter /*begin*/, Iter /*end*/,
 inline int CalculateReserve(Iter /*begin*/, Iter /*end*/,
-                            std::input_iterator_tag) {
+                            std::input_iterator_tag /*unused*/) {
   return -1;
   return -1;
 }
 }
 
 
@@ -349,6 +349,11 @@ class LIBPROTOBUF_EXPORT RepeatedPtrFieldBase {
   // use of AddFromCleared(), which is not part of the public interface.
   // use of AddFromCleared(), which is not part of the public interface.
   friend class ExtensionSet;
   friend class ExtensionSet;
 
 
+  // The MapFieldBase implementation needs to call protected methods directly,
+  // reinterpreting pointers as being to Message instead of a specific Message
+  // subclass.
+  friend class MapFieldBase;
+
   // To parse directly into a proto2 generated class, the upb class GMR_Handlers
   // To parse directly into a proto2 generated class, the upb class GMR_Handlers
   // needs to be able to modify a RepeatedPtrFieldBase directly.
   // needs to be able to modify a RepeatedPtrFieldBase directly.
   friend class LIBPROTOBUF_EXPORT upb::google_opensource::GMR_Handlers;
   friend class LIBPROTOBUF_EXPORT upb::google_opensource::GMR_Handlers;

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

@@ -231,7 +231,7 @@ class RepeatedFieldRefIterator
   const void* data_;
   const void* data_;
   const RepeatedFieldAccessor* accessor_;
   const RepeatedFieldAccessor* accessor_;
   void* iterator_;
   void* iterator_;
-  scoped_ptr<AccessorValueType> scratch_space_;
+  google::protobuf::scoped_ptr<AccessorValueType> scratch_space_;
 };
 };
 
 
 // TypeTraits that maps the type parameter T of RepeatedFieldRef or
 // TypeTraits that maps the type parameter T of RepeatedFieldRef or

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

@@ -686,7 +686,7 @@ TEST(RepeatedFieldReflectionTest, RepeatedFieldRefDynamicMessage) {
       desc->FindFieldByName("repeated_int32");
       desc->FindFieldByName("repeated_int32");
 
 
   DynamicMessageFactory factory;
   DynamicMessageFactory factory;
-  scoped_ptr<Message> dynamic_message(factory.GetPrototype(desc)->New());
+  google::protobuf::scoped_ptr<Message> dynamic_message(factory.GetPrototype(desc)->New());
   const Reflection* refl = dynamic_message->GetReflection();
   const Reflection* refl = dynamic_message->GetReflection();
 
 
   MutableRepeatedFieldRef<int32> rf_int32 =
   MutableRepeatedFieldRef<int32> rf_int32 =

+ 2 - 0
src/google/protobuf/stubs/common.h

@@ -267,6 +267,8 @@ static const uint64 kuint64max = GOOGLE_ULONGLONG(0xFFFFFFFFFFFFFFFF);
 #endif
 #endif
 
 
 #define GOOGLE_GUARDED_BY(x)
 #define GOOGLE_GUARDED_BY(x)
+#define GOOGLE_FALLTHROUGH_INTENDED
+#define GOOGLE_ATTRIBUTE_COLD
 
 
 // x86 and x86-64 can perform unaligned loads/stores directly.
 // x86 and x86-64 can perform unaligned loads/stores directly.
 #if defined(_M_X64) || defined(__x86_64__) || \
 #if defined(_M_X64) || defined(__x86_64__) || \

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

@@ -271,7 +271,7 @@ class LIBPROTOBUF_EXPORT TextFormat {
 
 
     bool print_message_fields_in_index_order_;
     bool print_message_fields_in_index_order_;
 
 
-    scoped_ptr<const FieldValuePrinter> default_field_value_printer_;
+    google::protobuf::scoped_ptr<const FieldValuePrinter> default_field_value_printer_;
     typedef map<const FieldDescriptor*,
     typedef map<const FieldDescriptor*,
                 const FieldValuePrinter*> CustomPrinterMap;
                 const FieldValuePrinter*> CustomPrinterMap;
     CustomPrinterMap custom_printers_;
     CustomPrinterMap custom_printers_;

+ 1 - 0
src/google/protobuf/unittest.proto

@@ -41,6 +41,7 @@ syntax = "proto2";
 option cc_generic_services = true;     // auto-added
 option cc_generic_services = true;     // auto-added
 option java_generic_services = true;   // auto-added
 option java_generic_services = true;   // auto-added
 option py_generic_services = true;     // auto-added
 option py_generic_services = true;     // auto-added
+option cc_enable_arenas = true;
 
 
 import "google/protobuf/unittest_import.proto";
 import "google/protobuf/unittest_import.proto";
 
 

+ 1 - 0
src/google/protobuf/unittest_arena.proto

@@ -34,6 +34,7 @@ import "google/protobuf/unittest_no_arena_import.proto";
 
 
 package proto2_arena_unittest;
 package proto2_arena_unittest;
 
 
+option cc_enable_arenas = true;
 
 
 message NestedMessage {
 message NestedMessage {
   optional int32 d = 1;
   optional int32 d = 1;

+ 1 - 0
src/google/protobuf/unittest_import.proto

@@ -43,6 +43,7 @@ syntax = "proto2";
 package protobuf_unittest_import;
 package protobuf_unittest_import;
 
 
 option optimize_for = SPEED;
 option optimize_for = SPEED;
+option cc_enable_arenas = true;
 
 
 // Exercise the java_package option.
 // Exercise the java_package option.
 option java_package = "com.google.protobuf.test";
 option java_package = "com.google.protobuf.test";

+ 1 - 0
src/google/protobuf/unittest_mset.proto

@@ -37,6 +37,7 @@
 syntax = "proto2";
 syntax = "proto2";
 package protobuf_unittest;
 package protobuf_unittest;
 
 
+option cc_enable_arenas = true;
 option optimize_for = SPEED;
 option optimize_for = SPEED;
 
 
 // A message with message_set_wire_format.
 // A message with message_set_wire_format.

+ 1 - 0
src/google/protobuf/unittest_no_arena.proto

@@ -43,6 +43,7 @@ syntax = "proto2";
 option cc_generic_services = true;     // auto-added
 option cc_generic_services = true;     // auto-added
 option java_generic_services = true;   // auto-added
 option java_generic_services = true;   // auto-added
 option py_generic_services = true;     // auto-added
 option py_generic_services = true;     // auto-added
+option cc_enable_arenas = false;
 
 
 import "google/protobuf/unittest_import.proto";
 import "google/protobuf/unittest_import.proto";
 import "google/protobuf/unittest_arena.proto";
 import "google/protobuf/unittest_arena.proto";

+ 1 - 0
src/google/protobuf/unittest_proto3_arena.proto

@@ -30,6 +30,7 @@
 
 
 syntax = "proto3";
 syntax = "proto3";
 
 
+option cc_enable_arenas = true;
 
 
 import "google/protobuf/unittest_import.proto";
 import "google/protobuf/unittest_import.proto";
 
 

Některé soubory nejsou zobrazeny, neboť je v těchto rozdílových datech změněno mnoho souborů